summaryrefslogtreecommitdiff
path: root/boost/asio
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:11:01 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2019-12-05 15:11:01 +0900
commit3fdc3e5ee96dca5b11d1694975a65200787eab86 (patch)
tree5c1733853892b8397d67706fa453a9bd978d2102 /boost/asio
parent88e602c57797660ebe0f9e15dbd64c1ff16dead3 (diff)
downloadboost-3fdc3e5ee96dca5b11d1694975a65200787eab86.tar.gz
boost-3fdc3e5ee96dca5b11d1694975a65200787eab86.tar.bz2
boost-3fdc3e5ee96dca5b11d1694975a65200787eab86.zip
Imported Upstream version 1.66.0upstream/1.66.0
Diffstat (limited to 'boost/asio')
-rw-r--r--boost/asio/associated_allocator.hpp133
-rw-r--r--boost/asio/associated_executor.hpp151
-rw-r--r--boost/asio/async_result.hpp169
-rw-r--r--boost/asio/basic_datagram_socket.hpp187
-rw-r--r--boost/asio/basic_deadline_timer.hpp178
-rw-r--r--boost/asio/basic_io_object.hpp114
-rw-r--r--boost/asio/basic_raw_socket.hpp186
-rw-r--r--boost/asio/basic_seq_packet_socket.hpp141
-rw-r--r--boost/asio/basic_serial_port.hpp89
-rw-r--r--boost/asio/basic_signal_set.hpp81
-rw-r--r--boost/asio/basic_socket.hpp456
-rw-r--r--boost/asio/basic_socket_acceptor.hpp1061
-rw-r--r--boost/asio/basic_socket_iostream.hpp238
-rw-r--r--boost/asio/basic_socket_streambuf.hpp682
-rw-r--r--boost/asio/basic_stream_socket.hpp161
-rw-r--r--boost/asio/basic_streambuf.hpp113
-rw-r--r--boost/asio/basic_streambuf_fwd.hpp3
-rw-r--r--boost/asio/basic_waitable_timer.hpp282
-rw-r--r--boost/asio/bind_executor.hpp613
-rw-r--r--boost/asio/buffer.hpp2289
-rw-r--r--boost/asio/buffered_read_stream.hpp39
-rw-r--r--boost/asio/buffered_stream.hpp30
-rw-r--r--boost/asio/buffered_write_stream.hpp39
-rw-r--r--boost/asio/buffers_iterator.hpp80
-rw-r--r--boost/asio/connect.hpp686
-rw-r--r--boost/asio/coroutine.hpp12
-rw-r--r--boost/asio/datagram_socket_service.hpp156
-rw-r--r--boost/asio/deadline_timer_service.hpp36
-rw-r--r--boost/asio/defer.hpp109
-rw-r--r--boost/asio/detail/addressof.hpp40
-rw-r--r--boost/asio/detail/bind_handler.hpp479
-rw-r--r--boost/asio/detail/buffer_sequence_adapter.hpp261
-rw-r--r--boost/asio/detail/call_stack.hpp2
-rw-r--r--boost/asio/detail/chrono.hpp68
-rw-r--r--boost/asio/detail/completion_handler.hpp12
-rw-r--r--boost/asio/detail/concurrency_hint.hpp94
-rw-r--r--boost/asio/detail/conditionally_enabled_event.hpp114
-rw-r--r--boost/asio/detail/conditionally_enabled_mutex.hpp151
-rw-r--r--boost/asio/detail/config.hpp323
-rw-r--r--boost/asio/detail/consuming_buffers.hpp450
-rw-r--r--boost/asio/detail/cstddef.hpp33
-rw-r--r--boost/asio/detail/cstdint.hpp14
-rw-r--r--boost/asio/detail/deadline_timer_service.hpp77
-rw-r--r--boost/asio/detail/descriptor_ops.hpp4
-rw-r--r--boost/asio/detail/descriptor_read_op.hpp23
-rw-r--r--boost/asio/detail/descriptor_write_op.hpp23
-rw-r--r--boost/asio/detail/dev_poll_reactor.hpp28
-rw-r--r--boost/asio/detail/epoll_reactor.hpp39
-rw-r--r--boost/asio/detail/executor_op.hpp86
-rw-r--r--boost/asio/detail/functional.hpp (renamed from boost/asio/detail/function.hpp)18
-rw-r--r--boost/asio/detail/gcc_arm_fenced_block.hpp2
-rw-r--r--boost/asio/detail/gcc_hppa_fenced_block.hpp2
-rw-r--r--boost/asio/detail/gcc_sync_fenced_block.hpp2
-rw-r--r--boost/asio/detail/gcc_x86_fenced_block.hpp2
-rw-r--r--boost/asio/detail/global.hpp54
-rw-r--r--boost/asio/detail/handler_alloc_helpers.hpp159
-rw-r--r--boost/asio/detail/handler_cont_helpers.hpp2
-rw-r--r--boost/asio/detail/handler_invoke_helpers.hpp2
-rw-r--r--boost/asio/detail/handler_tracking.hpp97
-rw-r--r--boost/asio/detail/handler_type_requirements.hpp150
-rw-r--r--boost/asio/detail/handler_work.hpp97
-rw-r--r--boost/asio/detail/impl/buffer_sequence_adapter.ipp10
-rw-r--r--boost/asio/detail/impl/descriptor_ops.ipp23
-rw-r--r--boost/asio/detail/impl/dev_poll_reactor.hpp19
-rw-r--r--boost/asio/detail/impl/dev_poll_reactor.ipp45
-rw-r--r--boost/asio/detail/impl/epoll_reactor.hpp19
-rw-r--r--boost/asio/detail/impl/epoll_reactor.ipp164
-rw-r--r--boost/asio/detail/impl/handler_tracking.ipp105
-rw-r--r--boost/asio/detail/impl/kqueue_reactor.hpp23
-rw-r--r--boost/asio/detail/impl/kqueue_reactor.ipp88
-rw-r--r--boost/asio/detail/impl/null_event.ipp76
-rw-r--r--boost/asio/detail/impl/posix_event.ipp12
-rw-r--r--boost/asio/detail/impl/posix_thread.ipp10
-rw-r--r--boost/asio/detail/impl/reactive_descriptor_service.ipp19
-rw-r--r--boost/asio/detail/impl/reactive_serial_port_service.ipp11
-rw-r--r--boost/asio/detail/impl/reactive_socket_service_base.ipp37
-rw-r--r--boost/asio/detail/impl/resolver_service_base.ipp82
-rw-r--r--boost/asio/detail/impl/scheduler.ipp (renamed from boost/asio/detail/impl/task_io_service.ipp)235
-rw-r--r--boost/asio/detail/impl/select_reactor.hpp19
-rw-r--r--boost/asio/detail/impl/select_reactor.ipp65
-rw-r--r--boost/asio/detail/impl/service_registry.hpp64
-rw-r--r--boost/asio/detail/impl/service_registry.ipp67
-rw-r--r--boost/asio/detail/impl/signal_set_service.ipp56
-rw-r--r--boost/asio/detail/impl/socket_ops.ipp153
-rw-r--r--boost/asio/detail/impl/strand_executor_service.hpp181
-rw-r--r--boost/asio/detail/impl/strand_executor_service.ipp126
-rw-r--r--boost/asio/detail/impl/strand_service.hpp24
-rw-r--r--boost/asio/detail/impl/strand_service.ipp27
-rw-r--r--boost/asio/detail/impl/task_io_service.hpp80
-rw-r--r--boost/asio/detail/impl/timer_queue_ptime.ipp15
-rw-r--r--boost/asio/detail/impl/win_event.ipp5
-rw-r--r--boost/asio/detail/impl/win_iocp_handle_service.ipp44
-rw-r--r--boost/asio/detail/impl/win_iocp_io_context.hpp (renamed from boost/asio/detail/impl/win_iocp_io_service.hpp)71
-rw-r--r--boost/asio/detail/impl/win_iocp_io_context.ipp (renamed from boost/asio/detail/impl/win_iocp_io_service.ipp)112
-rw-r--r--boost/asio/detail/impl/win_iocp_serial_port_service.ipp7
-rw-r--r--boost/asio/detail/impl/win_iocp_socket_service_base.ipp90
-rw-r--r--boost/asio/detail/impl/win_object_handle_service.ipp36
-rw-r--r--boost/asio/detail/impl/win_thread.ipp7
-rw-r--r--boost/asio/detail/impl/win_tss_ptr.ipp4
-rw-r--r--boost/asio/detail/impl/winrt_ssocket_service_base.ipp55
-rw-r--r--boost/asio/detail/impl/winrt_timer_scheduler.hpp19
-rw-r--r--boost/asio/detail/impl/winrt_timer_scheduler.ipp16
-rw-r--r--boost/asio/detail/io_control.hpp50
-rw-r--r--boost/asio/detail/is_buffer_sequence.hpp241
-rw-r--r--boost/asio/detail/is_executor.hpp128
-rw-r--r--boost/asio/detail/kqueue_reactor.hpp36
-rw-r--r--boost/asio/detail/macos_fenced_block.hpp1
-rw-r--r--boost/asio/detail/memory.hpp41
-rw-r--r--boost/asio/detail/null_event.hpp20
-rw-r--r--boost/asio/detail/null_fenced_block.hpp2
-rw-r--r--boost/asio/detail/null_global.hpp61
-rw-r--r--boost/asio/detail/null_reactor.hpp17
-rw-r--r--boost/asio/detail/null_socket_service.hpp46
-rw-r--r--boost/asio/detail/null_thread.hpp6
-rw-r--r--boost/asio/detail/object_pool.hpp25
-rw-r--r--boost/asio/detail/operation.hpp4
-rw-r--r--boost/asio/detail/pop_options.hpp4
-rw-r--r--boost/asio/detail/posix_event.hpp33
-rw-r--r--boost/asio/detail/posix_global.hpp82
-rw-r--r--boost/asio/detail/posix_thread.hpp4
-rw-r--r--boost/asio/detail/push_options.hpp9
-rw-r--r--boost/asio/detail/reactive_descriptor_service.hpp104
-rw-r--r--boost/asio/detail/reactive_null_buffers_op.hpp14
-rw-r--r--boost/asio/detail/reactive_serial_port_service.hpp16
-rw-r--r--boost/asio/detail/reactive_socket_accept_op.hpp119
-rw-r--r--boost/asio/detail/reactive_socket_connect_op.hpp19
-rw-r--r--boost/asio/detail/reactive_socket_recv_op.hpp26
-rw-r--r--boost/asio/detail/reactive_socket_recvfrom_op.hpp19
-rw-r--r--boost/asio/detail/reactive_socket_recvmsg_op.hpp21
-rw-r--r--boost/asio/detail/reactive_socket_send_op.hpp34
-rw-r--r--boost/asio/detail/reactive_socket_sendto_op.hpp21
-rw-r--r--boost/asio/detail/reactive_socket_service.hpp128
-rw-r--r--boost/asio/detail/reactive_socket_service_base.hpp129
-rw-r--r--boost/asio/detail/reactive_wait_op.hpp92
-rw-r--r--boost/asio/detail/reactor.hpp2
-rw-r--r--boost/asio/detail/reactor_fwd.hpp2
-rw-r--r--boost/asio/detail/reactor_op.hpp8
-rw-r--r--boost/asio/detail/recycling_allocator.hpp106
-rw-r--r--boost/asio/detail/resolve_endpoint_op.hpp47
-rw-r--r--boost/asio/detail/resolve_op.hpp96
-rw-r--r--boost/asio/detail/resolve_query_op.hpp136
-rw-r--r--boost/asio/detail/resolver_service.hpp58
-rw-r--r--boost/asio/detail/resolver_service_base.hpp47
-rw-r--r--boost/asio/detail/scheduler.hpp (renamed from boost/asio/detail/task_io_service.hpp)100
-rw-r--r--boost/asio/detail/scheduler_operation.hpp (renamed from boost/asio/detail/task_io_service_operation.hpp)34
-rw-r--r--boost/asio/detail/scheduler_thread_info.hpp (renamed from boost/asio/detail/task_io_service_thread_info.hpp)18
-rw-r--r--boost/asio/detail/scoped_ptr.hpp8
-rw-r--r--boost/asio/detail/select_reactor.hpp40
-rw-r--r--boost/asio/detail/service_registry.hpp86
-rw-r--r--boost/asio/detail/shared_ptr.hpp40
-rw-r--r--boost/asio/detail/signal_handler.hpp12
-rw-r--r--boost/asio/detail/signal_set_service.hpp25
-rw-r--r--boost/asio/detail/socket_ops.hpp13
-rw-r--r--boost/asio/detail/socket_types.hpp6
-rw-r--r--boost/asio/detail/solaris_fenced_block.hpp1
-rw-r--r--boost/asio/detail/std_global.hpp72
-rw-r--r--boost/asio/detail/std_thread.hpp6
-rw-r--r--boost/asio/detail/strand_executor_service.hpp140
-rw-r--r--boost/asio/detail/strand_service.hpp18
-rw-r--r--boost/asio/detail/string_view.hpp47
-rw-r--r--boost/asio/detail/thread.hpp12
-rw-r--r--boost/asio/detail/thread_context.hpp44
-rw-r--r--boost/asio/detail/thread_group.hpp91
-rw-r--r--boost/asio/detail/thread_info_base.hpp11
-rw-r--r--boost/asio/detail/timer_queue.hpp29
-rw-r--r--boost/asio/detail/timer_queue_ptime.hpp14
-rw-r--r--boost/asio/detail/timer_scheduler.hpp2
-rw-r--r--boost/asio/detail/timer_scheduler_fwd.hpp2
-rw-r--r--boost/asio/detail/type_traits.hpp22
-rw-r--r--boost/asio/detail/variadic_templates.hpp98
-rw-r--r--boost/asio/detail/wait_handler.hpp12
-rw-r--r--boost/asio/detail/weak_ptr.hpp40
-rw-r--r--boost/asio/detail/win_event.hpp21
-rw-r--r--boost/asio/detail/win_fenced_block.hpp1
-rw-r--r--boost/asio/detail/win_global.hpp75
-rw-r--r--boost/asio/detail/win_iocp_handle_read_op.hpp10
-rw-r--r--boost/asio/detail/win_iocp_handle_service.hpp39
-rw-r--r--boost/asio/detail/win_iocp_handle_write_op.hpp10
-rw-r--r--boost/asio/detail/win_iocp_io_context.hpp (renamed from boost/asio/detail/win_iocp_io_service.hpp)75
-rw-r--r--boost/asio/detail/win_iocp_null_buffers_op.hpp14
-rw-r--r--boost/asio/detail/win_iocp_operation.hpp13
-rw-r--r--boost/asio/detail/win_iocp_overlapped_op.hpp10
-rw-r--r--boost/asio/detail/win_iocp_overlapped_ptr.hpp25
-rw-r--r--boost/asio/detail/win_iocp_serial_port_service.hpp16
-rw-r--r--boost/asio/detail/win_iocp_socket_accept_op.hpp140
-rw-r--r--boost/asio/detail/win_iocp_socket_connect_op.hpp15
-rw-r--r--boost/asio/detail/win_iocp_socket_recv_op.hpp10
-rw-r--r--boost/asio/detail/win_iocp_socket_recvfrom_op.hpp10
-rw-r--r--boost/asio/detail/win_iocp_socket_recvmsg_op.hpp10
-rw-r--r--boost/asio/detail/win_iocp_socket_send_op.hpp10
-rw-r--r--boost/asio/detail/win_iocp_socket_service.hpp135
-rw-r--r--boost/asio/detail/win_iocp_socket_service_base.hpp153
-rw-r--r--boost/asio/detail/win_iocp_wait_op.hpp123
-rw-r--r--boost/asio/detail/win_object_handle_service.hpp21
-rw-r--r--boost/asio/detail/win_thread.hpp4
-rw-r--r--boost/asio/detail/winapp_thread.hpp (renamed from boost/asio/detail/winapi_thread.hpp)44
-rw-r--r--boost/asio/detail/wince_thread.hpp126
-rw-r--r--boost/asio/detail/winrt_async_manager.hpp26
-rw-r--r--boost/asio/detail/winrt_resolve_op.hpp25
-rw-r--r--boost/asio/detail/winrt_resolver_service.hpp65
-rw-r--r--boost/asio/detail/winrt_socket_connect_op.hpp12
-rw-r--r--boost/asio/detail/winrt_socket_recv_op.hpp10
-rw-r--r--boost/asio/detail/winrt_socket_send_op.hpp10
-rw-r--r--boost/asio/detail/winrt_ssocket_service.hpp22
-rw-r--r--boost/asio/detail/winrt_ssocket_service_base.hpp32
-rw-r--r--boost/asio/detail/winrt_timer_scheduler.hpp20
-rw-r--r--boost/asio/detail/winrt_utils.hpp6
-rw-r--r--boost/asio/detail/work_dispatcher.hpp74
-rw-r--r--boost/asio/dispatch.hpp110
-rw-r--r--boost/asio/error.hpp16
-rw-r--r--boost/asio/execution_context.hpp413
-rw-r--r--boost/asio/executor.hpp343
-rw-r--r--boost/asio/executor_work_guard.hpp171
-rw-r--r--boost/asio/generic/detail/impl/endpoint.ipp3
-rw-r--r--boost/asio/handler_invoke_hook.hpp6
-rw-r--r--boost/asio/handler_type.hpp82
-rw-r--r--boost/asio/high_resolution_timer.hpp25
-rw-r--r--boost/asio/impl/buffered_read_stream.hpp99
-rw-r--r--boost/asio/impl/buffered_write_stream.hpp109
-rw-r--r--boost/asio/impl/connect.hpp666
-rw-r--r--boost/asio/impl/defer.hpp79
-rw-r--r--boost/asio/impl/dispatch.hpp80
-rw-r--r--boost/asio/impl/execution_context.hpp109
-rw-r--r--boost/asio/impl/execution_context.ipp84
-rw-r--r--boost/asio/impl/executor.hpp388
-rw-r--r--boost/asio/impl/executor.ipp (renamed from boost/asio/ssl/basic_context.hpp)28
-rw-r--r--boost/asio/impl/handler_alloc_hook.ipp37
-rw-r--r--boost/asio/impl/io_context.hpp345
-rw-r--r--boost/asio/impl/io_context.ipp176
-rw-r--r--boost/asio/impl/io_service.hpp156
-rw-r--r--boost/asio/impl/io_service.ipp157
-rw-r--r--boost/asio/impl/post.hpp79
-rw-r--r--boost/asio/impl/read.hpp718
-rw-r--r--boost/asio/impl/read_at.hpp514
-rw-r--r--boost/asio/impl/read_until.hpp763
-rw-r--r--boost/asio/impl/serial_port_base.ipp58
-rw-r--r--boost/asio/impl/spawn.hpp308
-rw-r--r--boost/asio/impl/src.hpp14
-rw-r--r--boost/asio/impl/system_context.hpp (renamed from boost/asio/ssl/context_service.hpp)26
-rw-r--r--boost/asio/impl/system_context.ipp75
-rw-r--r--boost/asio/impl/system_executor.hpp87
-rw-r--r--boost/asio/impl/thread_pool.hpp129
-rw-r--r--boost/asio/impl/thread_pool.ipp78
-rw-r--r--boost/asio/impl/use_future.hpp947
-rw-r--r--boost/asio/impl/write.hpp805
-rw-r--r--boost/asio/impl/write_at.hpp581
-rw-r--r--boost/asio/io_context.hpp878
-rw-r--r--boost/asio/io_context_strand.hpp384
-rw-r--r--boost/asio/io_service.hpp747
-rw-r--r--boost/asio/io_service_strand.hpp20
-rw-r--r--boost/asio/ip/address.hpp96
-rw-r--r--boost/asio/ip/address_v4.hpp132
-rw-r--r--boost/asio/ip/address_v4_iterator.hpp164
-rw-r--r--boost/asio/ip/address_v4_range.hpp136
-rw-r--r--boost/asio/ip/address_v6.hpp116
-rw-r--r--boost/asio/ip/address_v6_iterator.hpp185
-rw-r--r--boost/asio/ip/address_v6_range.hpp131
-rw-r--r--boost/asio/ip/bad_address_cast.hpp50
-rw-r--r--boost/asio/ip/basic_endpoint.hpp8
-rw-r--r--boost/asio/ip/basic_resolver.hpp890
-rw-r--r--boost/asio/ip/basic_resolver_entry.hpp25
-rw-r--r--boost/asio/ip/basic_resolver_iterator.hpp128
-rw-r--r--boost/asio/ip/basic_resolver_results.hpp313
-rw-r--r--boost/asio/ip/detail/endpoint.hpp2
-rw-r--r--boost/asio/ip/detail/impl/endpoint.ipp13
-rw-r--r--boost/asio/ip/detail/socket_option.hpp33
-rw-r--r--boost/asio/ip/impl/address.hpp40
-rw-r--r--boost/asio/ip/impl/address.ipp100
-rw-r--r--boost/asio/ip/impl/address_v4.hpp40
-rw-r--r--boost/asio/ip/impl/address_v4.ipp118
-rw-r--r--boost/asio/ip/impl/address_v6.hpp40
-rw-r--r--boost/asio/ip/impl/address_v6.ipp116
-rw-r--r--boost/asio/ip/impl/basic_endpoint.hpp14
-rw-r--r--boost/asio/ip/impl/network_v4.hpp56
-rw-r--r--boost/asio/ip/impl/network_v4.ipp217
-rw-r--r--boost/asio/ip/impl/network_v6.hpp55
-rw-r--r--boost/asio/ip/impl/network_v6.ipp186
-rw-r--r--boost/asio/ip/multicast.hpp14
-rw-r--r--boost/asio/ip/network_v4.hpp263
-rw-r--r--boost/asio/ip/network_v6.hpp237
-rw-r--r--boost/asio/ip/resolver_base.hpp131
-rw-r--r--boost/asio/ip/resolver_query_base.hpp91
-rw-r--r--boost/asio/ip/resolver_service.hpp70
-rw-r--r--boost/asio/ip/tcp.hpp4
-rw-r--r--boost/asio/ip/unicast.hpp4
-rw-r--r--boost/asio/ip/v6_only.hpp4
-rw-r--r--boost/asio/is_executor.hpp48
-rw-r--r--boost/asio/local/connect_pair.hpp42
-rw-r--r--boost/asio/local/detail/impl/endpoint.ipp3
-rw-r--r--boost/asio/packaged_task.hpp128
-rw-r--r--boost/asio/placeholders.hpp30
-rw-r--r--boost/asio/posix/basic_descriptor.hpp182
-rw-r--r--boost/asio/posix/basic_stream_descriptor.hpp28
-rw-r--r--boost/asio/posix/descriptor.hpp646
-rw-r--r--boost/asio/posix/descriptor_base.hpp39
-rw-r--r--boost/asio/posix/stream_descriptor.hpp327
-rw-r--r--boost/asio/posix/stream_descriptor_service.hpp105
-rw-r--r--boost/asio/post.hpp109
-rw-r--r--boost/asio/raw_socket_service.hpp156
-rw-r--r--boost/asio/read.hpp338
-rw-r--r--boost/asio/read_at.hpp17
-rw-r--r--boost/asio/read_until.hpp967
-rw-r--r--boost/asio/seq_packet_socket_service.hpp142
-rw-r--r--boost/asio/serial_port.hpp737
-rw-r--r--boost/asio/serial_port_base.hpp20
-rw-r--r--boost/asio/serial_port_service.hpp84
-rw-r--r--boost/asio/signal_set.hpp423
-rw-r--r--boost/asio/signal_set_service.hpp54
-rw-r--r--boost/asio/socket_acceptor_service.hpp160
-rw-r--r--boost/asio/socket_base.hpp129
-rw-r--r--boost/asio/spawn.hpp105
-rw-r--r--boost/asio/ssl.hpp3
-rw-r--r--boost/asio/ssl/context.hpp93
-rw-r--r--boost/asio/ssl/detail/buffered_handshake_op.hpp48
-rw-r--r--boost/asio/ssl/detail/engine.hpp22
-rw-r--r--boost/asio/ssl/detail/handshake_op.hpp8
-rw-r--r--boost/asio/ssl/detail/impl/engine.ipp45
-rw-r--r--boost/asio/ssl/detail/impl/openssl_init.ipp5
-rw-r--r--boost/asio/ssl/detail/io.hpp53
-rw-r--r--boost/asio/ssl/detail/openssl_init.hpp2
-rw-r--r--boost/asio/ssl/detail/password_callback.hpp12
-rw-r--r--boost/asio/ssl/detail/read_op.hpp10
-rw-r--r--boost/asio/ssl/detail/shutdown_op.hpp8
-rw-r--r--boost/asio/ssl/detail/stream_core.hpp44
-rw-r--r--boost/asio/ssl/detail/verify_callback.hpp8
-rw-r--r--boost/asio/ssl/detail/write_op.hpp10
-rw-r--r--boost/asio/ssl/impl/context.hpp18
-rw-r--r--boost/asio/ssl/impl/context.ipp167
-rw-r--r--boost/asio/ssl/impl/rfc2818_verification.ipp18
-rw-r--r--boost/asio/ssl/old/basic_context.hpp436
-rw-r--r--boost/asio/ssl/old/context_service.hpp176
-rw-r--r--boost/asio/ssl/old/detail/openssl_context_service.hpp396
-rw-r--r--boost/asio/ssl/old/detail/openssl_operation.hpp526
-rw-r--r--boost/asio/ssl/old/detail/openssl_stream_service.hpp573
-rw-r--r--boost/asio/ssl/old/stream.hpp503
-rw-r--r--boost/asio/ssl/old/stream_service.hpp186
-rw-r--r--boost/asio/ssl/rfc2818_verification.hpp18
-rw-r--r--boost/asio/ssl/stream.hpp173
-rw-r--r--boost/asio/ssl/stream_service.hpp42
-rw-r--r--boost/asio/ssl/verify_context.hpp10
-rw-r--r--boost/asio/steady_timer.hpp25
-rw-r--r--boost/asio/strand.hpp382
-rw-r--r--boost/asio/stream_socket_service.hpp142
-rw-r--r--boost/asio/system_context.hpp80
-rw-r--r--boost/asio/system_executor.hpp131
-rw-r--r--boost/asio/system_timer.hpp21
-rw-r--r--boost/asio/thread_pool.hpp234
-rw-r--r--boost/asio/ts/buffer.hpp24
-rw-r--r--boost/asio/ts/executor.hpp35
-rw-r--r--boost/asio/ts/internet.hpp40
-rw-r--r--boost/asio/ts/io_context.hpp20
-rw-r--r--boost/asio/ts/net.hpp26
-rw-r--r--boost/asio/ts/netfwd.hpp199
-rw-r--r--boost/asio/ts/socket.hpp27
-rw-r--r--boost/asio/ts/timer.hpp26
-rw-r--r--boost/asio/use_future.hpp77
-rw-r--r--boost/asio/uses_executor.hpp73
-rw-r--r--boost/asio/version.hpp2
-rw-r--r--boost/asio/wait_traits.hpp17
-rw-r--r--boost/asio/waitable_timer_service.hpp80
-rw-r--r--boost/asio/windows/basic_handle.hpp50
-rw-r--r--boost/asio/windows/basic_object_handle.hpp22
-rw-r--r--boost/asio/windows/basic_random_access_handle.hpp28
-rw-r--r--boost/asio/windows/basic_stream_handle.hpp28
-rw-r--r--boost/asio/windows/object_handle.hpp347
-rw-r--r--boost/asio/windows/object_handle_service.hpp44
-rw-r--r--boost/asio/windows/overlapped_handle.hpp333
-rw-r--r--boost/asio/windows/overlapped_ptr.hpp10
-rw-r--r--boost/asio/windows/random_access_handle.hpp345
-rw-r--r--boost/asio/windows/random_access_handle_service.hpp66
-rw-r--r--boost/asio/windows/stream_handle.hpp329
-rw-r--r--boost/asio/windows/stream_handle_service.hpp64
-rw-r--r--boost/asio/write.hpp331
-rw-r--r--boost/asio/write_at.hpp17
374 files changed, 32894 insertions, 12780 deletions
diff --git a/boost/asio/associated_allocator.hpp b/boost/asio/associated_allocator.hpp
new file mode 100644
index 0000000000..b9ef5a452f
--- /dev/null
+++ b/boost/asio/associated_allocator.hpp
@@ -0,0 +1,133 @@
+//
+// associated_allocator.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_ASSOCIATED_ALLOCATOR_HPP
+#define BOOST_ASIO_ASSOCIATED_ALLOCATOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <memory>
+#include <boost/asio/detail/type_traits.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename>
+struct associated_allocator_check
+{
+ typedef void type;
+};
+
+template <typename T, typename E, typename = void>
+struct associated_allocator_impl
+{
+ typedef E type;
+
+ static type get(const T&, const E& e) BOOST_ASIO_NOEXCEPT
+ {
+ return e;
+ }
+};
+
+template <typename T, typename E>
+struct associated_allocator_impl<T, E,
+ typename associated_allocator_check<typename T::allocator_type>::type>
+{
+ typedef typename T::allocator_type type;
+
+ static type get(const T& t, const E&) BOOST_ASIO_NOEXCEPT
+ {
+ return t.get_allocator();
+ }
+};
+
+} // namespace detail
+
+/// Traits type used to obtain the allocator 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
+ * Allocator shall be a type meeting the Allocator requirements.
+ *
+ * Specialisations shall meet the following requirements, where @c t is a const
+ * reference to an object of type @c T, and @c a is an object of type @c
+ * Allocator.
+ *
+ * @li Provide a nested typedef @c type that identifies a type meeting the
+ * Allocator requirements.
+ *
+ * @li Provide a noexcept static member function named @c get, callable as @c
+ * get(t) and with return type @c type.
+ *
+ * @li Provide a noexcept static member function named @c get, callable as @c
+ * get(t,a) and with return type @c type.
+ */
+template <typename T, typename Allocator = std::allocator<void> >
+struct associated_allocator
+{
+ /// 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 a.
+ static type get(const T& t,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return detail::associated_allocator_impl<T, Allocator>::get(t, a);
+ }
+};
+
+/// Helper function to obtain an object's associated allocator.
+/**
+ * @returns <tt>associated_allocator<T>::get(t)</tt>
+ */
+template <typename T>
+inline typename associated_allocator<T>::type
+get_associated_allocator(const T& t) BOOST_ASIO_NOEXCEPT
+{
+ return associated_allocator<T>::get(t);
+}
+
+/// Helper function to obtain an object's associated allocator.
+/**
+ * @returns <tt>associated_allocator<T, Allocator>::get(t, a)</tt>
+ */
+template <typename T, typename Allocator>
+inline typename associated_allocator<T, Allocator>::type
+get_associated_allocator(const T& t, const Allocator& a) BOOST_ASIO_NOEXCEPT
+{
+ return associated_allocator<T, Allocator>::get(t, a);
+}
+
+#if defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
+
+template <typename T, typename Allocator = std::allocator<void> >
+using associated_allocator_t
+ = typename associated_allocator<T, Allocator>::type;
+
+#endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_ASSOCIATED_ALLOCATOR_HPP
diff --git a/boost/asio/associated_executor.hpp b/boost/asio/associated_executor.hpp
new file mode 100644
index 0000000000..d0347afcfa
--- /dev/null
+++ b/boost/asio/associated_executor.hpp
@@ -0,0 +1,151 @@
+//
+// associated_executor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_ASSOCIATED_EXECUTOR_HPP
+#define BOOST_ASIO_ASSOCIATED_EXECUTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/is_executor.hpp>
+#include <boost/asio/system_executor.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename>
+struct associated_executor_check
+{
+ typedef void type;
+};
+
+template <typename T, typename E, typename = void>
+struct associated_executor_impl
+{
+ typedef E type;
+
+ static type get(const T&, const E& e) BOOST_ASIO_NOEXCEPT
+ {
+ return e;
+ }
+};
+
+template <typename T, typename E>
+struct associated_executor_impl<T, E,
+ typename associated_executor_check<typename T::executor_type>::type>
+{
+ typedef typename T::executor_type type;
+
+ static type get(const T& t, const E&) BOOST_ASIO_NOEXCEPT
+ {
+ return t.get_executor();
+ }
+};
+
+} // namespace detail
+
+/// Traits type used to obtain the 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.
+ *
+ * @li Provide a noexcept static member function named @c get, callable as @c
+ * get(t,e) and with return type @c type.
+ */
+template <typename T, typename Executor = system_executor>
+struct associated_executor
+{
+ /// If @c T has a nested type @c executor_type, <tt>T::executor_type</tt>.
+ /// Otherwise @c Executor.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef see_below type;
+#else // defined(GENERATING_DOCUMENTATION)
+ typedef typename detail::associated_executor_impl<T, Executor>::type type;
+#endif // defined(GENERATING_DOCUMENTATION)
+
+ /// 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()) BOOST_ASIO_NOEXCEPT
+ {
+ return detail::associated_executor_impl<T, Executor>::get(t, ex);
+ }
+};
+
+/// Helper function to obtain an object's associated executor.
+/**
+ * @returns <tt>associated_executor<T>::get(t)</tt>
+ */
+template <typename T>
+inline typename associated_executor<T>::type
+get_associated_executor(const T& t) BOOST_ASIO_NOEXCEPT
+{
+ return associated_executor<T>::get(t);
+}
+
+/// Helper function to obtain an object's associated executor.
+/**
+ * @returns <tt>associated_executor<T, Executor>::get(t, ex)</tt>
+ */
+template <typename T, typename Executor>
+inline typename associated_executor<T, Executor>::type
+get_associated_executor(const T& t, const Executor& ex,
+ typename enable_if<is_executor<
+ Executor>::value>::type* = 0) BOOST_ASIO_NOEXCEPT
+{
+ return associated_executor<T, Executor>::get(t, ex);
+}
+
+/// Helper function to obtain an object's associated executor.
+/**
+ * @returns <tt>associated_executor<T, typename
+ * ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt>
+ */
+template <typename T, typename ExecutionContext>
+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) BOOST_ASIO_NOEXCEPT
+{
+ return associated_executor<T,
+ typename ExecutionContext::executor_type>::get(t, ctx.get_executor());
+}
+
+#if defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
+
+template <typename T, typename Executor = system_executor>
+using associated_executor_t = typename associated_executor<T, Executor>::type;
+
+#endif // defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_ASSOCIATED_EXECUTOR_HPP
diff --git a/boost/asio/async_result.hpp b/boost/asio/async_result.hpp
index 6290b8462a..f49f2eb2e0 100644
--- a/boost/asio/async_result.hpp
+++ b/boost/asio/async_result.hpp
@@ -16,6 +16,7 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/handler_type.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -25,10 +26,93 @@ namespace asio {
/// 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.
+ */
+#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+template <typename CompletionToken, typename Signature>
+#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+template <typename CompletionToken, typename Signature = void>
+#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+class async_result
+{
+public:
+#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ /// 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;
+#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ // For backward compatibility, determine the concrete completion handler type
+ // by using the legacy handler_type trait.
+ typedef typename handler_type<CompletionToken, Signature>::type
+ completion_handler_type;
+
+ // For backward compatibility, determine the initiating function return type
+ // using the legacy single-parameter version of async_result.
+ typedef typename async_result<completion_handler_type>::type return_type;
+#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+
+ /// 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)
+#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ // No data members to initialise.
+#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ : legacy_result_(h)
+#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ {
+ (void)h;
+ }
+
+ /// Obtain the value to be returned from the initiating function.
+ return_type get()
+ {
+#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ // Nothing to do.
+#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ return legacy_result_.get();
+#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ }
+
+private:
+ async_result(const async_result&) BOOST_ASIO_DELETED;
+ async_result& operator=(const async_result&) BOOST_ASIO_DELETED;
+
+#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ // No data members.
+#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ async_result<completion_handler_type> legacy_result_;
+#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+};
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+/// (Deprecated: Use two-parameter version of async_result.) An interface for
+/// customising the behaviour of an initiating function.
+/**
* This template may be specialised for user-defined handler types.
*/
template <typename Handler>
-class async_result
+class async_result<Handler>
{
public:
/// The return type of the initiating function.
@@ -50,29 +134,65 @@ public:
}
};
-namespace detail {
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-// Helper template to deduce the true type of a handler, capture a local copy
-// of the handler, and then create an async_result for the handler.
-template <typename Handler, typename Signature>
-struct async_result_init
+/// 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, typename Signature>
+struct async_completion
{
- explicit async_result_init(BOOST_ASIO_MOVE_ARG(Handler) orig_handler)
- : handler(BOOST_ASIO_MOVE_CAST(Handler)(orig_handler)),
- result(handler)
+ /// The real handler type to be used for the asynchronous operation.
+ typedef typename boost::asio::async_result<
+ typename decay<CompletionToken>::type,
+ Signature>::completion_handler_type completion_handler_type;
+
+#if defined(BOOST_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(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ explicit async_completion(typename decay<CompletionToken>::type& token)
+ : completion_handler(token),
+ result(completion_handler)
{
}
- typename handler_type<Handler, Signature>::type handler;
- async_result<typename handler_type<Handler, Signature>::type> result;
+ explicit async_completion(const typename decay<CompletionToken>::type& token)
+ : completion_handler(token),
+ result(completion_handler)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// A copy of, or reference to, a real handler object.
+#if defined(BOOST_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(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ completion_handler_type completion_handler;
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// The result of the asynchronous operation's initiating function.
+ async_result<typename decay<CompletionToken>::type, Signature> result;
};
-template <typename Handler, typename Signature>
-struct async_result_type_helper
+namespace detail {
+
+template <typename CompletionToken, typename Signature>
+struct async_result_helper
+ : async_result<typename decay<CompletionToken>::type, Signature>
{
- typedef typename async_result<
- typename handler_type<Handler, Signature>::type
- >::type type;
};
} // namespace detail
@@ -82,15 +202,22 @@ struct async_result_type_helper
#include <boost/asio/detail/pop_options.hpp>
#if defined(GENERATING_DOCUMENTATION)
-# define BOOST_ASIO_INITFN_RESULT_TYPE(h, sig) \
+# define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \
void_or_deduced
#elif defined(_MSC_VER) && (_MSC_VER < 1500)
-# define BOOST_ASIO_INITFN_RESULT_TYPE(h, sig) \
- typename ::boost::asio::detail::async_result_type_helper<h, sig>::type
+# define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \
+ typename ::boost::asio::detail::async_result_helper< \
+ ct, sig>::return_type
+#define BOOST_ASIO_HANDLER_TYPE(ct, sig) \
+ typename ::boost::asio::detail::async_result_helper< \
+ ct, sig>::completion_handler_type
#else
-# define BOOST_ASIO_INITFN_RESULT_TYPE(h, sig) \
+# define BOOST_ASIO_INITFN_RESULT_TYPE(ct, sig) \
+ typename ::boost::asio::async_result< \
+ typename ::boost::asio::decay<ct>::type, sig>::return_type
+#define BOOST_ASIO_HANDLER_TYPE(ct, sig) \
typename ::boost::asio::async_result< \
- typename ::boost::asio::handler_type<h, sig>::type>::type
+ typename ::boost::asio::decay<ct>::type, sig>::completion_handler_type
#endif
#endif // BOOST_ASIO_ASYNC_RESULT_HPP
diff --git a/boost/asio/basic_datagram_socket.hpp b/boost/asio/basic_datagram_socket.hpp
index 22801ee081..c2aa00bf48 100644
--- a/boost/asio/basic_datagram_socket.hpp
+++ b/boost/asio/basic_datagram_socket.hpp
@@ -18,12 +18,15 @@
#include <boost/asio/detail/config.hpp>
#include <cstddef>
#include <boost/asio/basic_socket.hpp>
-#include <boost/asio/datagram_socket_service.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/datagram_socket_service.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
@@ -38,18 +41,19 @@ namespace asio {
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
-template <typename Protocol,
- typename DatagramSocketService = datagram_socket_service<Protocol> >
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= datagram_socket_service<Protocol>)>
class basic_datagram_socket
- : public basic_socket<Protocol, DatagramSocketService>
+ : public basic_socket<Protocol BOOST_ASIO_SVC_TARG>
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// socket.
- typedef typename DatagramSocketService::native_handle_type native_type;
-
/// The native representation of a socket.
- typedef typename DatagramSocketService::native_handle_type native_handle_type;
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename basic_socket<
+ Protocol BOOST_ASIO_SVC_TARG>::native_handle_type native_handle_type;
+#endif
/// The protocol type.
typedef Protocol protocol_type;
@@ -62,12 +66,12 @@ public:
* This constructor creates a datagram socket without opening it. The open()
* function must be called before data can be sent or received on the socket.
*
- * @param io_service The io_service object that the datagram socket will use
+ * @param io_context The io_context object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*/
- explicit basic_datagram_socket(boost::asio::io_service& io_service)
- : basic_socket<Protocol, DatagramSocketService>(io_service)
+ explicit basic_datagram_socket(boost::asio::io_context& io_context)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context)
{
}
@@ -75,7 +79,7 @@ public:
/**
* This constructor creates and opens a datagram socket.
*
- * @param io_service The io_service object that the datagram socket will use
+ * @param io_context The io_context object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*
@@ -83,9 +87,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_datagram_socket(boost::asio::io_service& io_service,
+ basic_datagram_socket(boost::asio::io_context& io_context,
const protocol_type& protocol)
- : basic_socket<Protocol, DatagramSocketService>(io_service, protocol)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, protocol)
{
}
@@ -96,7 +100,7 @@ public:
* to the specified endpoint on the local machine. The protocol used is the
* protocol associated with the given endpoint.
*
- * @param io_service The io_service object that the datagram socket will use
+ * @param io_context The io_context object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*
@@ -105,9 +109,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_datagram_socket(boost::asio::io_service& io_service,
+ basic_datagram_socket(boost::asio::io_context& io_context,
const endpoint_type& endpoint)
- : basic_socket<Protocol, DatagramSocketService>(io_service, endpoint)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, endpoint)
{
}
@@ -116,7 +120,7 @@ public:
* This constructor creates a datagram socket object to hold an existing
* native socket.
*
- * @param io_service The io_service object that the datagram socket will use
+ * @param io_context The io_context object that the datagram socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*
@@ -126,10 +130,10 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_datagram_socket(boost::asio::io_service& io_service,
+ basic_datagram_socket(boost::asio::io_context& io_context,
const protocol_type& protocol, const native_handle_type& native_socket)
- : basic_socket<Protocol, DatagramSocketService>(
- io_service, protocol, native_socket)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(
+ io_context, protocol, native_socket)
{
}
@@ -142,11 +146,10 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_datagram_socket(io_service&) constructor.
+ * constructed using the @c basic_datagram_socket(io_context&) constructor.
*/
basic_datagram_socket(basic_datagram_socket&& other)
- : basic_socket<Protocol, DatagramSocketService>(
- BOOST_ASIO_MOVE_CAST(basic_datagram_socket)(other))
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
{
}
@@ -159,12 +162,11 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_datagram_socket(io_service&) constructor.
+ * constructed using the @c basic_datagram_socket(io_context&) constructor.
*/
basic_datagram_socket& operator=(basic_datagram_socket&& other)
{
- basic_socket<Protocol, DatagramSocketService>::operator=(
- BOOST_ASIO_MOVE_CAST(basic_datagram_socket)(other));
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
return *this;
}
@@ -177,15 +179,13 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_datagram_socket(io_service&) constructor.
+ * constructed using the @c basic_datagram_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename DatagramSocketService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
basic_datagram_socket(
- basic_datagram_socket<Protocol1, DatagramSocketService1>&& other,
+ basic_datagram_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
- : basic_socket<Protocol, DatagramSocketService>(
- BOOST_ASIO_MOVE_CAST2(basic_datagram_socket<
- Protocol1, DatagramSocketService1>)(other))
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
{
}
@@ -199,20 +199,27 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_datagram_socket(io_service&) constructor.
+ * constructed using the @c basic_datagram_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename DatagramSocketService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
typename enable_if<is_convertible<Protocol1, Protocol>::value,
basic_datagram_socket>::type& operator=(
- basic_datagram_socket<Protocol1, DatagramSocketService1>&& other)
+ basic_datagram_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other)
{
- basic_socket<Protocol, DatagramSocketService>::operator=(
- BOOST_ASIO_MOVE_CAST2(basic_datagram_socket<
- Protocol1, DatagramSocketService1>)(other));
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Destroys the socket.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_datagram_socket()
+ {
+ }
+
/// Send some data on a connected socket.
/**
* This function is used to send data on the datagram socket. The function
@@ -318,7 +325,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -343,8 +350,18 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous send on a connected socket.
@@ -369,7 +386,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -386,8 +403,18 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(this->get_implementation(),
+ buffers, flags, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Send a datagram to the specified endpoint.
@@ -501,7 +528,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
@@ -526,9 +553,20 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send_to(
this->get_implementation(), buffers, destination, 0,
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send_to(
+ this->get_implementation(), buffers, destination, 0,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous send.
@@ -556,7 +594,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename ConstBufferSequence, typename WriteHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
@@ -569,9 +607,20 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send_to(
this->get_implementation(), buffers, destination, flags,
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send_to(
+ this->get_implementation(), buffers, destination, flags,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Receive some data on a connected socket.
@@ -683,7 +732,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -709,8 +758,18 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous receive on a connected socket.
@@ -735,7 +794,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -752,8 +811,18 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, flags, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Receive a datagram with the endpoint of the sender.
@@ -870,7 +939,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
@@ -892,9 +961,20 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, 0,
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive_from(
+ this->get_implementation(), buffers, sender_endpoint, 0,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous receive.
@@ -924,7 +1004,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename MutableBufferSequence, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
@@ -937,9 +1017,20 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, flags,
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive_from(
+ this->get_implementation(), buffers, sender_endpoint, flags,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
};
diff --git a/boost/asio/basic_deadline_timer.hpp b/boost/asio/basic_deadline_timer.hpp
index 930370046b..f7179a853e 100644
--- a/boost/asio/basic_deadline_timer.hpp
+++ b/boost/asio/basic_deadline_timer.hpp
@@ -22,10 +22,17 @@
#include <cstddef>
#include <boost/asio/basic_io_object.hpp>
-#include <boost/asio/deadline_timer_service.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
+#include <boost/asio/time_traits.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/deadline_timer_service.hpp>
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/detail/deadline_timer_service.hpp>
+# define BOOST_ASIO_SVC_T detail::deadline_timer_service<TimeTraits>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
#include <boost/asio/detail/push_options.hpp>
@@ -51,7 +58,7 @@ namespace asio {
* Performing a blocking wait:
* @code
* // Construct a timer without setting an expiry time.
- * boost::asio::deadline_timer timer(io_service);
+ * boost::asio::deadline_timer timer(io_context);
*
* // Set an expiry time relative to now.
* timer.expires_from_now(boost::posix_time::seconds(5));
@@ -74,7 +81,7 @@ namespace asio {
* ...
*
* // Construct a timer with an absolute expiry time.
- * boost::asio::deadline_timer timer(io_service,
+ * boost::asio::deadline_timer timer(io_context,
* boost::posix_time::time_from_string("2005-12-07 23:59:59.000"));
*
* // Start an asynchronous wait.
@@ -121,12 +128,15 @@ namespace asio {
* it contains the value boost::asio::error::operation_aborted.
*/
template <typename Time,
- typename TimeTraits = boost::asio::time_traits<Time>,
- typename TimerService = deadline_timer_service<Time, TimeTraits> >
+ typename TimeTraits = boost::asio::time_traits<Time>
+ BOOST_ASIO_SVC_TPARAM_DEF2(= deadline_timer_service<Time, TimeTraits>)>
class basic_deadline_timer
- : public basic_io_object<TimerService>
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>
{
public:
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
+
/// The time traits type.
typedef TimeTraits traits_type;
@@ -142,11 +152,11 @@ public:
* expires_at() or expires_from_now() functions must be called to set an
* expiry time before the timer can be waited on.
*
- * @param io_service The io_service object that the timer will use to dispatch
+ * @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
*/
- explicit basic_deadline_timer(boost::asio::io_service& io_service)
- : basic_io_object<TimerService>(io_service)
+ explicit basic_deadline_timer(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
}
@@ -154,18 +164,18 @@ public:
/**
* This constructor creates a timer and sets the expiry time.
*
- * @param io_service The io_service object that the timer will use to dispatch
+ * @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, expressed
* as an absolute time.
*/
- basic_deadline_timer(boost::asio::io_service& io_service,
+ basic_deadline_timer(boost::asio::io_context& io_context,
const time_type& expiry_time)
- : basic_io_object<TimerService>(io_service)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
boost::system::error_code ec;
- this->service.expires_at(this->implementation, expiry_time, ec);
+ this->get_service().expires_at(this->get_implementation(), expiry_time, ec);
boost::asio::detail::throw_error(ec, "expires_at");
}
@@ -173,21 +183,105 @@ public:
/**
* This constructor creates a timer and sets the expiry time.
*
- * @param io_service The io_service object that the timer will use to dispatch
+ * @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, relative to
* now.
*/
- basic_deadline_timer(boost::asio::io_service& io_service,
+ basic_deadline_timer(boost::asio::io_context& io_context,
const duration_type& expiry_time)
- : basic_io_object<TimerService>(io_service)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
boost::system::error_code ec;
- this->service.expires_from_now(this->implementation, expiry_time, ec);
+ this->get_service().expires_from_now(
+ this->get_implementation(), expiry_time, ec);
boost::asio::detail::throw_error(ec, "expires_from_now");
}
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_deadline_timer from another.
+ /**
+ * This constructor moves a timer from one object to another.
+ *
+ * @param other The other basic_deadline_timer 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_deadline_timer(io_context&) constructor.
+ */
+ basic_deadline_timer(basic_deadline_timer&& other)
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_deadline_timer from another.
+ /**
+ * This assignment operator moves a timer from one object to another. Cancels
+ * any outstanding asynchronous operations associated with the target object.
+ *
+ * @param other The other basic_deadline_timer 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_deadline_timer(io_context&) constructor.
+ */
+ basic_deadline_timer& operator=(basic_deadline_timer&& other)
+ {
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroys the timer.
+ /**
+ * This function destroys the timer, cancelling any outstanding asynchronous
+ * wait operations associated with the timer as if by calling @c cancel.
+ */
+ ~basic_deadline_timer()
+ {
+ }
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ // These functions are provided by basic_io_object<>.
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
+ }
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
/// Cancel any asynchronous operations that are waiting on the timer.
/**
* This function forces the completion of any pending asynchronous wait
@@ -213,7 +307,7 @@ public:
std::size_t cancel()
{
boost::system::error_code ec;
- std::size_t s = this->service.cancel(this->implementation, ec);
+ std::size_t s = this->get_service().cancel(this->get_implementation(), ec);
boost::asio::detail::throw_error(ec, "cancel");
return s;
}
@@ -242,7 +336,7 @@ public:
*/
std::size_t cancel(boost::system::error_code& ec)
{
- return this->service.cancel(this->implementation, ec);
+ return this->get_service().cancel(this->get_implementation(), ec);
}
/// Cancels one asynchronous operation that is waiting on the timer.
@@ -272,7 +366,8 @@ public:
std::size_t cancel_one()
{
boost::system::error_code ec;
- std::size_t s = this->service.cancel_one(this->implementation, ec);
+ std::size_t s = this->get_service().cancel_one(
+ this->get_implementation(), ec);
boost::asio::detail::throw_error(ec, "cancel_one");
return s;
}
@@ -303,7 +398,7 @@ public:
*/
std::size_t cancel_one(boost::system::error_code& ec)
{
- return this->service.cancel_one(this->implementation, ec);
+ return this->get_service().cancel_one(this->get_implementation(), ec);
}
/// Get the timer's expiry time as an absolute time.
@@ -313,7 +408,7 @@ public:
*/
time_type expires_at() const
{
- return this->service.expires_at(this->implementation);
+ return this->get_service().expires_at(this->get_implementation());
}
/// Set the timer's expiry time as an absolute time.
@@ -341,8 +436,8 @@ public:
std::size_t expires_at(const time_type& expiry_time)
{
boost::system::error_code ec;
- std::size_t s = this->service.expires_at(
- this->implementation, expiry_time, ec);
+ std::size_t s = this->get_service().expires_at(
+ this->get_implementation(), expiry_time, ec);
boost::asio::detail::throw_error(ec, "expires_at");
return s;
}
@@ -372,7 +467,8 @@ public:
std::size_t expires_at(const time_type& expiry_time,
boost::system::error_code& ec)
{
- return this->service.expires_at(this->implementation, expiry_time, ec);
+ return this->get_service().expires_at(
+ this->get_implementation(), expiry_time, ec);
}
/// Get the timer's expiry time relative to now.
@@ -382,7 +478,7 @@ public:
*/
duration_type expires_from_now() const
{
- return this->service.expires_from_now(this->implementation);
+ return this->get_service().expires_from_now(this->get_implementation());
}
/// Set the timer's expiry time relative to now.
@@ -410,8 +506,8 @@ public:
std::size_t expires_from_now(const duration_type& expiry_time)
{
boost::system::error_code ec;
- std::size_t s = this->service.expires_from_now(
- this->implementation, expiry_time, ec);
+ std::size_t s = this->get_service().expires_from_now(
+ this->get_implementation(), expiry_time, ec);
boost::asio::detail::throw_error(ec, "expires_from_now");
return s;
}
@@ -441,8 +537,8 @@ public:
std::size_t expires_from_now(const duration_type& expiry_time,
boost::system::error_code& ec)
{
- return this->service.expires_from_now(
- this->implementation, expiry_time, ec);
+ return this->get_service().expires_from_now(
+ this->get_implementation(), expiry_time, ec);
}
/// Perform a blocking wait on the timer.
@@ -455,7 +551,7 @@ public:
void wait()
{
boost::system::error_code ec;
- this->service.wait(this->implementation, ec);
+ this->get_service().wait(this->get_implementation(), ec);
boost::asio::detail::throw_error(ec, "wait");
}
@@ -468,7 +564,7 @@ public:
*/
void wait(boost::system::error_code& ec)
{
- this->service.wait(this->implementation, ec);
+ this->get_service().wait(this->get_implementation(), ec);
}
/// Start an asynchronous wait on the timer.
@@ -493,7 +589,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename WaitHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
@@ -504,8 +600,18 @@ public:
// not meet the documented type requirements for a WaitHandler.
BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
- return this->service.async_wait(this->implementation,
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_wait(this->get_implementation(),
BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_wait(this->get_implementation(),
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
};
@@ -514,6 +620,10 @@ public:
#include <boost/asio/detail/pop_options.hpp>
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# undef BOOST_ASIO_SVC_T
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
// || defined(GENERATING_DOCUMENTATION)
diff --git a/boost/asio/basic_io_object.hpp b/boost/asio/basic_io_object.hpp
index d490a161f6..87653b5c53 100644
--- a/boost/asio/basic_io_object.hpp
+++ b/boost/asio/basic_io_object.hpp
@@ -16,7 +16,7 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -68,17 +68,43 @@ public:
/// The underlying implementation type of I/O object.
typedef typename service_type::implementation_type implementation_type;
- /// Get the io_service associated with the object.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
/**
- * This function may be used to obtain the io_service object that the I/O
+ * This function may be used to obtain the io_context object that the I/O
* object uses to dispatch handlers for asynchronous operations.
*
- * @return A reference to the io_service object that the I/O object will use
+ * @return A reference to the io_context object that the I/O object will use
* to dispatch handlers. Ownership is not transferred to the caller.
*/
- boost::asio::io_service& get_io_service()
+ boost::asio::io_context& get_io_context()
{
- return service.get_io_service();
+ return service_.get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return service_.get_io_context();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// The type of the executor associated with the object.
+ typedef boost::asio::io_context::executor_type executor_type;
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return service_.get_io_context().get_executor();
}
protected:
@@ -87,10 +113,10 @@ protected:
* Performs:
* @code get_service().construct(get_implementation()); @endcode
*/
- explicit basic_io_object(boost::asio::io_service& io_service)
- : service(boost::asio::use_service<IoObjectService>(io_service))
+ explicit basic_io_object(boost::asio::io_context& io_context)
+ : service_(boost::asio::use_service<IoObjectService>(io_context))
{
- service.construct(implementation);
+ service_.construct(implementation_);
}
#if defined(GENERATING_DOCUMENTATION)
@@ -127,47 +153,42 @@ protected:
*/
~basic_io_object()
{
- service.destroy(implementation);
+ service_.destroy(implementation_);
}
/// Get the service associated with the I/O object.
service_type& get_service()
{
- return service;
+ return service_;
}
/// Get the service associated with the I/O object.
const service_type& get_service() const
{
- return service;
+ return service_;
}
- /// (Deprecated: Use get_service().) The service associated with the I/O
- /// object.
- /**
- * @note Available only for services that do not support movability.
- */
- service_type& service;
-
/// Get the underlying implementation of the I/O object.
implementation_type& get_implementation()
{
- return implementation;
+ return implementation_;
}
/// Get the underlying implementation of the I/O object.
const implementation_type& get_implementation() const
{
- return implementation;
+ return implementation_;
}
- /// (Deprecated: Use get_implementation().) The underlying implementation of
- /// the I/O object.
- implementation_type implementation;
-
private:
basic_io_object(const basic_io_object&);
basic_io_object& operator=(const basic_io_object&);
+
+ // The service associated with the I/O object.
+ service_type& service_;
+
+ /// The underlying implementation of the I/O object.
+ implementation_type implementation_;
};
#if defined(BOOST_ASIO_HAS_MOVE)
@@ -179,43 +200,57 @@ public:
typedef IoObjectService service_type;
typedef typename service_type::implementation_type implementation_type;
- boost::asio::io_service& get_io_service()
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ boost::asio::io_context& get_io_context()
+ {
+ return service_->get_io_context();
+ }
+
+ boost::asio::io_context& get_io_service()
{
- return service_->get_io_service();
+ return service_->get_io_context();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ typedef boost::asio::io_context::executor_type executor_type;
+
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return service_->get_io_context().get_executor();
}
protected:
- explicit basic_io_object(boost::asio::io_service& io_service)
- : service_(&boost::asio::use_service<IoObjectService>(io_service))
+ explicit basic_io_object(boost::asio::io_context& io_context)
+ : service_(&boost::asio::use_service<IoObjectService>(io_context))
{
- service_->construct(implementation);
+ service_->construct(implementation_);
}
basic_io_object(basic_io_object&& other)
: service_(&other.get_service())
{
- service_->move_construct(implementation, other.implementation);
+ service_->move_construct(implementation_, other.implementation_);
}
template <typename IoObjectService1>
basic_io_object(IoObjectService1& other_service,
typename IoObjectService1::implementation_type& other_implementation)
: service_(&boost::asio::use_service<IoObjectService>(
- other_service.get_io_service()))
+ other_service.get_io_context()))
{
- service_->converting_move_construct(implementation,
+ service_->converting_move_construct(implementation_,
other_service, other_implementation);
}
~basic_io_object()
{
- service_->destroy(implementation);
+ service_->destroy(implementation_);
}
basic_io_object& operator=(basic_io_object&& other)
{
- service_->move_assign(implementation,
- *other.service_, other.implementation);
+ service_->move_assign(implementation_,
+ *other.service_, other.implementation_);
service_ = other.service_;
return *this;
}
@@ -232,21 +267,20 @@ protected:
implementation_type& get_implementation()
{
- return implementation;
+ return implementation_;
}
const implementation_type& get_implementation() const
{
- return implementation;
+ return implementation_;
}
- implementation_type implementation;
-
private:
basic_io_object(const basic_io_object&);
void operator=(const basic_io_object&);
IoObjectService* service_;
+ implementation_type implementation_;
};
#endif // defined(BOOST_ASIO_HAS_MOVE)
diff --git a/boost/asio/basic_raw_socket.hpp b/boost/asio/basic_raw_socket.hpp
index 85f8f42642..09058de224 100644
--- a/boost/asio/basic_raw_socket.hpp
+++ b/boost/asio/basic_raw_socket.hpp
@@ -22,7 +22,10 @@
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/raw_socket_service.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/raw_socket_service.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
#include <boost/asio/detail/push_options.hpp>
@@ -38,18 +41,19 @@ namespace asio {
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
-template <typename Protocol,
- typename RawSocketService = raw_socket_service<Protocol> >
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= raw_socket_service<Protocol>)>
class basic_raw_socket
- : public basic_socket<Protocol, RawSocketService>
+ : public basic_socket<Protocol BOOST_ASIO_SVC_TARG>
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// socket.
- typedef typename RawSocketService::native_handle_type native_type;
-
/// The native representation of a socket.
- typedef typename RawSocketService::native_handle_type native_handle_type;
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename basic_socket<
+ Protocol BOOST_ASIO_SVC_TARG>::native_handle_type native_handle_type;
+#endif
/// The protocol type.
typedef Protocol protocol_type;
@@ -62,12 +66,12 @@ public:
* This constructor creates a raw socket without opening it. The open()
* function must be called before data can be sent or received on the socket.
*
- * @param io_service The io_service object that the raw socket will use
+ * @param io_context The io_context object that the raw socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*/
- explicit basic_raw_socket(boost::asio::io_service& io_service)
- : basic_socket<Protocol, RawSocketService>(io_service)
+ explicit basic_raw_socket(boost::asio::io_context& io_context)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context)
{
}
@@ -75,7 +79,7 @@ public:
/**
* This constructor creates and opens a raw socket.
*
- * @param io_service The io_service object that the raw socket will use
+ * @param io_context The io_context object that the raw socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*
@@ -83,9 +87,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_raw_socket(boost::asio::io_service& io_service,
+ basic_raw_socket(boost::asio::io_context& io_context,
const protocol_type& protocol)
- : basic_socket<Protocol, RawSocketService>(io_service, protocol)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, protocol)
{
}
@@ -96,7 +100,7 @@ public:
* to the specified endpoint on the local machine. The protocol used is the
* protocol associated with the given endpoint.
*
- * @param io_service The io_service object that the raw socket will use
+ * @param io_context The io_context object that the raw socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*
@@ -105,9 +109,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_raw_socket(boost::asio::io_service& io_service,
+ basic_raw_socket(boost::asio::io_context& io_context,
const endpoint_type& endpoint)
- : basic_socket<Protocol, RawSocketService>(io_service, endpoint)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, endpoint)
{
}
@@ -116,7 +120,7 @@ public:
* This constructor creates a raw socket object to hold an existing
* native socket.
*
- * @param io_service The io_service object that the raw socket will use
+ * @param io_context The io_context object that the raw socket will use
* to dispatch handlers for any asynchronous operations performed on the
* socket.
*
@@ -126,10 +130,10 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_raw_socket(boost::asio::io_service& io_service,
+ basic_raw_socket(boost::asio::io_context& io_context,
const protocol_type& protocol, const native_handle_type& native_socket)
- : basic_socket<Protocol, RawSocketService>(
- io_service, protocol, native_socket)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(
+ io_context, protocol, native_socket)
{
}
@@ -142,11 +146,10 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_raw_socket(io_service&) constructor.
+ * constructed using the @c basic_raw_socket(io_context&) constructor.
*/
basic_raw_socket(basic_raw_socket&& other)
- : basic_socket<Protocol, RawSocketService>(
- BOOST_ASIO_MOVE_CAST(basic_raw_socket)(other))
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
{
}
@@ -158,12 +161,11 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_raw_socket(io_service&) constructor.
+ * constructed using the @c basic_raw_socket(io_context&) constructor.
*/
basic_raw_socket& operator=(basic_raw_socket&& other)
{
- basic_socket<Protocol, RawSocketService>::operator=(
- BOOST_ASIO_MOVE_CAST(basic_raw_socket)(other));
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
return *this;
}
@@ -175,14 +177,12 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_raw_socket(io_service&) constructor.
+ * constructed using the @c basic_raw_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename RawSocketService1>
- basic_raw_socket(basic_raw_socket<Protocol1, RawSocketService1>&& other,
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ basic_raw_socket(basic_raw_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
- : basic_socket<Protocol, RawSocketService>(
- BOOST_ASIO_MOVE_CAST2(basic_raw_socket<
- Protocol1, RawSocketService1>)(other))
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
{
}
@@ -194,20 +194,27 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_raw_socket(io_service&) constructor.
+ * constructed using the @c basic_raw_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename RawSocketService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
typename enable_if<is_convertible<Protocol1, Protocol>::value,
basic_raw_socket>::type& operator=(
- basic_raw_socket<Protocol1, RawSocketService1>&& other)
+ basic_raw_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other)
{
- basic_socket<Protocol, RawSocketService>::operator=(
- BOOST_ASIO_MOVE_CAST2(basic_raw_socket<
- Protocol1, RawSocketService1>)(other));
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Destroys the socket.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_raw_socket()
+ {
+ }
+
/// Send some data on a connected socket.
/**
* This function is used to send data on the raw socket. The function call
@@ -310,7 +317,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -335,8 +342,18 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous send on a connected socket.
@@ -361,7 +378,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -378,8 +395,18 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(this->get_implementation(),
+ buffers, flags, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Send raw data to the specified endpoint.
@@ -493,7 +520,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
@@ -518,8 +545,18 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send_to(this->get_implementation(),
buffers, destination, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send_to(this->get_implementation(),
+ buffers, destination, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous send.
@@ -547,7 +584,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename ConstBufferSequence, typename WriteHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
@@ -560,9 +597,20 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send_to(
this->get_implementation(), buffers, destination, flags,
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send_to(
+ this->get_implementation(), buffers, destination, flags,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Receive some data on a connected socket.
@@ -674,7 +722,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -700,8 +748,18 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous receive on a connected socket.
@@ -726,7 +784,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -743,8 +801,18 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, flags, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Receive raw data with the endpoint of the sender.
@@ -861,7 +929,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
@@ -883,9 +951,20 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, 0,
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive_from(
+ this->get_implementation(), buffers, sender_endpoint, 0,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous receive.
@@ -915,7 +994,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename MutableBufferSequence, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
@@ -928,9 +1007,20 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive_from(
this->get_implementation(), buffers, sender_endpoint, flags,
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive_from(
+ this->get_implementation(), buffers, sender_endpoint, flags,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
};
diff --git a/boost/asio/basic_seq_packet_socket.hpp b/boost/asio/basic_seq_packet_socket.hpp
index c8e43f77d6..a48a5b847e 100644
--- a/boost/asio/basic_seq_packet_socket.hpp
+++ b/boost/asio/basic_seq_packet_socket.hpp
@@ -21,7 +21,10 @@
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/seq_packet_socket_service.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/seq_packet_socket_service.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
#include <boost/asio/detail/push_options.hpp>
@@ -37,19 +40,19 @@ namespace asio {
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
-template <typename Protocol,
- typename SeqPacketSocketService = seq_packet_socket_service<Protocol> >
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= seq_packet_socket_service<Protocol>)>
class basic_seq_packet_socket
- : public basic_socket<Protocol, SeqPacketSocketService>
+ : public basic_socket<Protocol BOOST_ASIO_SVC_TARG>
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// socket.
- typedef typename SeqPacketSocketService::native_handle_type native_type;
-
/// The native representation of a socket.
- typedef typename SeqPacketSocketService::native_handle_type
- native_handle_type;
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename basic_socket<
+ Protocol BOOST_ASIO_SVC_TARG>::native_handle_type native_handle_type;
+#endif
/// The protocol type.
typedef Protocol protocol_type;
@@ -63,12 +66,12 @@ public:
* socket needs to be opened and then connected or accepted before data can
* be sent or received on it.
*
- * @param io_service The io_service object that the sequenced packet socket
+ * @param io_context The io_context object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
*/
- explicit basic_seq_packet_socket(boost::asio::io_service& io_service)
- : basic_socket<Protocol, SeqPacketSocketService>(io_service)
+ explicit basic_seq_packet_socket(boost::asio::io_context& io_context)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context)
{
}
@@ -78,7 +81,7 @@ public:
* needs to be connected or accepted before data can be sent or received on
* it.
*
- * @param io_service The io_service object that the sequenced packet socket
+ * @param io_context The io_context object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
*
@@ -86,9 +89,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_seq_packet_socket(boost::asio::io_service& io_service,
+ basic_seq_packet_socket(boost::asio::io_context& io_context,
const protocol_type& protocol)
- : basic_socket<Protocol, SeqPacketSocketService>(io_service, protocol)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, protocol)
{
}
@@ -99,7 +102,7 @@ public:
* it bound to the specified endpoint on the local machine. The protocol used
* is the protocol associated with the given endpoint.
*
- * @param io_service The io_service object that the sequenced packet socket
+ * @param io_context The io_context object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
*
@@ -108,9 +111,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_seq_packet_socket(boost::asio::io_service& io_service,
+ basic_seq_packet_socket(boost::asio::io_context& io_context,
const endpoint_type& endpoint)
- : basic_socket<Protocol, SeqPacketSocketService>(io_service, endpoint)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, endpoint)
{
}
@@ -119,7 +122,7 @@ public:
* This constructor creates a sequenced packet socket object to hold an
* existing native socket.
*
- * @param io_service The io_service object that the sequenced packet socket
+ * @param io_context The io_context object that the sequenced packet socket
* will use to dispatch handlers for any asynchronous operations performed on
* the socket.
*
@@ -129,10 +132,10 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_seq_packet_socket(boost::asio::io_service& io_service,
+ basic_seq_packet_socket(boost::asio::io_context& io_context,
const protocol_type& protocol, const native_handle_type& native_socket)
- : basic_socket<Protocol, SeqPacketSocketService>(
- io_service, protocol, native_socket)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(
+ io_context, protocol, native_socket)
{
}
@@ -146,11 +149,10 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_seq_packet_socket(io_service&) constructor.
+ * constructed using the @c basic_seq_packet_socket(io_context&) constructor.
*/
basic_seq_packet_socket(basic_seq_packet_socket&& other)
- : basic_socket<Protocol, SeqPacketSocketService>(
- BOOST_ASIO_MOVE_CAST(basic_seq_packet_socket)(other))
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
{
}
@@ -163,12 +165,11 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_seq_packet_socket(io_service&) constructor.
+ * constructed using the @c basic_seq_packet_socket(io_context&) constructor.
*/
basic_seq_packet_socket& operator=(basic_seq_packet_socket&& other)
{
- basic_socket<Protocol, SeqPacketSocketService>::operator=(
- BOOST_ASIO_MOVE_CAST(basic_seq_packet_socket)(other));
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
return *this;
}
@@ -182,15 +183,13 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_seq_packet_socket(io_service&) constructor.
+ * constructed using the @c basic_seq_packet_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename SeqPacketSocketService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
basic_seq_packet_socket(
- basic_seq_packet_socket<Protocol1, SeqPacketSocketService1>&& other,
+ basic_seq_packet_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
- : basic_socket<Protocol, SeqPacketSocketService>(
- BOOST_ASIO_MOVE_CAST2(basic_seq_packet_socket<
- Protocol1, SeqPacketSocketService1>)(other))
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
{
}
@@ -204,20 +203,27 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_seq_packet_socket(io_service&) constructor.
+ * constructed using the @c basic_seq_packet_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename SeqPacketSocketService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
typename enable_if<is_convertible<Protocol1, Protocol>::value,
basic_seq_packet_socket>::type& operator=(
- basic_seq_packet_socket<Protocol1, SeqPacketSocketService1>&& other)
+ basic_seq_packet_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other)
{
- basic_socket<Protocol, SeqPacketSocketService>::operator=(
- BOOST_ASIO_MOVE_CAST2(basic_seq_packet_socket<
- Protocol1, SeqPacketSocketService1>)(other));
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Destroys the socket.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_seq_packet_socket()
+ {
+ }
+
/// Send some data on the socket.
/**
* This function is used to send data on the sequenced packet socket. The
@@ -300,7 +306,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To send a single data buffer use the @ref buffer function as follows:
@@ -322,8 +328,18 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, flags, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(this->get_implementation(),
+ buffers, flags, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Receive some data on the socket.
@@ -360,8 +376,13 @@ public:
socket_base::message_flags& out_flags)
{
boost::system::error_code ec;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
std::size_t s = this->get_service().receive(
this->get_implementation(), buffers, 0, out_flags, ec);
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ std::size_t s = this->get_service().receive_with_flags(
+ this->get_implementation(), buffers, 0, out_flags, ec);
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
boost::asio::detail::throw_error(ec, "receive");
return s;
}
@@ -407,8 +428,13 @@ public:
socket_base::message_flags& out_flags)
{
boost::system::error_code ec;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
std::size_t s = this->get_service().receive(
this->get_implementation(), buffers, in_flags, out_flags, ec);
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ std::size_t s = this->get_service().receive_with_flags(
+ this->get_implementation(), buffers, in_flags, out_flags, ec);
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
boost::asio::detail::throw_error(ec, "receive");
return s;
}
@@ -441,8 +467,13 @@ public:
socket_base::message_flags in_flags,
socket_base::message_flags& out_flags, boost::system::error_code& ec)
{
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().receive(this->get_implementation(),
buffers, in_flags, out_flags, ec);
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().receive_with_flags(this->get_implementation(),
+ buffers, in_flags, out_flags, ec);
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous receive.
@@ -471,7 +502,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
@@ -494,9 +525,20 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(
this->get_implementation(), buffers, 0, out_flags,
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive_with_flags(
+ this->get_implementation(), buffers, 0, out_flags,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous receive.
@@ -527,7 +569,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To receive into a single data buffer use the @ref buffer function as
@@ -553,9 +595,20 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(
this->get_implementation(), buffers, in_flags, out_flags,
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive_with_flags(
+ this->get_implementation(), buffers, in_flags, out_flags,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
};
diff --git a/boost/asio/basic_serial_port.hpp b/boost/asio/basic_serial_port.hpp
index bfc78afaf6..af2193f7cb 100644
--- a/boost/asio/basic_serial_port.hpp
+++ b/boost/asio/basic_serial_port.hpp
@@ -18,6 +18,8 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \
|| defined(GENERATING_DOCUMENTATION)
@@ -49,10 +51,6 @@ class basic_serial_port
public serial_port_base
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// serial port.
- typedef typename SerialPortService::native_handle_type native_type;
-
/// The native representation of a serial port.
typedef typename SerialPortService::native_handle_type native_handle_type;
@@ -63,11 +61,11 @@ public:
/**
* This constructor creates a serial port without opening it.
*
- * @param io_service The io_service object that the serial port will use to
+ * @param io_context The io_context object that the serial port will use to
* dispatch handlers for any asynchronous operations performed on the port.
*/
- explicit basic_serial_port(boost::asio::io_service& io_service)
- : basic_io_object<SerialPortService>(io_service)
+ explicit basic_serial_port(boost::asio::io_context& io_context)
+ : basic_io_object<SerialPortService>(io_context)
{
}
@@ -76,15 +74,15 @@ public:
* This constructor creates and opens a serial port for the specified device
* name.
*
- * @param io_service The io_service object that the serial port will use to
+ * @param io_context The io_context object that the serial port will use to
* dispatch handlers for any asynchronous operations performed on the port.
*
* @param device The platform-specific device name for this serial
* port.
*/
- explicit basic_serial_port(boost::asio::io_service& io_service,
+ explicit basic_serial_port(boost::asio::io_context& io_context,
const char* device)
- : basic_io_object<SerialPortService>(io_service)
+ : basic_io_object<SerialPortService>(io_context)
{
boost::system::error_code ec;
this->get_service().open(this->get_implementation(), device, ec);
@@ -96,15 +94,15 @@ public:
* This constructor creates and opens a serial port for the specified device
* name.
*
- * @param io_service The io_service object that the serial port will use to
+ * @param io_context The io_context object that the serial port will use to
* dispatch handlers for any asynchronous operations performed on the port.
*
* @param device The platform-specific device name for this serial
* port.
*/
- explicit basic_serial_port(boost::asio::io_service& io_service,
+ explicit basic_serial_port(boost::asio::io_context& io_context,
const std::string& device)
- : basic_io_object<SerialPortService>(io_service)
+ : basic_io_object<SerialPortService>(io_context)
{
boost::system::error_code ec;
this->get_service().open(this->get_implementation(), device, ec);
@@ -116,16 +114,16 @@ public:
* This constructor creates a serial port object to hold an existing native
* serial port.
*
- * @param io_service The io_service object that the serial port will use to
+ * @param io_context The io_context object that the serial port will use to
* dispatch handlers for any asynchronous operations performed on the port.
*
* @param native_serial_port A native serial port.
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_serial_port(boost::asio::io_service& io_service,
+ basic_serial_port(boost::asio::io_context& io_context,
const native_handle_type& native_serial_port)
- : basic_io_object<SerialPortService>(io_service)
+ : basic_io_object<SerialPortService>(io_context)
{
boost::system::error_code ec;
this->get_service().assign(this->get_implementation(),
@@ -142,7 +140,7 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_serial_port(io_service&) constructor.
+ * constructed using the @c basic_serial_port(io_context&) constructor.
*/
basic_serial_port(basic_serial_port&& other)
: basic_io_object<SerialPortService>(
@@ -158,7 +156,7 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_serial_port(io_service&) constructor.
+ * constructed using the @c basic_serial_port(io_context&) constructor.
*/
basic_serial_port& operator=(basic_serial_port&& other)
{
@@ -220,10 +218,11 @@ public:
*
* @param ec Set the indicate what error occurred, if any.
*/
- boost::system::error_code open(const std::string& device,
+ BOOST_ASIO_SYNC_OP_VOID open(const std::string& device,
boost::system::error_code& ec)
{
- return this->get_service().open(this->get_implementation(), device, ec);
+ this->get_service().open(this->get_implementation(), device, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Assign an existing native serial port to the serial port.
@@ -250,11 +249,12 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code assign(const native_handle_type& native_serial_port,
+ BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_serial_port,
boost::system::error_code& ec)
{
- return this->get_service().assign(this->get_implementation(),
+ this->get_service().assign(this->get_implementation(),
native_serial_port, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the serial port is open.
@@ -286,21 +286,10 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code close(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
- return this->get_service().close(this->get_implementation(), ec);
- }
-
- /// (Deprecated: Use native_handle().) Get the native serial port
- /// representation.
- /**
- * This function may be used to obtain the underlying representation of the
- * serial port. This is intended to allow access to native serial port
- * functionality that is not otherwise provided.
- */
- native_type native()
- {
- return this->get_service().native_handle(this->get_implementation());
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the native serial port representation.
@@ -337,9 +326,10 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code cancel(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
{
- return this->get_service().cancel(this->get_implementation(), ec);
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Send a break sequence to the serial port.
@@ -363,9 +353,10 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code send_break(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID send_break(boost::system::error_code& ec)
{
- return this->get_service().send_break(this->get_implementation(), ec);
+ this->get_service().send_break(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Set an option on the serial port.
@@ -407,11 +398,11 @@ public:
* boost::asio::serial_port_base::character_size
*/
template <typename SettableSerialPortOption>
- boost::system::error_code set_option(const SettableSerialPortOption& option,
+ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSerialPortOption& option,
boost::system::error_code& ec)
{
- return this->get_service().set_option(
- this->get_implementation(), option, ec);
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get an option from the serial port.
@@ -455,11 +446,11 @@ public:
* boost::asio::serial_port_base::character_size
*/
template <typename GettableSerialPortOption>
- boost::system::error_code get_option(GettableSerialPortOption& option,
+ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSerialPortOption& option,
boost::system::error_code& ec)
{
- return this->get_service().get_option(
- this->get_implementation(), option, ec);
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Write some data to the serial port.
@@ -543,7 +534,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -655,7 +646,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -694,4 +685,6 @@ public:
#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_BASIC_SERIAL_PORT_HPP
diff --git a/boost/asio/basic_signal_set.hpp b/boost/asio/basic_signal_set.hpp
index 608bc0a6d8..3c00fa6e26 100644
--- a/boost/asio/basic_signal_set.hpp
+++ b/boost/asio/basic_signal_set.hpp
@@ -17,6 +17,8 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <boost/asio/basic_io_object.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/throw_error.hpp>
@@ -55,7 +57,7 @@ namespace asio {
* ...
*
* // Construct a signal set registered for process termination.
- * boost::asio::signal_set signals(io_service, SIGINT, SIGTERM);
+ * boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
*
* // Start an asynchronous wait for one of the signals to occur.
* signals.async_wait(handler);
@@ -99,11 +101,11 @@ public:
/**
* This constructor creates a signal set without registering for any signals.
*
- * @param io_service The io_service object that the signal set will use to
+ * @param io_context The io_context object that the signal set will use to
* dispatch handlers for any asynchronous operations performed on the set.
*/
- explicit basic_signal_set(boost::asio::io_service& io_service)
- : basic_io_object<SignalSetService>(io_service)
+ explicit basic_signal_set(boost::asio::io_context& io_context)
+ : basic_io_object<SignalSetService>(io_context)
{
}
@@ -111,20 +113,20 @@ public:
/**
* This constructor creates a signal set and registers for one signal.
*
- * @param io_service The io_service object that the signal set will use to
+ * @param io_context The io_context object that the signal set will use to
* dispatch handlers for any asynchronous operations performed on the set.
*
* @param signal_number_1 The signal number to be added.
*
* @note This constructor is equivalent to performing:
- * @code boost::asio::signal_set signals(io_service);
+ * @code boost::asio::signal_set signals(io_context);
* signals.add(signal_number_1); @endcode
*/
- basic_signal_set(boost::asio::io_service& io_service, int signal_number_1)
- : basic_io_object<SignalSetService>(io_service)
+ basic_signal_set(boost::asio::io_context& io_context, int signal_number_1)
+ : basic_io_object<SignalSetService>(io_context)
{
boost::system::error_code ec;
- this->service.add(this->implementation, signal_number_1, ec);
+ this->get_service().add(this->get_implementation(), signal_number_1, ec);
boost::asio::detail::throw_error(ec, "add");
}
@@ -132,7 +134,7 @@ public:
/**
* This constructor creates a signal set and registers for two signals.
*
- * @param io_service The io_service object that the signal set will use to
+ * @param io_context The io_context object that the signal set will use to
* dispatch handlers for any asynchronous operations performed on the set.
*
* @param signal_number_1 The first signal number to be added.
@@ -140,18 +142,18 @@ public:
* @param signal_number_2 The second signal number to be added.
*
* @note This constructor is equivalent to performing:
- * @code boost::asio::signal_set signals(io_service);
+ * @code boost::asio::signal_set signals(io_context);
* signals.add(signal_number_1);
* signals.add(signal_number_2); @endcode
*/
- basic_signal_set(boost::asio::io_service& io_service, int signal_number_1,
+ basic_signal_set(boost::asio::io_context& io_context, int signal_number_1,
int signal_number_2)
- : basic_io_object<SignalSetService>(io_service)
+ : basic_io_object<SignalSetService>(io_context)
{
boost::system::error_code ec;
- this->service.add(this->implementation, signal_number_1, ec);
+ this->get_service().add(this->get_implementation(), signal_number_1, ec);
boost::asio::detail::throw_error(ec, "add");
- this->service.add(this->implementation, signal_number_2, ec);
+ this->get_service().add(this->get_implementation(), signal_number_2, ec);
boost::asio::detail::throw_error(ec, "add");
}
@@ -159,7 +161,7 @@ public:
/**
* This constructor creates a signal set and registers for three signals.
*
- * @param io_service The io_service object that the signal set will use to
+ * @param io_context The io_context object that the signal set will use to
* dispatch handlers for any asynchronous operations performed on the set.
*
* @param signal_number_1 The first signal number to be added.
@@ -169,21 +171,21 @@ public:
* @param signal_number_3 The third signal number to be added.
*
* @note This constructor is equivalent to performing:
- * @code boost::asio::signal_set signals(io_service);
+ * @code boost::asio::signal_set signals(io_context);
* signals.add(signal_number_1);
* signals.add(signal_number_2);
* signals.add(signal_number_3); @endcode
*/
- basic_signal_set(boost::asio::io_service& io_service, int signal_number_1,
+ basic_signal_set(boost::asio::io_context& io_context, int signal_number_1,
int signal_number_2, int signal_number_3)
- : basic_io_object<SignalSetService>(io_service)
+ : basic_io_object<SignalSetService>(io_context)
{
boost::system::error_code ec;
- this->service.add(this->implementation, signal_number_1, ec);
+ this->get_service().add(this->get_implementation(), signal_number_1, ec);
boost::asio::detail::throw_error(ec, "add");
- this->service.add(this->implementation, signal_number_2, ec);
+ this->get_service().add(this->get_implementation(), signal_number_2, ec);
boost::asio::detail::throw_error(ec, "add");
- this->service.add(this->implementation, signal_number_3, ec);
+ this->get_service().add(this->get_implementation(), signal_number_3, ec);
boost::asio::detail::throw_error(ec, "add");
}
@@ -199,7 +201,7 @@ public:
void add(int signal_number)
{
boost::system::error_code ec;
- this->service.add(this->implementation, signal_number, ec);
+ this->get_service().add(this->get_implementation(), signal_number, ec);
boost::asio::detail::throw_error(ec, "add");
}
@@ -212,10 +214,10 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code add(int signal_number,
- boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID add(int signal_number, boost::system::error_code& ec)
{
- return this->service.add(this->implementation, signal_number, ec);
+ this->get_service().add(this->get_implementation(), signal_number, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Remove a signal from a signal_set.
@@ -233,7 +235,7 @@ public:
void remove(int signal_number)
{
boost::system::error_code ec;
- this->service.remove(this->implementation, signal_number, ec);
+ this->get_service().remove(this->get_implementation(), signal_number, ec);
boost::asio::detail::throw_error(ec, "remove");
}
@@ -249,10 +251,11 @@ public:
* @note Removes any notifications that have been queued for the specified
* signal number.
*/
- boost::system::error_code remove(int signal_number,
+ BOOST_ASIO_SYNC_OP_VOID remove(int signal_number,
boost::system::error_code& ec)
{
- return this->service.remove(this->implementation, signal_number, ec);
+ this->get_service().remove(this->get_implementation(), signal_number, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Remove all signals from a signal_set.
@@ -267,7 +270,7 @@ public:
void clear()
{
boost::system::error_code ec;
- this->service.clear(this->implementation, ec);
+ this->get_service().clear(this->get_implementation(), ec);
boost::asio::detail::throw_error(ec, "clear");
}
@@ -280,9 +283,10 @@ public:
*
* @note Removes all queued notifications.
*/
- boost::system::error_code clear(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID clear(boost::system::error_code& ec)
{
- return this->service.clear(this->implementation, ec);
+ this->get_service().clear(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Cancel all operations associated with the signal set.
@@ -309,7 +313,7 @@ public:
void cancel()
{
boost::system::error_code ec;
- this->service.cancel(this->implementation, ec);
+ this->get_service().cancel(this->get_implementation(), ec);
boost::asio::detail::throw_error(ec, "cancel");
}
@@ -334,9 +338,10 @@ public:
* These handlers can no longer be cancelled, and therefore are passed an
* error code that indicates the successful completion of the wait operation.
*/
- boost::system::error_code cancel(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
{
- return this->service.cancel(this->implementation, ec);
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Start an asynchronous operation to wait for a signal to be delivered.
@@ -362,7 +367,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename SignalHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(SignalHandler,
@@ -373,7 +378,7 @@ public:
// not meet the documented type requirements for a SignalHandler.
BOOST_ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check;
- return this->service.async_wait(this->implementation,
+ return this->get_service().async_wait(this->get_implementation(),
BOOST_ASIO_MOVE_CAST(SignalHandler)(handler));
}
};
@@ -383,4 +388,6 @@ public:
#include <boost/asio/detail/pop_options.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_BASIC_SIGNAL_SET_HPP
diff --git a/boost/asio/basic_socket.hpp b/boost/asio/basic_socket.hpp
index 777f6a9ce1..cf51470690 100644
--- a/boost/asio/basic_socket.hpp
+++ b/boost/asio/basic_socket.hpp
@@ -22,8 +22,26 @@
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
+#include <boost/asio/post.hpp>
#include <boost/asio/socket_base.hpp>
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/winrt_ssocket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::winrt_ssocket_service<Protocol>
+# elif defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_socket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::win_iocp_socket_service<Protocol>
+# else
+# include <boost/asio/detail/reactive_socket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::reactive_socket_service<Protocol>
+# endif
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
@@ -38,18 +56,21 @@ namespace asio {
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
-template <typename Protocol, typename SocketService>
+template <typename Protocol BOOST_ASIO_SVC_TPARAM>
class basic_socket
- : public basic_io_object<SocketService>,
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>,
public socket_base
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// socket.
- typedef typename SocketService::native_handle_type native_type;
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
/// The native representation of a socket.
- typedef typename SocketService::native_handle_type native_handle_type;
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename BOOST_ASIO_SVC_T::native_handle_type native_handle_type;
+#endif
/// The protocol type.
typedef Protocol protocol_type;
@@ -57,18 +78,20 @@ public:
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
/// A basic_socket is always the lowest layer.
- typedef basic_socket<Protocol, SocketService> lowest_layer_type;
+ typedef basic_socket<Protocol BOOST_ASIO_SVC_TARG> lowest_layer_type;
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
/// Construct a basic_socket without opening it.
/**
* This constructor creates a socket without opening it.
*
- * @param io_service The io_service object that the socket will use to
+ * @param io_context The io_context object that the socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*/
- explicit basic_socket(boost::asio::io_service& io_service)
- : basic_io_object<SocketService>(io_service)
+ explicit basic_socket(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
}
@@ -76,16 +99,16 @@ public:
/**
* This constructor creates and opens a socket.
*
- * @param io_service The io_service object that the socket will use to
+ * @param io_context The io_context object that the socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_socket(boost::asio::io_service& io_service,
+ basic_socket(boost::asio::io_context& io_context,
const protocol_type& protocol)
- : basic_io_object<SocketService>(io_service)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
boost::system::error_code ec;
this->get_service().open(this->get_implementation(), protocol, ec);
@@ -99,7 +122,7 @@ public:
* specified endpoint on the local machine. The protocol used is the protocol
* associated with the given endpoint.
*
- * @param io_service The io_service object that the socket will use to
+ * @param io_context The io_context object that the socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the socket will
@@ -107,9 +130,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_socket(boost::asio::io_service& io_service,
+ basic_socket(boost::asio::io_context& io_context,
const endpoint_type& endpoint)
- : basic_io_object<SocketService>(io_service)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
boost::system::error_code ec;
const protocol_type protocol = endpoint.protocol();
@@ -123,7 +146,7 @@ public:
/**
* This constructor creates a socket object to hold an existing native socket.
*
- * @param io_service The io_service object that the socket will use to
+ * @param io_context The io_context object that the socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
@@ -132,9 +155,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_socket(boost::asio::io_service& io_service,
+ basic_socket(boost::asio::io_context& io_context,
const protocol_type& protocol, const native_handle_type& native_socket)
- : basic_io_object<SocketService>(io_service)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
boost::system::error_code ec;
this->get_service().assign(this->get_implementation(),
@@ -151,11 +174,10 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_socket(io_service&) constructor.
+ * constructed using the @c basic_socket(io_context&) constructor.
*/
basic_socket(basic_socket&& other)
- : basic_io_object<SocketService>(
- BOOST_ASIO_MOVE_CAST(basic_socket)(other))
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
{
}
@@ -167,17 +189,16 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_socket(io_service&) constructor.
+ * constructed using the @c basic_socket(io_context&) constructor.
*/
basic_socket& operator=(basic_socket&& other)
{
- basic_io_object<SocketService>::operator=(
- BOOST_ASIO_MOVE_CAST(basic_socket)(other));
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
return *this;
}
// All sockets have access to each other's implementations.
- template <typename Protocol1, typename SocketService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
friend class basic_socket;
/// Move-construct a basic_socket from a socket of another protocol type.
@@ -188,12 +209,12 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_socket(io_service&) constructor.
+ * constructed using the @c basic_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename SocketService1>
- basic_socket(basic_socket<Protocol1, SocketService1>&& other,
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
+ basic_socket(basic_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
- : basic_io_object<SocketService>(
+ : basic_io_object<BOOST_ASIO_SVC_T>(
other.get_service(), other.get_implementation())
{
}
@@ -206,21 +227,60 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_socket(io_service&) constructor.
+ * constructed using the @c basic_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename SocketService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
typename enable_if<is_convertible<Protocol1, Protocol>::value,
basic_socket>::type& operator=(
- basic_socket<Protocol1, SocketService1>&& other)
+ basic_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other)
{
- basic_socket tmp(BOOST_ASIO_MOVE_CAST2(basic_socket<
- Protocol1, SocketService1>)(other));
- basic_io_object<SocketService>::operator=(
- BOOST_ASIO_MOVE_CAST(basic_socket)(tmp));
+ basic_socket tmp(std::move(other));
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(tmp));
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ // These functions are provided by basic_io_object<>.
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
+ }
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
/// Get a reference to the lowest layer.
/**
* This function returns a reference to the lowest layer in a stack of
@@ -248,6 +308,7 @@ public:
{
return *this;
}
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
/// Open the socket using the specified protocol.
/**
@@ -259,7 +320,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* socket.open(boost::asio::ip::tcp::v4());
* @endcode
*/
@@ -280,7 +341,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* boost::system::error_code ec;
* socket.open(boost::asio::ip::tcp::v4(), ec);
* if (ec)
@@ -289,10 +350,11 @@ public:
* }
* @endcode
*/
- boost::system::error_code open(const protocol_type& protocol,
+ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol,
boost::system::error_code& ec)
{
- return this->get_service().open(this->get_implementation(), protocol, ec);
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Assign an existing native socket to the socket.
@@ -324,11 +386,12 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code assign(const protocol_type& protocol,
+ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,
const native_handle_type& native_socket, boost::system::error_code& ec)
{
- return this->get_service().assign(this->get_implementation(),
+ this->get_service().assign(this->get_implementation(),
protocol, native_socket, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is open.
@@ -367,7 +430,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::system::error_code ec;
* socket.close(ec);
@@ -380,20 +443,62 @@ public:
* @note For portable behaviour with respect to graceful closure of a
* connected socket, call shutdown() before closing the socket.
*/
- boost::system::error_code close(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
- return this->get_service().close(this->get_implementation(), ec);
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
- /// (Deprecated: Use native_handle().) Get the native socket representation.
+ /// Release ownership of the underlying native socket.
/**
- * This function may be used to obtain the underlying representation of the
- * socket. This is intended to allow access to native socket functionality
- * that is not otherwise provided.
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error. Ownership
+ * of the native socket is then transferred to the caller.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_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()
+ {
+ boost::system::error_code ec;
+ native_handle_type s = this->get_service().release(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "release");
+ return s;
+ }
+
+ /// Release ownership of the underlying native socket.
+ /**
+ * This function causes all outstanding asynchronous connect, send and receive
+ * operations to finish immediately, and the handlers for cancelled operations
+ * will be passed the boost::asio::error::operation_aborted error. Ownership
+ * of the native socket 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 boost::asio::error::operation_not_supported on
+ * these platforms.
*/
- native_type native()
+#if defined(BOOST_ASIO_MSVC) && (BOOST_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(boost::system::error_code& ec)
{
- return this->get_service().native_handle(this->get_implementation());
+ return this->get_service().release(this->get_implementation(), ec);
}
/// Get the native socket representation.
@@ -496,9 +601,10 @@ public:
"operation_not_supported when used on Windows XP, Windows Server 2003, "
"or earlier. Consult documentation for details."))
#endif
- boost::system::error_code cancel(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
{
- return this->get_service().cancel(this->get_implementation(), ec);
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is at the out-of-band data mark.
@@ -580,7 +686,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* socket.open(boost::asio::ip::tcp::v4());
* socket.bind(boost::asio::ip::tcp::endpoint(
* boost::asio::ip::tcp::v4(), 12345));
@@ -605,7 +711,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* socket.open(boost::asio::ip::tcp::v4());
* boost::system::error_code ec;
* socket.bind(boost::asio::ip::tcp::endpoint(
@@ -616,10 +722,11 @@ public:
* }
* @endcode
*/
- boost::system::error_code bind(const endpoint_type& endpoint,
+ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,
boost::system::error_code& ec)
{
- return this->get_service().bind(this->get_implementation(), endpoint, ec);
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Connect the socket to the specified endpoint.
@@ -639,7 +746,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* boost::asio::ip::tcp::endpoint endpoint(
* boost::asio::ip::address::from_string("1.2.3.4"), 12345);
* socket.connect(endpoint);
@@ -675,7 +782,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* boost::asio::ip::tcp::endpoint endpoint(
* boost::asio::ip::address::from_string("1.2.3.4"), 12345);
* boost::system::error_code ec;
@@ -686,20 +793,21 @@ public:
* }
* @endcode
*/
- boost::system::error_code connect(const endpoint_type& peer_endpoint,
+ BOOST_ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint,
boost::system::error_code& ec)
{
if (!is_open())
{
- if (this->get_service().open(this->get_implementation(),
- peer_endpoint.protocol(), ec))
+ this->get_service().open(this->get_implementation(),
+ peer_endpoint.protocol(), ec);
+ if (ec)
{
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
- return this->get_service().connect(
- this->get_implementation(), peer_endpoint, ec);
+ this->get_service().connect(this->get_implementation(), peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Start an asynchronous connect.
@@ -723,7 +831,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* @code
@@ -737,7 +845,7 @@ public:
*
* ...
*
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* boost::asio::ip::tcp::endpoint endpoint(
* boost::asio::ip::address::from_string("1.2.3.4"), 12345);
* socket.async_connect(endpoint, connect_handler);
@@ -757,24 +865,34 @@ public:
{
boost::system::error_code ec;
const protocol_type protocol = peer_endpoint.protocol();
- if (this->get_service().open(this->get_implementation(), protocol, ec))
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ if (ec)
{
- detail::async_result_init<
- ConnectHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
+ async_completion<ConnectHandler,
+ void (boost::system::error_code)> init(handler);
- this->get_io_service().post(
+ boost::asio::post(this->get_executor(),
boost::asio::detail::bind_handler(
BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(
ConnectHandler, void (boost::system::error_code)))(
- init.handler), ec));
+ init.completion_handler), ec));
return init.result.get();
}
}
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_connect(this->get_implementation(),
peer_endpoint, BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ConnectHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_connect(
+ this->get_implementation(), peer_endpoint, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Set an option on the socket.
@@ -805,7 +923,7 @@ public:
* @par Example
* Setting the IPPROTO_TCP/TCP_NODELAY option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::tcp::no_delay option(true);
* socket.set_option(option);
@@ -847,7 +965,7 @@ public:
* @par Example
* Setting the IPPROTO_TCP/TCP_NODELAY option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::tcp::no_delay option(true);
* boost::system::error_code ec;
@@ -859,11 +977,11 @@ public:
* @endcode
*/
template <typename SettableSocketOption>
- boost::system::error_code set_option(const SettableSocketOption& option,
+ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option,
boost::system::error_code& ec)
{
- return this->get_service().set_option(
- this->get_implementation(), option, ec);
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get an option from the socket.
@@ -894,7 +1012,7 @@ public:
* @par Example
* Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::tcp::socket::keep_alive option;
* socket.get_option(option);
@@ -937,7 +1055,7 @@ public:
* @par Example
* Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::tcp::socket::keep_alive option;
* boost::system::error_code ec;
@@ -950,11 +1068,11 @@ public:
* @endcode
*/
template <typename GettableSocketOption>
- boost::system::error_code get_option(GettableSocketOption& option,
+ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,
boost::system::error_code& ec) const
{
- return this->get_service().get_option(
- this->get_implementation(), option, ec);
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform an IO control command on the socket.
@@ -972,7 +1090,7 @@ public:
* @par Example
* Getting the number of bytes ready to read:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::tcp::socket::bytes_readable command;
* socket.io_control(command);
@@ -1002,7 +1120,7 @@ public:
* @par Example
* Getting the number of bytes ready to read:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::tcp::socket::bytes_readable command;
* boost::system::error_code ec;
@@ -1015,11 +1133,11 @@ public:
* @endcode
*/
template <typename IoControlCommand>
- boost::system::error_code io_control(IoControlCommand& command,
+ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
boost::system::error_code& ec)
{
- return this->get_service().io_control(
- this->get_implementation(), command, ec);
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the socket.
@@ -1071,11 +1189,11 @@ public:
* operations. Asynchronous operations will never fail with the error
* boost::asio::error::would_block.
*/
- boost::system::error_code non_blocking(
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(
bool mode, boost::system::error_code& ec)
{
- return this->get_service().non_blocking(
- this->get_implementation(), mode, ec);
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the native socket implementation.
@@ -1135,7 +1253,7 @@ public:
* || ec == boost::asio::error::try_again)
* {
* // We have to wait for the socket to become ready again.
- * sock_.async_write_some(boost::asio::null_buffers(), *this);
+ * sock_.async_wait(tcp::socket::wait_write, *this);
* return;
* }
*
@@ -1159,7 +1277,7 @@ public:
* void async_sendfile(tcp::socket& sock, int fd, Handler h)
* {
* sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
- * sock.async_write_some(boost::asio::null_buffers(), op);
+ * sock.async_wait(tcp::socket::wait_write, op);
* } @endcode
*/
bool native_non_blocking() const
@@ -1225,7 +1343,7 @@ public:
* || ec == boost::asio::error::try_again)
* {
* // We have to wait for the socket to become ready again.
- * sock_.async_write_some(boost::asio::null_buffers(), *this);
+ * sock_.async_wait(tcp::socket::wait_write, *this);
* return;
* }
*
@@ -1249,7 +1367,7 @@ public:
* void async_sendfile(tcp::socket& sock, int fd, Handler h)
* {
* sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
- * sock.async_write_some(boost::asio::null_buffers(), op);
+ * sock.async_wait(tcp::socket::wait_write, op);
* } @endcode
*/
void native_non_blocking(bool mode)
@@ -1318,7 +1436,7 @@ public:
* || ec == boost::asio::error::try_again)
* {
* // We have to wait for the socket to become ready again.
- * sock_.async_write_some(boost::asio::null_buffers(), *this);
+ * sock_.async_wait(tcp::socket::wait_write, *this);
* return;
* }
*
@@ -1342,14 +1460,15 @@ public:
* void async_sendfile(tcp::socket& sock, int fd, Handler h)
* {
* sendfile_op<Handler> op = { sock, fd, h, 0, 0 };
- * sock.async_write_some(boost::asio::null_buffers(), op);
+ * sock.async_wait(tcp::socket::wait_write, op);
* } @endcode
*/
- boost::system::error_code native_non_blocking(
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
bool mode, boost::system::error_code& ec)
{
- return this->get_service().native_non_blocking(
+ this->get_service().native_non_blocking(
this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the local endpoint of the socket.
@@ -1362,7 +1481,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint();
* @endcode
@@ -1387,7 +1506,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::system::error_code ec;
* boost::asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);
@@ -1412,7 +1531,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();
* @endcode
@@ -1437,7 +1556,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::system::error_code ec;
* boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);
@@ -1464,7 +1583,7 @@ public:
* @par Example
* Shutting down the send side of the socket:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send);
* @endcode
@@ -1488,7 +1607,7 @@ public:
* @par Example
* Shutting down the send side of the socket:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::system::error_code ec;
* socket.shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
@@ -1498,17 +1617,134 @@ public:
* }
* @endcode
*/
- boost::system::error_code shutdown(shutdown_type what,
+ BOOST_ASIO_SYNC_OP_VOID shutdown(shutdown_type what,
boost::system::error_code& ec)
{
- return this->get_service().shutdown(this->get_implementation(), what, ec);
+ this->get_service().shutdown(this->get_implementation(), what, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @par Example
+ * Waiting for a socket to become readable.
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * socket.wait(boost::asio::ip::tcp::socket::wait_read);
+ * @endcode
+ */
+ void wait(wait_type w)
+ {
+ boost::system::error_code ec;
+ this->get_service().wait(this->get_implementation(), w, ec);
+ boost::asio::detail::throw_error(ec, "wait");
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a socket to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired socket state.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Waiting for a socket to become readable.
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * socket.wait(boost::asio::ip::tcp::socket::wait_read, ec);
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
+ {
+ this->get_service().wait(this->get_implementation(), w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the socket to become ready to read, ready to
+ /// 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void wait_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Wait succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * socket.async_wait(boost::asio::ip::tcp::socket::wait_read, wait_handler);
+ * @endcode
+ */
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WaitHandler.
+ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_wait(this->get_implementation(),
+ w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_wait(this->get_implementation(),
+ w, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
protected:
/// Protected destructor to prevent deletion through this type.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
~basic_socket()
{
}
+
+private:
+ // Disallow copying and assignment.
+ basic_socket(const basic_socket&) BOOST_ASIO_DELETED;
+ basic_socket& operator=(const basic_socket&) BOOST_ASIO_DELETED;
};
} // namespace asio
@@ -1516,4 +1752,8 @@ protected:
#include <boost/asio/detail/pop_options.hpp>
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# undef BOOST_ASIO_SVC_T
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_BASIC_SOCKET_HPP
diff --git a/boost/asio/basic_socket_acceptor.hpp b/boost/asio/basic_socket_acceptor.hpp
index f1d2b8e7a6..3cbfa5081d 100644
--- a/boost/asio/basic_socket_acceptor.hpp
+++ b/boost/asio/basic_socket_acceptor.hpp
@@ -22,9 +22,27 @@
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/socket_acceptor_service.hpp>
#include <boost/asio/socket_base.hpp>
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/socket_acceptor_service.hpp>
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/null_socket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::null_socket_service<Protocol>
+# elif defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_socket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::win_iocp_socket_service<Protocol>
+# else
+# include <boost/asio/detail/reactive_socket_service.hpp>
+# define BOOST_ASIO_SVC_T detail::reactive_socket_service<Protocol>
+# endif
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
@@ -42,7 +60,7 @@ namespace asio {
* @par Example
* Opening a socket acceptor with the SO_REUSEADDR option enabled:
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
* acceptor.open(endpoint.protocol());
* acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
@@ -50,19 +68,22 @@ namespace asio {
* acceptor.listen();
* @endcode
*/
-template <typename Protocol,
- typename SocketAcceptorService = socket_acceptor_service<Protocol> >
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= socket_acceptor_service<Protocol>)>
class basic_socket_acceptor
- : public basic_io_object<SocketAcceptorService>,
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>,
public socket_base
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of an
- /// acceptor.
- typedef typename SocketAcceptorService::native_handle_type native_type;
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
/// The native representation of an acceptor.
- typedef typename SocketAcceptorService::native_handle_type native_handle_type;
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename BOOST_ASIO_SVC_T::native_handle_type native_handle_type;
+#endif
/// The protocol type.
typedef Protocol protocol_type;
@@ -76,12 +97,12 @@ public:
* connections. The open() function must be called before the acceptor can
* accept new socket connections.
*
- * @param io_service The io_service object that the acceptor will use to
+ * @param io_context The io_context object that the acceptor will use to
* dispatch handlers for any asynchronous operations performed on the
* acceptor.
*/
- explicit basic_socket_acceptor(boost::asio::io_service& io_service)
- : basic_io_object<SocketAcceptorService>(io_service)
+ explicit basic_socket_acceptor(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
}
@@ -89,7 +110,7 @@ public:
/**
* This constructor creates an acceptor and automatically opens it.
*
- * @param io_service The io_service object that the acceptor will use to
+ * @param io_context The io_context object that the acceptor will use to
* dispatch handlers for any asynchronous operations performed on the
* acceptor.
*
@@ -97,9 +118,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_socket_acceptor(boost::asio::io_service& io_service,
+ basic_socket_acceptor(boost::asio::io_context& io_context,
const protocol_type& protocol)
- : basic_io_object<SocketAcceptorService>(io_service)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
boost::system::error_code ec;
this->get_service().open(this->get_implementation(), protocol, ec);
@@ -111,7 +132,7 @@ public:
* This constructor creates an acceptor and automatically opens it to listen
* for new connections on the specified endpoint.
*
- * @param io_service The io_service object that the acceptor will use to
+ * @param io_context The io_context object that the acceptor will use to
* dispatch handlers for any asynchronous operations performed on the
* acceptor.
*
@@ -125,7 +146,7 @@ public:
*
* @note This constructor is equivalent to the following code:
* @code
- * basic_socket_acceptor<Protocol> acceptor(io_service);
+ * basic_socket_acceptor<Protocol> acceptor(io_context);
* acceptor.open(endpoint.protocol());
* if (reuse_addr)
* acceptor.set_option(socket_base::reuse_address(true));
@@ -133,9 +154,9 @@ public:
* acceptor.listen(listen_backlog);
* @endcode
*/
- basic_socket_acceptor(boost::asio::io_service& io_service,
+ basic_socket_acceptor(boost::asio::io_context& io_context,
const endpoint_type& endpoint, bool reuse_addr = true)
- : basic_io_object<SocketAcceptorService>(io_service)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
boost::system::error_code ec;
const protocol_type protocol = endpoint.protocol();
@@ -150,7 +171,7 @@ public:
this->get_service().bind(this->get_implementation(), endpoint, ec);
boost::asio::detail::throw_error(ec, "bind");
this->get_service().listen(this->get_implementation(),
- socket_base::max_connections, ec);
+ socket_base::max_listen_connections, ec);
boost::asio::detail::throw_error(ec, "listen");
}
@@ -159,7 +180,7 @@ public:
* This constructor creates an acceptor object to hold an existing native
* acceptor.
*
- * @param io_service The io_service object that the acceptor will use to
+ * @param io_context The io_context object that the acceptor will use to
* dispatch handlers for any asynchronous operations performed on the
* acceptor.
*
@@ -169,9 +190,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_socket_acceptor(boost::asio::io_service& io_service,
+ basic_socket_acceptor(boost::asio::io_context& io_context,
const protocol_type& protocol, const native_handle_type& native_acceptor)
- : basic_io_object<SocketAcceptorService>(io_service)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
boost::system::error_code ec;
this->get_service().assign(this->get_implementation(),
@@ -188,11 +209,10 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_socket_acceptor(io_service&) constructor.
+ * constructed using the @c basic_socket_acceptor(io_context&) constructor.
*/
basic_socket_acceptor(basic_socket_acceptor&& other)
- : basic_io_object<SocketAcceptorService>(
- BOOST_ASIO_MOVE_CAST(basic_socket_acceptor)(other))
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
{
}
@@ -204,17 +224,16 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_socket_acceptor(io_service&) constructor.
+ * constructed using the @c basic_socket_acceptor(io_context&) constructor.
*/
basic_socket_acceptor& operator=(basic_socket_acceptor&& other)
{
- basic_io_object<SocketAcceptorService>::operator=(
- BOOST_ASIO_MOVE_CAST(basic_socket_acceptor)(other));
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
return *this;
}
// All socket acceptors have access to each other's implementations.
- template <typename Protocol1, typename SocketAcceptorService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
friend class basic_socket_acceptor;
/// Move-construct a basic_socket_acceptor from an acceptor of another
@@ -226,13 +245,13 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_socket(io_service&) constructor.
+ * constructed using the @c basic_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename SocketAcceptorService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
basic_socket_acceptor(
- basic_socket_acceptor<Protocol1, SocketAcceptorService1>&& other,
+ basic_socket_acceptor<Protocol1 BOOST_ASIO_SVC_TARG1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
- : basic_io_object<SocketAcceptorService>(
+ : basic_io_object<BOOST_ASIO_SVC_T>(
other.get_service(), other.get_implementation())
{
}
@@ -246,21 +265,69 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_socket(io_service&) constructor.
+ * constructed using the @c basic_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename SocketAcceptorService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
typename enable_if<is_convertible<Protocol1, Protocol>::value,
basic_socket_acceptor>::type& operator=(
- basic_socket_acceptor<Protocol1, SocketAcceptorService1>&& other)
+ basic_socket_acceptor<Protocol1 BOOST_ASIO_SVC_TARG1>&& other)
{
- basic_socket_acceptor tmp(BOOST_ASIO_MOVE_CAST2(basic_socket_acceptor<
- Protocol1, SocketAcceptorService1>)(other));
- basic_io_object<SocketAcceptorService>::operator=(
- BOOST_ASIO_MOVE_CAST(basic_socket_acceptor)(tmp));
+ basic_socket_acceptor tmp(std::move(other));
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(tmp));
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Destroys the acceptor.
+ /**
+ * This function destroys the acceptor, cancelling any outstanding
+ * asynchronous operations associated with the acceptor as if by calling
+ * @c cancel.
+ */
+ ~basic_socket_acceptor()
+ {
+ }
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ // These functions are provided by basic_io_object<>.
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
+ }
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
/// Open the acceptor using the specified protocol.
/**
* This function opens the socket acceptor so that it will use the specified
@@ -272,7 +339,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* acceptor.open(boost::asio::ip::tcp::v4());
* @endcode
*/
@@ -294,7 +361,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* boost::system::error_code ec;
* acceptor.open(boost::asio::ip::tcp::v4(), ec);
* if (ec)
@@ -303,10 +370,11 @@ public:
* }
* @endcode
*/
- boost::system::error_code open(const protocol_type& protocol,
+ BOOST_ASIO_SYNC_OP_VOID open(const protocol_type& protocol,
boost::system::error_code& ec)
{
- return this->get_service().open(this->get_implementation(), protocol, ec);
+ this->get_service().open(this->get_implementation(), protocol, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Assigns an existing native acceptor to the acceptor.
@@ -338,11 +406,12 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code assign(const protocol_type& protocol,
+ BOOST_ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,
const native_handle_type& native_acceptor, boost::system::error_code& ec)
{
- return this->get_service().assign(this->get_implementation(),
+ this->get_service().assign(this->get_implementation(),
protocol, native_acceptor, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the acceptor is open.
@@ -363,7 +432,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345);
* acceptor.open(endpoint.protocol());
* acceptor.bind(endpoint);
@@ -388,7 +457,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 12345);
* acceptor.open(endpoint.protocol());
* boost::system::error_code ec;
@@ -399,10 +468,11 @@ public:
* }
* @endcode
*/
- boost::system::error_code bind(const endpoint_type& endpoint,
+ BOOST_ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,
boost::system::error_code& ec)
{
- return this->get_service().bind(this->get_implementation(), endpoint, ec);
+ this->get_service().bind(this->get_implementation(), endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Place the acceptor into the state where it will listen for new
@@ -415,7 +485,7 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- void listen(int backlog = socket_base::max_connections)
+ void listen(int backlog = socket_base::max_listen_connections)
{
boost::system::error_code ec;
this->get_service().listen(this->get_implementation(), backlog, ec);
@@ -434,19 +504,20 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::system::error_code ec;
- * acceptor.listen(boost::asio::socket_base::max_connections, ec);
+ * acceptor.listen(boost::asio::socket_base::max_listen_connections, ec);
* if (ec)
* {
* // An error occurred.
* }
* @endcode
*/
- boost::system::error_code listen(int backlog, boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID listen(int backlog, boost::system::error_code& ec)
{
- return this->get_service().listen(this->get_implementation(), backlog, ec);
+ this->get_service().listen(this->get_implementation(), backlog, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Close the acceptor.
@@ -478,7 +549,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::system::error_code ec;
* acceptor.close(ec);
@@ -488,20 +559,62 @@ public:
* }
* @endcode
*/
- boost::system::error_code close(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
- return this->get_service().close(this->get_implementation(), ec);
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
- /// (Deprecated: Use native_handle().) Get the native acceptor representation.
+ /// Release ownership of the underlying native acceptor.
/**
- * This function may be used to obtain the underlying representation of the
- * acceptor. This is intended to allow access to native acceptor functionality
- * that is not otherwise provided.
+ * This function causes all outstanding asynchronous accept operations to
+ * finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error. Ownership of the
+ * native acceptor is then transferred to the caller.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This function is unsupported on Windows versions prior to Windows
+ * 8.1, and will fail with boost::asio::error::operation_not_supported on
+ * these platforms.
*/
- native_type native()
+#if defined(BOOST_ASIO_MSVC) && (BOOST_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()
{
- return this->get_service().native_handle(this->get_implementation());
+ boost::system::error_code ec;
+ native_handle_type s = this->get_service().release(
+ this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "release");
+ return s;
+ }
+
+ /// Release ownership of the underlying native acceptor.
+ /**
+ * This function causes all outstanding asynchronous accept operations to
+ * finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error. Ownership of the
+ * native acceptor 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 boost::asio::error::operation_not_supported on
+ * these platforms.
+ */
+#if defined(BOOST_ASIO_MSVC) && (BOOST_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(boost::system::error_code& ec)
+ {
+ return this->get_service().release(this->get_implementation(), ec);
}
/// Get the native acceptor representation.
@@ -538,9 +651,10 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code cancel(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
{
- return this->get_service().cancel(this->get_implementation(), ec);
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Set an option on the acceptor.
@@ -558,7 +672,7 @@ public:
* @par Example
* Setting the SOL_SOCKET/SO_REUSEADDR option:
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::asio::ip::tcp::acceptor::reuse_address option(true);
* acceptor.set_option(option);
@@ -587,7 +701,7 @@ public:
* @par Example
* Setting the SOL_SOCKET/SO_REUSEADDR option:
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::asio::ip::tcp::acceptor::reuse_address option(true);
* boost::system::error_code ec;
@@ -599,11 +713,11 @@ public:
* @endcode
*/
template <typename SettableSocketOption>
- boost::system::error_code set_option(const SettableSocketOption& option,
+ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& option,
boost::system::error_code& ec)
{
- return this->get_service().set_option(
- this->get_implementation(), option, ec);
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get an option from the acceptor.
@@ -621,7 +735,7 @@ public:
* @par Example
* Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::asio::ip::tcp::acceptor::reuse_address option;
* acceptor.get_option(option);
@@ -651,7 +765,7 @@ public:
* @par Example
* Getting the value of the SOL_SOCKET/SO_REUSEADDR option:
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::asio::ip::tcp::acceptor::reuse_address option;
* boost::system::error_code ec;
@@ -664,11 +778,11 @@ public:
* @endcode
*/
template <typename GettableSocketOption>
- boost::system::error_code get_option(GettableSocketOption& option,
+ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,
boost::system::error_code& ec)
{
- return this->get_service().get_option(
- this->get_implementation(), option, ec);
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform an IO control command on the acceptor.
@@ -685,7 +799,7 @@ public:
* @par Example
* Getting the number of bytes ready to read:
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::asio::ip::tcp::acceptor::non_blocking_io command(true);
* socket.io_control(command);
@@ -713,7 +827,7 @@ public:
* @par Example
* Getting the number of bytes ready to read:
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::asio::ip::tcp::acceptor::non_blocking_io command(true);
* boost::system::error_code ec;
@@ -725,11 +839,11 @@ public:
* @endcode
*/
template <typename IoControlCommand>
- boost::system::error_code io_control(IoControlCommand& command,
+ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
boost::system::error_code& ec)
{
- return this->get_service().io_control(
- this->get_implementation(), command, ec);
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the acceptor.
@@ -781,11 +895,11 @@ public:
* operations. Asynchronous operations will never fail with the error
* boost::asio::error::would_block.
*/
- boost::system::error_code non_blocking(
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(
bool mode, boost::system::error_code& ec)
{
- return this->get_service().non_blocking(
- this->get_implementation(), mode, ec);
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the native acceptor implementation.
@@ -845,11 +959,12 @@ public:
* function fails with boost::asio::error::invalid_argument, as the
* combination does not make sense.
*/
- boost::system::error_code native_non_blocking(
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
bool mode, boost::system::error_code& ec)
{
- return this->get_service().native_non_blocking(
+ this->get_service().native_non_blocking(
this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the local endpoint of the acceptor.
@@ -862,7 +977,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint();
* @endcode
@@ -888,7 +1003,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::system::error_code ec;
* boost::asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec);
@@ -903,6 +1018,116 @@ public:
return this->get_service().local_endpoint(this->get_implementation(), ec);
}
+ /// Wait for the acceptor to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for an acceptor to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired acceptor state.
+ *
+ * @par Example
+ * Waiting for an acceptor to become readable.
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read);
+ * @endcode
+ */
+ void wait(wait_type w)
+ {
+ boost::system::error_code ec;
+ this->get_service().wait(this->get_implementation(), w, ec);
+ boost::asio::detail::throw_error(ec, "wait");
+ }
+
+ /// Wait for the acceptor to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for an acceptor to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired acceptor state.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Waiting for an acceptor to become readable.
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * acceptor.wait(boost::asio::ip::tcp::acceptor::wait_read, ec);
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
+ {
+ this->get_service().wait(this->get_implementation(), w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the acceptor to become ready to read, ready to
+ /// 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void wait_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Wait succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * acceptor.async_wait(
+ * boost::asio::ip::tcp::acceptor::wait_read,
+ * wait_handler);
+ * @endcode
+ */
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WaitHandler.
+ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_wait(this->get_implementation(),
+ w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_wait(this->get_implementation(),
+ w, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
/// Accept a new connection.
/**
* This function is used to accept a new connection from a peer into the
@@ -915,15 +1140,21 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* acceptor.accept(socket);
* @endcode
*/
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
template <typename Protocol1, typename SocketService>
void accept(basic_socket<Protocol1, SocketService>& peer,
typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename Protocol1>
+ void accept(basic_socket<Protocol1>& peer,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
{
boost::system::error_code ec;
this->get_service().accept(this->get_implementation(),
@@ -943,9 +1174,9 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
- * boost::asio::ip::tcp::soocket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* boost::system::error_code ec;
* acceptor.accept(socket, ec);
* if (ec)
@@ -954,14 +1185,22 @@ public:
* }
* @endcode
*/
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
template <typename Protocol1, typename SocketService>
- boost::system::error_code accept(
+ BOOST_ASIO_SYNC_OP_VOID accept(
basic_socket<Protocol1, SocketService>& peer,
boost::system::error_code& ec,
typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename Protocol1>
+ BOOST_ASIO_SYNC_OP_VOID accept(
+ basic_socket<Protocol1>& peer, boost::system::error_code& ec,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
{
- return this->get_service().accept(this->get_implementation(),
+ this->get_service().accept(this->get_implementation(),
peer, static_cast<endpoint_type*>(0), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Start an asynchronous accept.
@@ -982,7 +1221,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* @code
@@ -996,26 +1235,45 @@ public:
*
* ...
*
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* acceptor.async_accept(socket, accept_handler);
* @endcode
*/
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
template <typename Protocol1, typename SocketService, typename AcceptHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
void (boost::system::error_code))
async_accept(basic_socket<Protocol1, SocketService>& peer,
BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename Protocol1, typename AcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
+ void (boost::system::error_code))
+ async_accept(basic_socket<Protocol1>& peer,
+ BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
+ typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a AcceptHandler.
BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_accept(this->get_implementation(),
peer, static_cast<endpoint_type*>(0),
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<AcceptHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_accept(this->get_implementation(),
+ peer, static_cast<endpoint_type*>(0), init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Accept a new connection and obtain the endpoint of the peer
@@ -1034,16 +1292,20 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* boost::asio::ip::tcp::endpoint endpoint;
* acceptor.accept(socket, endpoint);
* @endcode
*/
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
template <typename SocketService>
void accept(basic_socket<protocol_type, SocketService>& peer,
endpoint_type& peer_endpoint)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ void accept(basic_socket<protocol_type>& peer, endpoint_type& peer_endpoint)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
{
boost::system::error_code ec;
this->get_service().accept(this->get_implementation(),
@@ -1067,9 +1329,9 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* boost::asio::ip::tcp::endpoint endpoint;
* boost::system::error_code ec;
* acceptor.accept(socket, endpoint, ec);
@@ -1079,13 +1341,19 @@ public:
* }
* @endcode
*/
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
template <typename SocketService>
- boost::system::error_code accept(
+ BOOST_ASIO_SYNC_OP_VOID accept(
basic_socket<protocol_type, SocketService>& peer,
endpoint_type& peer_endpoint, boost::system::error_code& ec)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ BOOST_ASIO_SYNC_OP_VOID accept(basic_socket<protocol_type>& peer,
+ endpoint_type& peer_endpoint, boost::system::error_code& ec)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
{
- return this->get_service().accept(
+ this->get_service().accept(
this->get_implementation(), peer, &peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Start an asynchronous accept.
@@ -1112,21 +1380,600 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
template <typename SocketService, typename AcceptHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
void (boost::system::error_code))
async_accept(basic_socket<protocol_type, SocketService>& peer,
endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ template <typename AcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler,
+ void (boost::system::error_code))
+ async_accept(basic_socket<protocol_type>& peer,
+ endpoint_type& peer_endpoint, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a AcceptHandler.
BOOST_ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_accept(this->get_implementation(), peer,
&peer_endpoint, BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<AcceptHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_accept(this->get_implementation(),
+ peer, &peer_endpoint, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept());
+ * @endcode
+ */
+ typename Protocol::socket accept()
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket peer(
+ this->get_service().accept(
+ this->get_implementation(), 0, 0, ec));
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ typename Protocol::socket accept(boost::system::error_code& ec)
+ {
+ return this->get_service().accept(this->get_implementation(), 0, 0, ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call 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:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket 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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * acceptor.async_accept(accept_handler);
+ * @endcode
+ */
+ template <typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket))
+ async_accept(BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a MoveAcceptHandler.
+ BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler,
+ handler, typename Protocol::socket) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_accept(
+ this->get_implementation(), static_cast<boost::asio::io_context*>(0),
+ static_cast<endpoint_type*>(0),
+ BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket)> init(handler);
+
+ this->get_service().async_accept(
+ this->get_implementation(), static_cast<boost::asio::io_context*>(0),
+ static_cast<endpoint_type*>(0), init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_context object to be used for the newly accepted
+ * socket.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept());
+ * @endcode
+ */
+ typename Protocol::socket accept(boost::asio::io_context& io_context)
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket peer(
+ this->get_service().accept(this->get_implementation(),
+ &io_context, static_cast<endpoint_type*>(0), ec));
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
}
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_context object to be used for the newly accepted
+ * socket.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(io_context2, ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ typename Protocol::socket accept(
+ boost::asio::io_context& io_context, boost::system::error_code& ec)
+ {
+ return this->get_service().accept(this->get_implementation(),
+ &io_context, static_cast<endpoint_type*>(0), ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_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:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket 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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * acceptor.async_accept(io_context2, accept_handler);
+ * @endcode
+ */
+ template <typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket))
+ async_accept(boost::asio::io_context& io_context,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a MoveAcceptHandler.
+ BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler,
+ handler, typename Protocol::socket) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_accept(this->get_implementation(),
+ &io_context, static_cast<endpoint_type*>(0),
+ BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket)> init(handler);
+
+ this->get_service().async_accept(this->get_implementation(),
+ &io_context, static_cast<endpoint_type*>(0), init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint));
+ * @endcode
+ */
+ typename Protocol::socket accept(endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket peer(
+ this->get_service().accept(this->get_implementation(),
+ static_cast<boost::asio::io_context*>(0), &peer_endpoint, ec));
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(acceptor.accept(endpoint, ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ typename Protocol::socket accept(
+ endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ return this->get_service().accept(this->get_implementation(),
+ static_cast<boost::asio::io_context*>(0), &peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket 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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * acceptor.async_accept(endpoint, accept_handler);
+ * @endcode
+ */
+ template <typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket))
+ async_accept(endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a MoveAcceptHandler.
+ BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler,
+ handler, typename Protocol::socket) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_accept(this->get_implementation(),
+ static_cast<boost::asio::io_context*>(0), &peer_endpoint,
+ BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket)> init(handler);
+
+ this->get_service().async_accept(this->get_implementation(),
+ static_cast<boost::asio::io_context*>(0), &peer_endpoint,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_context object to be used for the newly accepted
+ * socket.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @returns A socket object representing the newly accepted connection.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(
+ * acceptor.accept(io_context2, endpoint));
+ * @endcode
+ */
+ typename Protocol::socket accept(
+ boost::asio::io_context& io_context, endpoint_type& peer_endpoint)
+ {
+ boost::system::error_code ec;
+ typename Protocol::socket peer(
+ this->get_service().accept(this->get_implementation(),
+ &io_context, &peer_endpoint, ec));
+ boost::asio::detail::throw_error(ec, "accept");
+ return peer;
+ }
+
+ /// Accept a new connection.
+ /**
+ * This function is used to accept a new connection from a peer. The function
+ * call will block until a new connection has been accepted successfully or
+ * an error occurs.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_context object to be used for the newly accepted
+ * socket.
+ *
+ * @param peer_endpoint An endpoint object into which the endpoint of the
+ * remote peer will be written.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns On success, a socket object representing the newly accepted
+ * connection. On error, a socket object where is_open() is false.
+ *
+ * @par Example
+ * @code
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * boost::asio::ip::tcp::socket socket(
+ * acceptor.accept(io_context2, endpoint, ec));
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * @endcode
+ */
+ typename Protocol::socket accept(boost::asio::io_context& io_context,
+ endpoint_type& peer_endpoint, boost::system::error_code& ec)
+ {
+ return this->get_service().accept(this->get_implementation(),
+ &io_context, &peer_endpoint, ec);
+ }
+
+ /// Start an asynchronous accept.
+ /**
+ * This function is used to asynchronously accept a new connection. The
+ * function call always returns immediately.
+ *
+ * This overload requires that the Protocol template parameter satisfy the
+ * AcceptableProtocol type requirements.
+ *
+ * @param io_context The io_context object to be used for the newly accepted
+ * socket.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ * typename Protocol::socket 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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void accept_handler(const boost::system::error_code& error,
+ * boost::asio::ip::tcp::socket peer)
+ * {
+ * if (!error)
+ * {
+ * // Accept succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
+ * ...
+ * boost::asio::ip::tcp::endpoint endpoint;
+ * acceptor.async_accept(io_context2, endpoint, accept_handler);
+ * @endcode
+ */
+ template <typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket))
+ async_accept(boost::asio::io_context& io_context,
+ endpoint_type& peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a MoveAcceptHandler.
+ BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK(MoveAcceptHandler,
+ handler, typename Protocol::socket) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_accept(
+ this->get_implementation(), &io_context, &peer_endpoint,
+ BOOST_ASIO_MOVE_CAST(MoveAcceptHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket)> init(handler);
+
+ this->get_service().async_accept(this->get_implementation(),
+ &io_context, &peer_endpoint, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
};
} // namespace asio
@@ -1134,4 +1981,8 @@ public:
#include <boost/asio/detail/pop_options.hpp>
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# undef BOOST_ASIO_SVC_T
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_BASIC_SOCKET_ACCEPTOR_HPP
diff --git a/boost/asio/basic_socket_iostream.hpp b/boost/asio/basic_socket_iostream.hpp
index 6ed71f7b68..a5f8e0223a 100644
--- a/boost/asio/basic_socket_iostream.hpp
+++ b/boost/asio/basic_socket_iostream.hpp
@@ -22,7 +22,10 @@
#include <istream>
#include <ostream>
#include <boost/asio/basic_socket_streambuf.hpp>
-#include <boost/asio/stream_socket_service.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/stream_socket_service.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
#if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
@@ -33,8 +36,8 @@
// explicit basic_socket_iostream(T1 x1, ..., Tn xn)
// : std::basic_iostream<char>(
// &this->detail::socket_iostream_base<
-// Protocol, StreamSocketService, Time,
-// TimeTraits, TimerService>::streambuf_)
+// Protocol BOOST_ASIO_SVC_TARG, Clock,
+// WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_)
// {
// if (rdbuf()->connect(x1, ..., xn) == 0)
// this->setstate(std::ios_base::failbit);
@@ -43,14 +46,14 @@
# define BOOST_ASIO_PRIVATE_CTR_DEF(n) \
template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
- explicit basic_socket_iostream(BOOST_ASIO_VARIADIC_PARAMS(n)) \
+ explicit basic_socket_iostream(BOOST_ASIO_VARIADIC_BYVAL_PARAMS(n)) \
: std::basic_iostream<char>( \
&this->detail::socket_iostream_base< \
- Protocol, StreamSocketService, Time, \
- TimeTraits, TimerService>::streambuf_) \
+ Protocol BOOST_ASIO_SVC_TARG, Clock, \
+ WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_) \
{ \
this->setf(std::ios_base::unitbuf); \
- if (rdbuf()->connect(BOOST_ASIO_VARIADIC_ARGS(n)) == 0) \
+ if (rdbuf()->connect(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \
this->setstate(std::ios_base::failbit); \
} \
/**/
@@ -66,9 +69,9 @@
# define BOOST_ASIO_PRIVATE_CONNECT_DEF(n) \
template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
- void connect(BOOST_ASIO_VARIADIC_PARAMS(n)) \
+ void connect(BOOST_ASIO_VARIADIC_BYVAL_PARAMS(n)) \
{ \
- if (rdbuf()->connect(BOOST_ASIO_VARIADIC_ARGS(n)) == 0) \
+ if (rdbuf()->connect(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \
this->setstate(std::ios_base::failbit); \
} \
/**/
@@ -83,69 +86,163 @@ namespace detail {
// A separate base class is used to ensure that the streambuf is initialised
// prior to the basic_socket_iostream's basic_iostream base class.
-template <typename Protocol, typename StreamSocketService,
- typename Time, typename TimeTraits, typename TimerService>
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename Clock, typename WaitTraits BOOST_ASIO_SVC_TPARAM1>
class socket_iostream_base
{
protected:
- basic_socket_streambuf<Protocol, StreamSocketService,
- Time, TimeTraits, TimerService> streambuf_;
+ socket_iostream_base()
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ socket_iostream_base(socket_iostream_base&& other)
+ : streambuf_(std::move(other.streambuf_))
+ {
+ }
+
+ socket_iostream_base(basic_stream_socket<Protocol> s)
+ : streambuf_(std::move(s))
+ {
+ }
+
+ socket_iostream_base& operator=(socket_iostream_base&& other)
+ {
+ streambuf_ = std::move(other.streambuf_);
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ basic_socket_streambuf<Protocol BOOST_ASIO_SVC_TARG,
+ Clock, WaitTraits BOOST_ASIO_SVC_TARG1> streambuf_;
};
-}
+} // namespace detail
-/// Iostream interface for a socket.
-template <typename Protocol,
- typename StreamSocketService = stream_socket_service<Protocol>,
-#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
- || defined(GENERATING_DOCUMENTATION)
- typename Time = boost::posix_time::ptime,
- typename TimeTraits = boost::asio::time_traits<Time>,
- typename TimerService = deadline_timer_service<Time, TimeTraits> >
+#if !defined(BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
+#define BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL
+
+// Forward declaration with defaulted arguments.
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>),
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ typename Clock = boost::posix_time::ptime,
+ typename WaitTraits = time_traits<Clock>
+ BOOST_ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)>
#else
- typename Time = steady_timer::clock_type,
- typename TimeTraits = steady_timer::traits_type,
- typename TimerService = steady_timer::service_type>
+ typename Clock = chrono::steady_clock,
+ typename WaitTraits = wait_traits<Clock>
+ BOOST_ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)>
#endif
+class basic_socket_iostream;
+
+#endif // !defined(BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
+
+/// Iostream interface for a socket.
+#if defined(GENERATING_DOCUMENTATION)
+template <typename Protocol,
+ typename Clock = chrono::steady_clock,
+ typename WaitTraits = wait_traits<Clock> >
+#else // defined(GENERATING_DOCUMENTATION)
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename Clock, typename WaitTraits BOOST_ASIO_SVC_TPARAM1>
+#endif // defined(GENERATING_DOCUMENTATION)
class basic_socket_iostream
- : private detail::socket_iostream_base<Protocol,
- StreamSocketService, Time, TimeTraits, TimerService>,
+ : private detail::socket_iostream_base<Protocol
+ BOOST_ASIO_SVC_TARG, Clock, WaitTraits BOOST_ASIO_SVC_TARG1>,
public std::basic_iostream<char>
{
private:
// These typedefs are intended keep this class's implementation independent
- // of whether it's using Boost.DateTime, Boost.Chrono or std::chrono.
+ // of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
- typedef TimeTraits traits_helper;
+ typedef WaitTraits traits_helper;
#else
- typedef detail::chrono_time_traits<Time, TimeTraits> traits_helper;
+ typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
#endif
public:
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
+ /// The clock type.
+ typedef Clock clock_type;
+
#if defined(GENERATING_DOCUMENTATION)
+ /// (Deprecated: Use time_point.) The time type.
+ typedef typename WaitTraits::time_type time_type;
+
/// The time type.
- typedef typename TimeTraits::time_type time_type;
+ typedef typename WaitTraits::time_point time_point;
+
+ /// (Deprecated: Use duration.) The duration type.
+ typedef typename WaitTraits::duration_type duration_type;
/// The duration type.
- typedef typename TimeTraits::duration_type duration_type;
+ typedef typename WaitTraits::duration duration;
#else
+# if !defined(BOOST_ASIO_NO_DEPRECATED)
typedef typename traits_helper::time_type time_type;
typedef typename traits_helper::duration_type duration_type;
+# endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ typedef typename traits_helper::time_type time_point;
+ typedef typename traits_helper::duration_type duration;
#endif
/// Construct a basic_socket_iostream without establishing a connection.
basic_socket_iostream()
: std::basic_iostream<char>(
&this->detail::socket_iostream_base<
- Protocol, StreamSocketService, Time,
- TimeTraits, TimerService>::streambuf_)
+ Protocol BOOST_ASIO_SVC_TARG, Clock,
+ WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_)
+ {
+ this->setf(std::ios_base::unitbuf);
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Construct a basic_socket_iostream from the supplied socket.
+ explicit basic_socket_iostream(basic_stream_socket<protocol_type> s)
+ : detail::socket_iostream_base<
+ Protocol BOOST_ASIO_SVC_TARG, Clock,
+ WaitTraits BOOST_ASIO_SVC_TARG1>(std::move(s)),
+ std::basic_iostream<char>(
+ &this->detail::socket_iostream_base<
+ Protocol BOOST_ASIO_SVC_TARG, Clock,
+ WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_)
{
this->setf(std::ios_base::unitbuf);
}
+#if defined(BOOST_ASIO_HAS_STD_IOSTREAM_MOVE) \
+ || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_socket_iostream from another.
+ basic_socket_iostream(basic_socket_iostream&& other)
+ : detail::socket_iostream_base<
+ Protocol BOOST_ASIO_SVC_TARG, Clock,
+ WaitTraits BOOST_ASIO_SVC_TARG1>(std::move(other)),
+ std::basic_iostream<char>(std::move(other))
+ {
+ this->set_rdbuf(&this->detail::socket_iostream_base<
+ Protocol BOOST_ASIO_SVC_TARG, Clock,
+ WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_);
+ }
+
+ /// Move-assign a basic_socket_iostream from another.
+ basic_socket_iostream& operator=(basic_socket_iostream&& other)
+ {
+ std::basic_iostream<char>::operator=(std::move(other));
+ detail::socket_iostream_base<
+ Protocol BOOST_ASIO_SVC_TARG, Clock,
+ WaitTraits BOOST_ASIO_SVC_TARG1>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_STD_IOSTREAM_MOVE)
+ // || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
#if defined(GENERATING_DOCUMENTATION)
/// Establish a connection to an endpoint corresponding to a resolver query.
/**
@@ -160,8 +257,8 @@ public:
explicit basic_socket_iostream(T... x)
: std::basic_iostream<char>(
&this->detail::socket_iostream_base<
- Protocol, StreamSocketService, Time,
- TimeTraits, TimerService>::streambuf_)
+ Protocol BOOST_ASIO_SVC_TARG, Clock,
+ WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_)
{
this->setf(std::ios_base::unitbuf);
if (rdbuf()->connect(x...) == 0)
@@ -199,14 +296,20 @@ public:
}
/// Return a pointer to the underlying streambuf.
- basic_socket_streambuf<Protocol, StreamSocketService,
- Time, TimeTraits, TimerService>* rdbuf() const
+ basic_socket_streambuf<Protocol BOOST_ASIO_SVC_TARG,
+ Clock, WaitTraits BOOST_ASIO_SVC_TARG1>* rdbuf() const
{
- return const_cast<basic_socket_streambuf<Protocol, StreamSocketService,
- Time, TimeTraits, TimerService>*>(
+ return const_cast<basic_socket_streambuf<Protocol BOOST_ASIO_SVC_TARG,
+ Clock, WaitTraits BOOST_ASIO_SVC_TARG1>*>(
&this->detail::socket_iostream_base<
- Protocol, StreamSocketService, Time,
- TimeTraits, TimerService>::streambuf_);
+ Protocol BOOST_ASIO_SVC_TARG, Clock,
+ WaitTraits BOOST_ASIO_SVC_TARG1>::streambuf_);
+ }
+
+ /// Get a reference to the underlying socket.
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket()
+ {
+ return rdbuf()->socket();
}
/// Get the last error associated with the stream.
@@ -223,17 +326,29 @@ public:
*/
const boost::system::error_code& error() const
{
- return rdbuf()->puberror();
+ return rdbuf()->error();
}
- /// Get the stream's expiry time as an absolute time.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use expiry().) Get the stream's expiry time as an absolute
+ /// time.
/**
* @return An absolute time value representing the stream's expiry time.
*/
- time_type expires_at() const
+ time_point expires_at() const
{
return rdbuf()->expires_at();
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the stream's expiry time as an absolute time.
+ /**
+ * @return An absolute time value representing the stream's expiry time.
+ */
+ time_point expiry() const
+ {
+ return rdbuf()->expiry();
+ }
/// Set the stream's expiry time as an absolute time.
/**
@@ -244,21 +359,37 @@ public:
*
* @param expiry_time The expiry time to be used for the stream.
*/
- void expires_at(const time_type& expiry_time)
+ void expires_at(const time_point& expiry_time)
{
rdbuf()->expires_at(expiry_time);
}
- /// Get the timer's expiry time relative to now.
+ /// Set the stream's expiry time relative to now.
+ /**
+ * This function sets the expiry time associated with the stream. Stream
+ * operations performed after this time (where the operations cannot be
+ * completed using the internal buffers) will fail with the error
+ * boost::asio::error::operation_aborted.
+ *
+ * @param expiry_time The expiry time to be used for the timer.
+ */
+ void expires_after(const duration& expiry_time)
+ {
+ rdbuf()->expires_after(expiry_time);
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use expiry().) Get the stream's expiry time relative to now.
/**
* @return A relative time value representing the stream's expiry time.
*/
- duration_type expires_from_now() const
+ duration expires_from_now() const
{
return rdbuf()->expires_from_now();
}
- /// Set the stream's expiry time relative to now.
+ /// (Deprecated: Use expires_after().) Set the stream's expiry time relative
+ /// to now.
/**
* This function sets the expiry time associated with the stream. Stream
* operations performed after this time (where the operations cannot be
@@ -267,10 +398,17 @@ public:
*
* @param expiry_time The expiry time to be used for the timer.
*/
- void expires_from_now(const duration_type& expiry_time)
+ void expires_from_now(const duration& expiry_time)
{
rdbuf()->expires_from_now(expiry_time);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+private:
+ // Disallow copying and assignment.
+ basic_socket_iostream(const basic_socket_iostream&) BOOST_ASIO_DELETED;
+ basic_socket_iostream& operator=(
+ const basic_socket_iostream&) BOOST_ASIO_DELETED;
};
} // namespace asio
diff --git a/boost/asio/basic_socket_streambuf.hpp b/boost/asio/basic_socket_streambuf.hpp
index 922b005d88..352225b876 100644
--- a/boost/asio/basic_socket_streambuf.hpp
+++ b/boost/asio/basic_socket_streambuf.hpp
@@ -20,15 +20,24 @@
#if !defined(BOOST_ASIO_NO_IOSTREAM)
#include <streambuf>
+#include <vector>
#include <boost/asio/basic_socket.hpp>
-#include <boost/asio/deadline_timer_service.hpp>
-#include <boost/asio/detail/array.hpp>
+#include <boost/asio/basic_stream_socket.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/throw_error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/stream_socket_service.hpp>
+#include <boost/asio/io_context.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/stream_socket_service.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
-# include <boost/asio/deadline_timer.hpp>
+# if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/deadline_timer_service.hpp>
+# else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/detail/deadline_timer_service.hpp>
+# endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
#else
# include <boost/asio/steady_timer.hpp>
#endif
@@ -39,113 +48,214 @@
// A macro that should expand to:
// template <typename T1, ..., typename Tn>
-// basic_socket_streambuf<Protocol, StreamSocketService,
-// Time, TimeTraits, TimerService>* connect(
-// T1 x1, ..., Tn xn)
+// basic_socket_streambuf* connect(T1 x1, ..., Tn xn)
// {
// init_buffers();
-// this->basic_socket<Protocol, StreamSocketService>::close(ec_);
// typedef typename Protocol::resolver resolver_type;
-// typedef typename resolver_type::query resolver_query;
-// resolver_query query(x1, ..., xn);
-// resolve_and_connect(query);
+// resolver_type resolver(socket().get_executor().context());
+// connect_to_endpoints(
+// resolver.resolve(x1, ..., xn, ec_));
// return !ec_ ? this : 0;
// }
// This macro should only persist within this file.
# define BOOST_ASIO_PRIVATE_CONNECT_DEF(n) \
template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
- basic_socket_streambuf<Protocol, StreamSocketService, \
- Time, TimeTraits, TimerService>* connect(BOOST_ASIO_VARIADIC_PARAMS(n)) \
+ basic_socket_streambuf* connect(BOOST_ASIO_VARIADIC_BYVAL_PARAMS(n)) \
{ \
init_buffers(); \
- this->basic_socket<Protocol, StreamSocketService>::close(ec_); \
typedef typename Protocol::resolver resolver_type; \
- typedef typename resolver_type::query resolver_query; \
- resolver_query query(BOOST_ASIO_VARIADIC_ARGS(n)); \
- resolve_and_connect(query); \
+ resolver_type resolver(socket().get_executor().context()); \
+ connect_to_endpoints( \
+ resolver.resolve(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n), ec_)); \
return !ec_ ? this : 0; \
} \
/**/
#endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# define BOOST_ASIO_SVC_T1 detail::deadline_timer_service<traits_helper>
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace detail {
-// A separate base class is used to ensure that the io_service is initialised
-// prior to the basic_socket_streambuf's basic_socket base class.
-class socket_streambuf_base
+// A separate base class is used to ensure that the io_context member is
+// initialised prior to the basic_socket_streambuf's basic_socket base class.
+class socket_streambuf_io_context
+{
+protected:
+ socket_streambuf_io_context(io_context* ctx)
+ : default_io_context_(ctx)
+ {
+ }
+
+ shared_ptr<io_context> default_io_context_;
+};
+
+// A separate base class is used to ensure that the dynamically allocated
+// buffers are constructed prior to the basic_socket_streambuf's basic_socket
+// base class. This makes moving the socket is the last potentially throwing
+// step in the streambuf's move constructor, giving the constructor a strong
+// exception safety guarantee.
+class socket_streambuf_buffers
{
protected:
- io_service io_service_;
+ socket_streambuf_buffers()
+ : get_buffer_(buffer_size),
+ put_buffer_(buffer_size)
+ {
+ }
+
+ enum { buffer_size = 512 };
+ std::vector<char> get_buffer_;
+ std::vector<char> put_buffer_;
};
} // namespace detail
-/// Iostream streambuf for a socket.
-template <typename Protocol,
- typename StreamSocketService = stream_socket_service<Protocol>,
-#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
- || defined(GENERATING_DOCUMENTATION)
- typename Time = boost::posix_time::ptime,
- typename TimeTraits = boost::asio::time_traits<Time>,
- typename TimerService = deadline_timer_service<Time, TimeTraits> >
+#if !defined(BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)
+#define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL
+
+// Forward declaration with defaulted arguments.
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>),
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ typename Clock = boost::posix_time::ptime,
+ typename WaitTraits = time_traits<Clock>
+ BOOST_ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)>
#else
- typename Time = steady_timer::clock_type,
- typename TimeTraits = steady_timer::traits_type,
- typename TimerService = steady_timer::service_type>
+ typename Clock = chrono::steady_clock,
+ typename WaitTraits = wait_traits<Clock>
+ BOOST_ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)>
#endif
+class basic_socket_streambuf;
+
+#endif // !defined(BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)
+
+/// Iostream streambuf for a socket.
+#if defined(GENERATING_DOCUMENTATION)
+template <typename Protocol,
+ typename Clock = chrono::steady_clock,
+ typename WaitTraits = wait_traits<Clock> >
+#else // defined(GENERATING_DOCUMENTATION)
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename Clock, typename WaitTraits BOOST_ASIO_SVC_TPARAM1>
+#endif // defined(GENERATING_DOCUMENTATION)
class basic_socket_streambuf
: public std::streambuf,
- private detail::socket_streambuf_base,
- public basic_socket<Protocol, StreamSocketService>
+ private detail::socket_streambuf_io_context,
+ private detail::socket_streambuf_buffers,
+#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ private basic_socket<Protocol BOOST_ASIO_SVC_TARG>
+#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+ public basic_socket<Protocol BOOST_ASIO_SVC_TARG>
+#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
{
private:
// These typedefs are intended keep this class's implementation independent
- // of whether it's using Boost.DateTime, Boost.Chrono or std::chrono.
+ // of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
- typedef TimeTraits traits_helper;
+ typedef WaitTraits traits_helper;
#else
- typedef detail::chrono_time_traits<Time, TimeTraits> traits_helper;
+ typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
#endif
public:
+ /// The protocol type.
+ typedef Protocol protocol_type;
+
/// The endpoint type.
typedef typename Protocol::endpoint endpoint_type;
+ /// The clock type.
+ typedef Clock clock_type;
+
#if defined(GENERATING_DOCUMENTATION)
+ /// (Deprecated: Use time_point.) The time type.
+ typedef typename WaitTraits::time_type time_type;
+
/// The time type.
- typedef typename TimeTraits::time_type time_type;
+ typedef typename WaitTraits::time_point time_point;
+
+ /// (Deprecated: Use duration.) The duration type.
+ typedef typename WaitTraits::duration_type duration_type;
/// The duration type.
- typedef typename TimeTraits::duration_type duration_type;
+ typedef typename WaitTraits::duration duration;
#else
+# if !defined(BOOST_ASIO_NO_DEPRECATED)
typedef typename traits_helper::time_type time_type;
typedef typename traits_helper::duration_type duration_type;
+# endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ typedef typename traits_helper::time_type time_point;
+ typedef typename traits_helper::duration_type duration;
#endif
/// Construct a basic_socket_streambuf without establishing a connection.
basic_socket_streambuf()
- : basic_socket<Protocol, StreamSocketService>(
- this->detail::socket_streambuf_base::io_service_),
- unbuffered_(false),
- timer_service_(0),
- timer_state_(no_timer)
+ : detail::socket_streambuf_io_context(new io_context),
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>(*default_io_context_),
+ expiry_time_(max_expiry_time())
+ {
+ init_buffers();
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Construct a basic_socket_streambuf from the supplied socket.
+ explicit basic_socket_streambuf(basic_stream_socket<protocol_type> s)
+ : detail::socket_streambuf_io_context(0),
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(s)),
+ expiry_time_(max_expiry_time())
{
init_buffers();
}
+ /// Move-construct a basic_socket_streambuf from another.
+ basic_socket_streambuf(basic_socket_streambuf&& other)
+ : detail::socket_streambuf_io_context(other),
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other.socket())),
+ ec_(other.ec_),
+ expiry_time_(other.expiry_time_)
+ {
+ get_buffer_.swap(other.get_buffer_);
+ put_buffer_.swap(other.put_buffer_);
+ setg(other.eback(), other.gptr(), other.egptr());
+ setp(other.pptr(), other.epptr());
+ other.ec_ = boost::system::error_code();
+ other.expiry_time_ = max_expiry_time();
+ other.init_buffers();
+ }
+
+ /// Move-assign a basic_socket_streambuf from another.
+ basic_socket_streambuf& operator=(basic_socket_streambuf&& other)
+ {
+ this->close();
+ socket() = std::move(other.socket());
+ detail::socket_streambuf_io_context::operator=(other);
+ ec_ = other.ec_;
+ expiry_time_ = other.expiry_time_;
+ get_buffer_.swap(other.get_buffer_);
+ put_buffer_.swap(other.put_buffer_);
+ setg(other.eback(), other.gptr(), other.egptr());
+ setp(other.pptr(), other.epptr());
+ other.ec_ = boost::system::error_code();
+ other.expiry_time_ = max_expiry_time();
+ other.put_buffer_.resize(buffer_size);
+ other.init_buffers();
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
/// Destructor flushes buffered data.
virtual ~basic_socket_streambuf()
{
if (pptr() != pbase())
overflow(traits_type::eof());
-
- destroy_timer();
}
/// Establish a connection.
@@ -155,29 +265,11 @@ public:
* @return \c this if a connection was successfully established, a null
* pointer otherwise.
*/
- basic_socket_streambuf<Protocol, StreamSocketService,
- Time, TimeTraits, TimerService>* connect(
- const endpoint_type& endpoint)
+ basic_socket_streambuf* connect(const endpoint_type& endpoint)
{
init_buffers();
-
- this->basic_socket<Protocol, StreamSocketService>::close(ec_);
-
- if (timer_state_ == timer_has_expired)
- {
- ec_ = boost::asio::error::operation_aborted;
- return 0;
- }
-
- io_handler handler = { this };
- this->basic_socket<Protocol, StreamSocketService>::async_connect(
- endpoint, handler);
-
- ec_ = boost::asio::error::would_block;
- this->get_service().get_io_service().reset();
- do this->get_service().get_io_service().run_one();
- while (ec_ == boost::asio::error::would_block);
-
+ ec_ = boost::system::error_code();
+ this->connect_to_endpoints(&endpoint, &endpoint + 1);
return !ec_ ? this : 0;
}
@@ -192,19 +284,15 @@ public:
* pointer otherwise.
*/
template <typename T1, ..., typename TN>
- basic_socket_streambuf<Protocol, StreamSocketService>* connect(
- T1 t1, ..., TN tn);
+ basic_socket_streambuf* connect(T1 t1, ..., TN tn);
#elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
template <typename... T>
- basic_socket_streambuf<Protocol, StreamSocketService,
- Time, TimeTraits, TimerService>* connect(T... x)
+ basic_socket_streambuf* connect(T... x)
{
init_buffers();
- this->basic_socket<Protocol, StreamSocketService>::close(ec_);
typedef typename Protocol::resolver resolver_type;
- typedef typename resolver_type::query resolver_query;
- resolver_query query(x...);
- resolve_and_connect(query);
+ resolver_type resolver(socket().get_executor().context());
+ connect_to_endpoints(resolver.resolve(x..., ec_));
return !ec_ ? this : 0;
}
#else
@@ -216,36 +304,63 @@ public:
* @return \c this if a connection was successfully established, a null
* pointer otherwise.
*/
- basic_socket_streambuf<Protocol, StreamSocketService,
- Time, TimeTraits, TimerService>* close()
+ basic_socket_streambuf* close()
{
sync();
- this->basic_socket<Protocol, StreamSocketService>::close(ec_);
+ socket().close(ec_);
if (!ec_)
init_buffers();
return !ec_ ? this : 0;
}
+ /// Get a reference to the underlying socket.
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket()
+ {
+ return *this;
+ }
+
/// Get the last error associated with the stream buffer.
/**
* @return An \c error_code corresponding to the last error from the stream
* buffer.
*/
+ const boost::system::error_code& error() const
+ {
+ return ec_;
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use error().) Get the last error associated with the stream
+ /// buffer.
+ /**
+ * @return An \c error_code corresponding to the last error from the stream
+ * buffer.
+ */
const boost::system::error_code& puberror() const
{
return error();
}
+ /// (Deprecated: Use expiry().) Get the stream buffer's expiry time as an
+ /// absolute time.
+ /**
+ * @return An absolute time value representing the stream buffer's expiry
+ * time.
+ */
+ time_point expires_at() const
+ {
+ return expiry_time_;
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
/// Get the stream buffer's expiry time as an absolute time.
/**
* @return An absolute time value representing the stream buffer's expiry
* time.
*/
- time_type expires_at() const
+ time_point expiry() const
{
- return timer_service_
- ? timer_service_->expires_at(timer_implementation_)
- : time_type();
+ return expiry_time_;
}
/// Set the stream buffer's expiry time as an absolute time.
@@ -257,27 +372,38 @@ public:
*
* @param expiry_time The expiry time to be used for the stream.
*/
- void expires_at(const time_type& expiry_time)
+ void expires_at(const time_point& expiry_time)
{
- construct_timer();
-
- boost::system::error_code ec;
- timer_service_->expires_at(timer_implementation_, expiry_time, ec);
- boost::asio::detail::throw_error(ec, "expires_at");
+ expiry_time_ = expiry_time;
+ }
- start_timer();
+ /// Set the stream buffer's expiry time relative to now.
+ /**
+ * This function sets the expiry time associated with the stream. Stream
+ * operations performed after this time (where the operations cannot be
+ * completed using the internal buffers) will fail with the error
+ * boost::asio::error::operation_aborted.
+ *
+ * @param expiry_time The expiry time to be used for the timer.
+ */
+ void expires_after(const duration& expiry_time)
+ {
+ expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
}
- /// Get the stream buffer's expiry time relative to now.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use expiry().) Get the stream buffer's expiry time relative
+ /// to now.
/**
* @return A relative time value representing the stream buffer's expiry time.
*/
- duration_type expires_from_now() const
+ duration expires_from_now() const
{
return traits_helper::subtract(expires_at(), traits_helper::now());
}
- /// Set the stream buffer's expiry time relative to now.
+ /// (Deprecated: Use expires_after().) Set the stream buffer's expiry time
+ /// relative to now.
/**
* This function sets the expiry time associated with the stream. Stream
* operations performed after this time (where the operations cannot be
@@ -286,109 +412,126 @@ public:
*
* @param expiry_time The expiry time to be used for the timer.
*/
- void expires_from_now(const duration_type& expiry_time)
+ void expires_from_now(const duration& expiry_time)
{
- construct_timer();
-
- boost::system::error_code ec;
- timer_service_->expires_from_now(timer_implementation_, expiry_time, ec);
- boost::asio::detail::throw_error(ec, "expires_from_now");
-
- start_timer();
+ expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
protected:
int_type underflow()
{
- if (gptr() == egptr())
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ec_ = boost::asio::error::operation_not_supported;
+ return traits_type::eof();
+#else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ if (gptr() != egptr())
+ return traits_type::eof();
+
+ for (;;)
{
- if (timer_state_ == timer_has_expired)
+ // Check if we are past the expiry time.
+ if (traits_helper::less_than(expiry_time_, traits_helper::now()))
{
- ec_ = boost::asio::error::operation_aborted;
+ ec_ = boost::asio::error::timed_out;
return traits_type::eof();
}
- io_handler handler = { this };
- this->get_service().async_receive(this->get_implementation(),
- boost::asio::buffer(boost::asio::buffer(get_buffer_) + putback_max),
- 0, handler);
+ // Try to complete the operation without blocking.
+ if (!socket().native_non_blocking())
+ socket().native_non_blocking(true, ec_);
+ detail::buffer_sequence_adapter<mutable_buffer, mutable_buffer>
+ bufs(boost::asio::buffer(get_buffer_) + putback_max);
+ detail::signed_size_type bytes = detail::socket_ops::recv(
+ socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
- ec_ = boost::asio::error::would_block;
- this->get_service().get_io_service().reset();
- do this->get_service().get_io_service().run_one();
- while (ec_ == boost::asio::error::would_block);
- if (ec_)
+ // Check if operation succeeded.
+ if (bytes > 0)
+ {
+ setg(&get_buffer_[0], &get_buffer_[0] + putback_max,
+ &get_buffer_[0] + putback_max + bytes);
+ return traits_type::to_int_type(*gptr());
+ }
+
+ // Check for EOF.
+ if (bytes == 0)
+ {
+ ec_ = boost::asio::error::eof;
return traits_type::eof();
+ }
- setg(&get_buffer_[0], &get_buffer_[0] + putback_max,
- &get_buffer_[0] + putback_max + bytes_transferred_);
- return traits_type::to_int_type(*gptr());
- }
- else
- {
- return traits_type::eof();
+ // Operation failed.
+ if (ec_ != boost::asio::error::would_block
+ && ec_ != boost::asio::error::try_again)
+ return traits_type::eof();
+
+ // Wait for socket to become ready.
+ if (detail::socket_ops::poll_read(
+ socket().native_handle(), 0, timeout(), ec_) < 0)
+ return traits_type::eof();
}
+#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
}
int_type overflow(int_type c)
{
- if (unbuffered_)
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ec_ = boost::asio::error::operation_not_supported;
+ return traits_type::eof();
+#else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ char_type ch = traits_type::to_char_type(c);
+
+ // Determine what needs to be sent.
+ const_buffer output_buffer;
+ if (put_buffer_.empty())
{
if (traits_type::eq_int_type(c, traits_type::eof()))
+ return traits_type::not_eof(c); // Nothing to do.
+ output_buffer = boost::asio::buffer(&ch, sizeof(char_type));
+ }
+ else
+ {
+ output_buffer = boost::asio::buffer(pbase(),
+ (pptr() - pbase()) * sizeof(char_type));
+ }
+
+ while (output_buffer.size() > 0)
+ {
+ // Check if we are past the expiry time.
+ if (traits_helper::less_than(expiry_time_, traits_helper::now()))
{
- // Nothing to do.
- return traits_type::not_eof(c);
+ ec_ = boost::asio::error::timed_out;
+ return traits_type::eof();
}
- else
+
+ // Try to complete the operation without blocking.
+ if (!socket().native_non_blocking())
+ socket().native_non_blocking(true, ec_);
+ detail::buffer_sequence_adapter<
+ const_buffer, const_buffer> bufs(output_buffer);
+ detail::signed_size_type bytes = detail::socket_ops::send(
+ socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
+
+ // Check if operation succeeded.
+ if (bytes > 0)
{
- if (timer_state_ == timer_has_expired)
- {
- ec_ = boost::asio::error::operation_aborted;
- return traits_type::eof();
- }
-
- // Send the single character immediately.
- char_type ch = traits_type::to_char_type(c);
- io_handler handler = { this };
- this->get_service().async_send(this->get_implementation(),
- boost::asio::buffer(&ch, sizeof(char_type)), 0, handler);
-
- ec_ = boost::asio::error::would_block;
- this->get_service().get_io_service().reset();
- do this->get_service().get_io_service().run_one();
- while (ec_ == boost::asio::error::would_block);
- if (ec_)
- return traits_type::eof();
-
- return c;
+ output_buffer += static_cast<std::size_t>(bytes);
+ continue;
}
+
+ // Operation failed.
+ if (ec_ != boost::asio::error::would_block
+ && ec_ != boost::asio::error::try_again)
+ return traits_type::eof();
+
+ // Wait for socket to become ready.
+ if (detail::socket_ops::poll_write(
+ socket().native_handle(), 0, timeout(), ec_) < 0)
+ return traits_type::eof();
}
- else
+
+ if (!put_buffer_.empty())
{
- // Send all data in the output buffer.
- boost::asio::const_buffer buffer =
- boost::asio::buffer(pbase(), pptr() - pbase());
- while (boost::asio::buffer_size(buffer) > 0)
- {
- if (timer_state_ == timer_has_expired)
- {
- ec_ = boost::asio::error::operation_aborted;
- return traits_type::eof();
- }
-
- io_handler handler = { this };
- this->get_service().async_send(this->get_implementation(),
- boost::asio::buffer(buffer), 0, handler);
-
- ec_ = boost::asio::error::would_block;
- this->get_service().get_io_service().reset();
- do this->get_service().get_io_service().run_one();
- while (ec_ == boost::asio::error::would_block);
- if (ec_)
- return traits_type::eof();
-
- buffer = buffer + bytes_transferred_;
- }
setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
// If the new character is eof then our work here is done.
@@ -396,10 +539,12 @@ protected:
return traits_type::not_eof(c);
// Add the new character to the output buffer.
- *pptr() = traits_type::to_char_type(c);
+ *pptr() = ch;
pbump(1);
- return c;
}
+
+ return c;
+#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
}
int sync()
@@ -411,148 +556,127 @@ protected:
{
if (pptr() == pbase() && s == 0 && n == 0)
{
- unbuffered_ = true;
+ put_buffer_.clear();
setp(0, 0);
+ sync();
return this;
}
return 0;
}
- /// Get the last error associated with the stream buffer.
- /**
- * @return An \c error_code corresponding to the last error from the stream
- * buffer.
- */
- virtual const boost::system::error_code& error() const
- {
- return ec_;
- }
-
private:
+ // Disallow copying and assignment.
+ basic_socket_streambuf(const basic_socket_streambuf&) BOOST_ASIO_DELETED;
+ basic_socket_streambuf& operator=(
+ const basic_socket_streambuf&) BOOST_ASIO_DELETED;
+
void init_buffers()
{
setg(&get_buffer_[0],
&get_buffer_[0] + putback_max,
&get_buffer_[0] + putback_max);
- if (unbuffered_)
+
+ if (put_buffer_.empty())
setp(0, 0);
else
setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
}
- template <typename ResolverQuery>
- void resolve_and_connect(const ResolverQuery& query)
+ int timeout() const
{
- typedef typename Protocol::resolver resolver_type;
- typedef typename resolver_type::iterator iterator_type;
- resolver_type resolver(detail::socket_streambuf_base::io_service_);
- iterator_type i = resolver.resolve(query, ec_);
- if (!ec_)
- {
- iterator_type end;
- ec_ = boost::asio::error::host_not_found;
- while (ec_ && i != end)
- {
- this->basic_socket<Protocol, StreamSocketService>::close(ec_);
-
- if (timer_state_ == timer_has_expired)
- {
- ec_ = boost::asio::error::operation_aborted;
- return;
- }
-
- io_handler handler = { this };
- this->basic_socket<Protocol, StreamSocketService>::async_connect(
- *i, handler);
-
- ec_ = boost::asio::error::would_block;
- this->get_service().get_io_service().reset();
- do this->get_service().get_io_service().run_one();
- while (ec_ == boost::asio::error::would_block);
-
- ++i;
- }
- }
+ int64_t msec = traits_helper::to_posix_duration(
+ traits_helper::subtract(expiry_time_,
+ traits_helper::now())).total_milliseconds();
+ if (msec > (std::numeric_limits<int>::max)())
+ msec = (std::numeric_limits<int>::max)();
+ else if (msec < 0)
+ msec = 0;
+ return static_cast<int>(msec);
}
- struct io_handler;
- friend struct io_handler;
- struct io_handler
+ template <typename EndpointSequence>
+ void connect_to_endpoints(const EndpointSequence& endpoints)
{
- basic_socket_streambuf* this_;
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred = 0)
- {
- this_->ec_ = ec;
- this_->bytes_transferred_ = bytes_transferred;
- }
- };
+ this->connect_to_endpoints(endpoints.begin(), endpoints.end());
+ }
- struct timer_handler;
- friend struct timer_handler;
- struct timer_handler
+ template <typename EndpointIterator>
+ void connect_to_endpoints(EndpointIterator begin, EndpointIterator end)
{
- basic_socket_streambuf* this_;
-
- void operator()(const boost::system::error_code&)
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ ec_ = boost::asio::error::operation_not_supported;
+#else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ if (ec_)
+ return;
+
+ ec_ = boost::asio::error::not_found;
+ for (EndpointIterator i = begin; i != end; ++i)
{
- time_type now = traits_helper::now();
-
- time_type expiry_time = this_->timer_service_->expires_at(
- this_->timer_implementation_);
-
- if (traits_helper::less_than(now, expiry_time))
+ // Check if we are past the expiry time.
+ if (traits_helper::less_than(expiry_time_, traits_helper::now()))
{
- this_->timer_state_ = timer_is_pending;
- this_->timer_service_->async_wait(this_->timer_implementation_, *this);
+ ec_ = boost::asio::error::timed_out;
+ return;
}
- else
- {
- this_->timer_state_ = timer_has_expired;
- boost::system::error_code ec;
- this_->basic_socket<Protocol, StreamSocketService>::close(ec);
- }
- }
- };
- void construct_timer()
- {
- if (timer_service_ == 0)
- {
- TimerService& timer_service = use_service<TimerService>(
- detail::socket_streambuf_base::io_service_);
- timer_service.construct(timer_implementation_);
- timer_service_ = &timer_service;
+ // Close and reopen the socket.
+ typename Protocol::endpoint ep(*i);
+ socket().close(ec_);
+ socket().open(ep.protocol(), ec_);
+ if (ec_)
+ continue;
+
+ // Try to complete the operation without blocking.
+ if (!socket().native_non_blocking())
+ socket().native_non_blocking(true, ec_);
+ detail::socket_ops::connect(socket().native_handle(),
+ ep.data(), ep.size(), ec_);
+
+ // Check if operation succeeded.
+ if (!ec_)
+ return;
+
+ // Operation failed.
+ if (ec_ != boost::asio::error::in_progress
+ && ec_ != boost::asio::error::would_block)
+ continue;
+
+ // Wait for socket to become ready.
+ if (detail::socket_ops::poll_connect(
+ socket().native_handle(), timeout(), ec_) < 0)
+ continue;
+
+ // Get the error code from the connect operation.
+ int connect_error = 0;
+ size_t connect_error_len = sizeof(connect_error);
+ if (detail::socket_ops::getsockopt(socket().native_handle(), 0,
+ SOL_SOCKET, SO_ERROR, &connect_error, &connect_error_len, ec_)
+ == detail::socket_error_retval)
+ return;
+
+ // Check the result of the connect operation.
+ ec_ = boost::system::error_code(connect_error,
+ boost::asio::error::get_system_category());
+ if (!ec_)
+ return;
}
+#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
}
- void destroy_timer()
+ // Helper function to get the maximum expiry time.
+ static time_point max_expiry_time()
{
- if (timer_service_)
- timer_service_->destroy(timer_implementation_);
- }
-
- void start_timer()
- {
- if (timer_state_ != timer_is_pending)
- {
- timer_handler handler = { this };
- handler(boost::system::error_code());
- }
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ return boost::posix_time::pos_infin;
+#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+ return (time_point::max)();
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
}
enum { putback_max = 8 };
- enum { buffer_size = 512 };
- boost::asio::detail::array<char, buffer_size> get_buffer_;
- boost::asio::detail::array<char, buffer_size> put_buffer_;
- bool unbuffered_;
boost::system::error_code ec_;
- std::size_t bytes_transferred_;
- TimerService* timer_service_;
- typename TimerService::implementation_type timer_implementation_;
- enum state { no_timer, timer_is_pending, timer_has_expired } timer_state_;
+ time_point expiry_time_;
};
} // namespace asio
@@ -560,6 +684,10 @@ private:
#include <boost/asio/detail/pop_options.hpp>
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# undef BOOST_ASIO_SVC_T1
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
# undef BOOST_ASIO_PRIVATE_CONNECT_DEF
#endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
diff --git a/boost/asio/basic_stream_socket.hpp b/boost/asio/basic_stream_socket.hpp
index 5b959d7db8..709e214a37 100644
--- a/boost/asio/basic_stream_socket.hpp
+++ b/boost/asio/basic_stream_socket.hpp
@@ -22,7 +22,10 @@
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/stream_socket_service.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/stream_socket_service.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
#include <boost/asio/detail/push_options.hpp>
@@ -41,18 +44,19 @@ namespace asio {
* @par Concepts:
* AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
*/
-template <typename Protocol,
- typename StreamSocketService = stream_socket_service<Protocol> >
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>)>
class basic_stream_socket
- : public basic_socket<Protocol, StreamSocketService>
+ : public basic_socket<Protocol BOOST_ASIO_SVC_TARG>
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// socket.
- typedef typename StreamSocketService::native_handle_type native_type;
-
/// The native representation of a socket.
- typedef typename StreamSocketService::native_handle_type native_handle_type;
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef typename basic_socket<
+ Protocol BOOST_ASIO_SVC_TARG>::native_handle_type native_handle_type;
+#endif
/// The protocol type.
typedef Protocol protocol_type;
@@ -66,11 +70,11 @@ public:
* needs to be opened and then connected or accepted before data can be sent
* or received on it.
*
- * @param io_service The io_service object that the stream socket will use to
+ * @param io_context The io_context object that the stream socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*/
- explicit basic_stream_socket(boost::asio::io_service& io_service)
- : basic_socket<Protocol, StreamSocketService>(io_service)
+ explicit basic_stream_socket(boost::asio::io_context& io_context)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context)
{
}
@@ -79,16 +83,16 @@ public:
* This constructor creates and opens a stream socket. The socket needs to be
* connected or accepted before data can be sent or received on it.
*
- * @param io_service The io_service object that the stream socket will use to
+ * @param io_context The io_context object that the stream socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_stream_socket(boost::asio::io_service& io_service,
+ basic_stream_socket(boost::asio::io_context& io_context,
const protocol_type& protocol)
- : basic_socket<Protocol, StreamSocketService>(io_service, protocol)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, protocol)
{
}
@@ -99,7 +103,7 @@ public:
* to the specified endpoint on the local machine. The protocol used is the
* protocol associated with the given endpoint.
*
- * @param io_service The io_service object that the stream socket will use to
+ * @param io_context The io_context object that the stream socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param endpoint An endpoint on the local machine to which the stream
@@ -107,9 +111,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_stream_socket(boost::asio::io_service& io_service,
+ basic_stream_socket(boost::asio::io_context& io_context,
const endpoint_type& endpoint)
- : basic_socket<Protocol, StreamSocketService>(io_service, endpoint)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(io_context, endpoint)
{
}
@@ -118,7 +122,7 @@ public:
* This constructor creates a stream socket object to hold an existing native
* socket.
*
- * @param io_service The io_service object that the stream socket will use to
+ * @param io_context The io_context object that the stream socket will use to
* dispatch handlers for any asynchronous operations performed on the socket.
*
* @param protocol An object specifying protocol parameters to be used.
@@ -127,10 +131,10 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_stream_socket(boost::asio::io_service& io_service,
+ basic_stream_socket(boost::asio::io_context& io_context,
const protocol_type& protocol, const native_handle_type& native_socket)
- : basic_socket<Protocol, StreamSocketService>(
- io_service, protocol, native_socket)
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(
+ io_context, protocol, native_socket)
{
}
@@ -143,11 +147,10 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_stream_socket(io_service&) constructor.
+ * constructed using the @c basic_stream_socket(io_context&) constructor.
*/
basic_stream_socket(basic_stream_socket&& other)
- : basic_socket<Protocol, StreamSocketService>(
- BOOST_ASIO_MOVE_CAST(basic_stream_socket)(other))
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
{
}
@@ -159,12 +162,11 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_stream_socket(io_service&) constructor.
+ * constructed using the @c basic_stream_socket(io_context&) constructor.
*/
basic_stream_socket& operator=(basic_stream_socket&& other)
{
- basic_socket<Protocol, StreamSocketService>::operator=(
- BOOST_ASIO_MOVE_CAST(basic_stream_socket)(other));
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
return *this;
}
@@ -177,15 +179,13 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_stream_socket(io_service&) constructor.
+ * constructed using the @c basic_stream_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename StreamSocketService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
basic_stream_socket(
- basic_stream_socket<Protocol1, StreamSocketService1>&& other,
+ basic_stream_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other,
typename enable_if<is_convertible<Protocol1, Protocol>::value>::type* = 0)
- : basic_socket<Protocol, StreamSocketService>(
- BOOST_ASIO_MOVE_CAST2(basic_stream_socket<
- Protocol1, StreamSocketService1>)(other))
+ : basic_socket<Protocol BOOST_ASIO_SVC_TARG>(std::move(other))
{
}
@@ -197,20 +197,27 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_stream_socket(io_service&) constructor.
+ * constructed using the @c basic_stream_socket(io_context&) constructor.
*/
- template <typename Protocol1, typename StreamSocketService1>
+ template <typename Protocol1 BOOST_ASIO_SVC_TPARAM1>
typename enable_if<is_convertible<Protocol1, Protocol>::value,
basic_stream_socket>::type& operator=(
- basic_stream_socket<Protocol1, StreamSocketService1>&& other)
+ basic_stream_socket<Protocol1 BOOST_ASIO_SVC_TARG1>&& other)
{
- basic_socket<Protocol, StreamSocketService>::operator=(
- BOOST_ASIO_MOVE_CAST2(basic_stream_socket<
- Protocol1, StreamSocketService1>)(other));
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>::operator=(std::move(other));
return *this;
}
#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Destroys the socket.
+ /**
+ * This function destroys the socket, cancelling any outstanding asynchronous
+ * operations associated with the socket as if by calling @c cancel.
+ */
+ ~basic_stream_socket()
+ {
+ }
+
/// Send some data on the socket.
/**
* This function is used to send data on the stream socket. The function
@@ -330,7 +337,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -355,9 +362,20 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(
this->get_implementation(), buffers, 0,
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(
+ this->get_implementation(), buffers, 0,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous send.
@@ -382,7 +400,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -408,9 +426,20 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(
this->get_implementation(), buffers, flags,
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(
+ this->get_implementation(), buffers, flags,
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Receive some data on the socket.
@@ -538,7 +567,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -565,8 +594,18 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Start an asynchronous receive.
@@ -591,7 +630,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -619,8 +658,18 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, flags, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, flags, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Write some data to the socket.
@@ -703,7 +752,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -728,8 +777,18 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_send(this->get_implementation(),
buffers, 0, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_send(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
/// Read some data from the socket.
@@ -815,7 +874,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -841,8 +900,18 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
return this->get_service().async_receive(this->get_implementation(),
buffers, 0, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_receive(this->get_implementation(),
+ buffers, 0, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
};
diff --git a/boost/asio/basic_streambuf.hpp b/boost/asio/basic_streambuf.hpp
index 1392596dc5..d8bfecd6b6 100644
--- a/boost/asio/basic_streambuf.hpp
+++ b/boost/asio/basic_streambuf.hpp
@@ -120,8 +120,8 @@ public:
/// The type used to represent the output sequence as a list of buffers.
typedef implementation_defined mutable_buffers_type;
#else
- typedef boost::asio::const_buffers_1 const_buffers_type;
- typedef boost::asio::mutable_buffers_1 mutable_buffers_type;
+ typedef BOOST_ASIO_CONST_BUFFER const_buffers_type;
+ typedef BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_type;
#endif
/// Construct a basic_streambuf object.
@@ -152,11 +152,11 @@ public:
* while (i != bufs.end())
* {
* const_buffer buf(*i++);
- * s += buffer_size(buf);
+ * s += buf.size();
* }
* @endcode
*/
- std::size_t size() const
+ std::size_t size() const BOOST_ASIO_NOEXCEPT
{
return pptr() - gptr();
}
@@ -166,11 +166,21 @@ public:
* @returns The allowed maximum of the sum of the sizes of the input sequence
* and output sequence.
*/
- std::size_t max_size() const
+ std::size_t max_size() const BOOST_ASIO_NOEXCEPT
{
return max_size_;
}
+ /// Get the current capacity of the basic_streambuf.
+ /**
+ * @returns The current total capacity of the streambuf, i.e. for both the
+ * input sequence and output sequence.
+ */
+ std::size_t capacity() const BOOST_ASIO_NOEXCEPT
+ {
+ return buffer_.capacity();
+ }
+
/// Get a list of buffers that represents the input sequence.
/**
* @returns An object of type @c const_buffers_type that satisfies
@@ -180,7 +190,7 @@ public:
* @note The returned object is invalidated by any @c basic_streambuf member
* function that modifies the input sequence or output sequence.
*/
- const_buffers_type data() const
+ const_buffers_type data() const BOOST_ASIO_NOEXCEPT
{
return boost::asio::buffer(boost::asio::const_buffer(gptr(),
(pptr() - gptr()) * sizeof(char_type)));
@@ -223,8 +233,7 @@ public:
*/
void commit(std::size_t n)
{
- if (pptr() + n > epptr())
- n = epptr() - pptr();
+ n = std::min<std::size_t>(n, epptr() - pptr());
pbump(static_cast<int>(n));
setg(eback(), gptr(), pptr());
}
@@ -351,15 +360,89 @@ private:
}
};
-// Helper function to get the preferred size for reading data. Used for any
-// user-provided specialisations of basic_streambuf.
+/// Adapts basic_streambuf to the dynamic buffer sequence type requirements.
+#if defined(GENERATING_DOCUMENTATION)
+template <typename Allocator = std::allocator<char> >
+#else
template <typename Allocator>
-inline std::size_t read_size_helper(
- basic_streambuf<Allocator>& sb, std::size_t max_size)
+#endif
+class basic_streambuf_ref
{
- return std::min<std::size_t>(512,
- std::min<std::size_t>(max_size, sb.max_size() - sb.size()));
-}
+public:
+ /// The type used to represent the input sequence as a list of buffers.
+ typedef typename basic_streambuf<Allocator>::const_buffers_type
+ const_buffers_type;
+
+ /// The type used to represent the output sequence as a list of buffers.
+ typedef typename basic_streambuf<Allocator>::mutable_buffers_type
+ mutable_buffers_type;
+
+ /// Construct a basic_streambuf_ref for the given basic_streambuf object.
+ explicit basic_streambuf_ref(basic_streambuf<Allocator>& sb)
+ : sb_(sb)
+ {
+ }
+
+ /// Copy construct a basic_streambuf_ref.
+ basic_streambuf_ref(const basic_streambuf_ref& other) BOOST_ASIO_NOEXCEPT
+ : sb_(other.sb_)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move construct a basic_streambuf_ref.
+ basic_streambuf_ref(basic_streambuf_ref&& other) BOOST_ASIO_NOEXCEPT
+ : sb_(other.sb_)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Get the size of the input sequence.
+ std::size_t size() const BOOST_ASIO_NOEXCEPT
+ {
+ return sb_.size();
+ }
+
+ /// Get the maximum size of the dynamic buffer.
+ std::size_t max_size() const BOOST_ASIO_NOEXCEPT
+ {
+ return sb_.max_size();
+ }
+
+ /// Get the current capacity of the dynamic buffer.
+ std::size_t capacity() const BOOST_ASIO_NOEXCEPT
+ {
+ return sb_.capacity();
+ }
+
+ /// Get a list of buffers that represents the input sequence.
+ const_buffers_type data() const BOOST_ASIO_NOEXCEPT
+ {
+ return sb_.data();
+ }
+
+ /// Get a list of buffers that represents the output sequence, with the given
+ /// size.
+ mutable_buffers_type prepare(std::size_t n)
+ {
+ return sb_.prepare(n);
+ }
+
+ /// Move bytes from the output sequence to the input sequence.
+ void commit(std::size_t n)
+ {
+ return sb_.commit(n);
+ }
+
+ /// Remove characters from the input sequence.
+ void consume(std::size_t n)
+ {
+ return sb_.consume(n);
+ }
+
+private:
+ basic_streambuf<Allocator>& sb_;
+};
} // namespace asio
} // namespace boost
diff --git a/boost/asio/basic_streambuf_fwd.hpp b/boost/asio/basic_streambuf_fwd.hpp
index f3e006bf11..b34e3459bb 100644
--- a/boost/asio/basic_streambuf_fwd.hpp
+++ b/boost/asio/basic_streambuf_fwd.hpp
@@ -27,6 +27,9 @@ namespace asio {
template <typename Allocator = std::allocator<char> >
class basic_streambuf;
+template <typename Allocator = std::allocator<char> >
+class basic_streambuf_ref;
+
} // namespace asio
} // namespace boost
diff --git a/boost/asio/basic_waitable_timer.hpp b/boost/asio/basic_waitable_timer.hpp
index e4aeb0b7d8..3657d8b429 100644
--- a/boost/asio/basic_waitable_timer.hpp
+++ b/boost/asio/basic_waitable_timer.hpp
@@ -22,13 +22,37 @@
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/wait_traits.hpp>
-#include <boost/asio/waitable_timer_service.hpp>
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/waitable_timer_service.hpp>
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/detail/chrono_time_traits.hpp>
+# include <boost/asio/detail/deadline_timer_service.hpp>
+# define BOOST_ASIO_SVC_T \
+ detail::deadline_timer_service< \
+ detail::chrono_time_traits<Clock, WaitTraits> >
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
+#if !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
+#define BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL
+
+// Forward declaration with defaulted arguments.
+template <typename Clock,
+ typename WaitTraits = boost::asio::wait_traits<Clock>
+ BOOST_ASIO_SVC_TPARAM_DEF2(= waitable_timer_service<Clock, WaitTraits>)>
+class basic_waitable_timer;
+
+#endif // !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
+
/// Provides waitable timer functionality.
/**
* The basic_waitable_timer class template provides the ability to perform a
@@ -52,10 +76,10 @@ namespace asio {
* Performing a blocking wait (C++11):
* @code
* // Construct a timer without setting an expiry time.
- * boost::asio::steady_timer timer(io_service);
+ * boost::asio::steady_timer timer(io_context);
*
* // Set an expiry time relative to now.
- * timer.expires_from_now(std::chrono::seconds(5));
+ * timer.expires_after(std::chrono::seconds(5));
*
* // Wait for the timer to expire.
* timer.wait();
@@ -75,7 +99,7 @@ namespace asio {
* ...
*
* // Construct a timer with an absolute expiry time.
- * boost::asio::steady_timer timer(io_service,
+ * boost::asio::steady_timer timer(io_context,
* std::chrono::steady_clock::now() + std::chrono::seconds(60));
*
* // Start an asynchronous wait.
@@ -92,7 +116,7 @@ namespace asio {
* @code
* void on_some_event()
* {
- * if (my_timer.expires_from_now(seconds(5)) > 0)
+ * if (my_timer.expires_after(seconds(5)) > 0)
* {
* // We managed to cancel the timer. Start new asynchronous wait.
* my_timer.async_wait(on_timeout);
@@ -112,7 +136,7 @@ namespace asio {
* }
* @endcode
*
- * @li The boost::asio::basic_waitable_timer::expires_from_now() function
+ * @li The boost::asio::basic_waitable_timer::expires_after() function
* cancels any pending asynchronous waits, and returns the number of
* asynchronous waits that were cancelled. If it returns 0 then you were too
* late and the wait handler has already been executed, or will soon be
@@ -121,13 +145,14 @@ namespace asio {
* @li If a wait handler is cancelled, the boost::system::error_code passed to
* it contains the value boost::asio::error::operation_aborted.
*/
-template <typename Clock,
- typename WaitTraits = boost::asio::wait_traits<Clock>,
- typename WaitableTimerService = waitable_timer_service<Clock, WaitTraits> >
+template <typename Clock, typename WaitTraits BOOST_ASIO_SVC_TPARAM>
class basic_waitable_timer
- : public basic_io_object<WaitableTimerService>
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>
{
public:
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
+
/// The clock type.
typedef Clock clock_type;
@@ -143,14 +168,14 @@ public:
/// Constructor.
/**
* This constructor creates a timer without setting an expiry time. The
- * expires_at() or expires_from_now() functions must be called to set an
- * expiry time before the timer can be waited on.
+ * expires_at() or expires_after() functions must be called to set an expiry
+ * time before the timer can be waited on.
*
- * @param io_service The io_service object that the timer will use to dispatch
+ * @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
*/
- explicit basic_waitable_timer(boost::asio::io_service& io_service)
- : basic_io_object<WaitableTimerService>(io_service)
+ explicit basic_waitable_timer(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
}
@@ -158,18 +183,18 @@ public:
/**
* This constructor creates a timer and sets the expiry time.
*
- * @param io_service The io_service object that the timer will use to dispatch
+ * @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, expressed
* as an absolute time.
*/
- basic_waitable_timer(boost::asio::io_service& io_service,
+ basic_waitable_timer(boost::asio::io_context& io_context,
const time_point& expiry_time)
- : basic_io_object<WaitableTimerService>(io_service)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
boost::system::error_code ec;
- this->service.expires_at(this->implementation, expiry_time, ec);
+ this->get_service().expires_at(this->get_implementation(), expiry_time, ec);
boost::asio::detail::throw_error(ec, "expires_at");
}
@@ -177,21 +202,105 @@ public:
/**
* This constructor creates a timer and sets the expiry time.
*
- * @param io_service The io_service object that the timer will use to dispatch
+ * @param io_context The io_context object that the timer will use to dispatch
* handlers for any asynchronous operations performed on the timer.
*
* @param expiry_time The expiry time to be used for the timer, relative to
* now.
*/
- basic_waitable_timer(boost::asio::io_service& io_service,
+ basic_waitable_timer(boost::asio::io_context& io_context,
const duration& expiry_time)
- : basic_io_object<WaitableTimerService>(io_service)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
{
boost::system::error_code ec;
- this->service.expires_from_now(this->implementation, expiry_time, ec);
- boost::asio::detail::throw_error(ec, "expires_from_now");
+ this->get_service().expires_after(
+ this->get_implementation(), expiry_time, ec);
+ boost::asio::detail::throw_error(ec, "expires_after");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a basic_waitable_timer from another.
+ /**
+ * This constructor moves a timer from one object to another.
+ *
+ * @param other The other basic_waitable_timer 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_waitable_timer(io_context&) constructor.
+ */
+ basic_waitable_timer(basic_waitable_timer&& other)
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
+ {
+ }
+
+ /// Move-assign a basic_waitable_timer from another.
+ /**
+ * This assignment operator moves a timer from one object to another. Cancels
+ * any outstanding asynchronous operations associated with the target object.
+ *
+ * @param other The other basic_waitable_timer 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_waitable_timer(io_context&) constructor.
+ */
+ basic_waitable_timer& operator=(basic_waitable_timer&& other)
+ {
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroys the timer.
+ /**
+ * This function destroys the timer, cancelling any outstanding asynchronous
+ * wait operations associated with the timer as if by calling @c cancel.
+ */
+ ~basic_waitable_timer()
+ {
+ }
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ // These functions are provided by basic_io_object<>.
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
}
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
+ }
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
/// Cancel any asynchronous operations that are waiting on the timer.
/**
* This function forces the completion of any pending asynchronous wait
@@ -217,12 +326,14 @@ public:
std::size_t cancel()
{
boost::system::error_code ec;
- std::size_t s = this->service.cancel(this->implementation, ec);
+ std::size_t s = this->get_service().cancel(this->get_implementation(), ec);
boost::asio::detail::throw_error(ec, "cancel");
return s;
}
- /// Cancel any asynchronous operations that are waiting on the timer.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use non-error_code overload.) Cancel any asynchronous
+ /// operations that are waiting on the timer.
/**
* This function forces the completion of any pending asynchronous wait
* operations against the timer. The handler for each cancelled operation will
@@ -246,8 +357,9 @@ public:
*/
std::size_t cancel(boost::system::error_code& ec)
{
- return this->service.cancel(this->implementation, ec);
+ return this->get_service().cancel(this->get_implementation(), ec);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Cancels one asynchronous operation that is waiting on the timer.
/**
@@ -276,12 +388,15 @@ public:
std::size_t cancel_one()
{
boost::system::error_code ec;
- std::size_t s = this->service.cancel_one(this->implementation, ec);
+ std::size_t s = this->get_service().cancel_one(
+ this->get_implementation(), ec);
boost::asio::detail::throw_error(ec, "cancel_one");
return s;
}
- /// Cancels one asynchronous operation that is waiting on the timer.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use non-error_code overload.) Cancels one asynchronous
+ /// operation that is waiting on the timer.
/**
* This function forces the completion of one pending asynchronous wait
* operation against the timer. Handlers are cancelled in FIFO order. The
@@ -307,17 +422,29 @@ public:
*/
std::size_t cancel_one(boost::system::error_code& ec)
{
- return this->service.cancel_one(this->implementation, ec);
+ return this->get_service().cancel_one(this->get_implementation(), ec);
}
- /// Get the timer's expiry time as an absolute time.
+ /// (Deprecated: Use expiry().) Get the timer's expiry time as an absolute
+ /// time.
/**
* This function may be used to obtain the timer's current expiry time.
* Whether the timer has expired or not does not affect this value.
*/
time_point expires_at() const
{
- return this->service.expires_at(this->implementation);
+ return this->get_service().expires_at(this->get_implementation());
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the timer's expiry time as an absolute time.
+ /**
+ * This function may be used to obtain the timer's current expiry time.
+ * Whether the timer has expired or not does not affect this value.
+ */
+ time_point expiry() const
+ {
+ return this->get_service().expiry(this->get_implementation());
}
/// Set the timer's expiry time as an absolute time.
@@ -345,13 +472,15 @@ public:
std::size_t expires_at(const time_point& expiry_time)
{
boost::system::error_code ec;
- std::size_t s = this->service.expires_at(
- this->implementation, expiry_time, ec);
+ std::size_t s = this->get_service().expires_at(
+ this->get_implementation(), expiry_time, ec);
boost::asio::detail::throw_error(ec, "expires_at");
return s;
}
- /// Set the timer's expiry time as an absolute time.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use non-error_code overload.) Set the timer's expiry time as
+ /// an absolute time.
/**
* This function sets the expiry time. Any pending asynchronous wait
* operations will be cancelled. The handler for each cancelled operation will
@@ -376,20 +505,55 @@ public:
std::size_t expires_at(const time_point& expiry_time,
boost::system::error_code& ec)
{
- return this->service.expires_at(this->implementation, expiry_time, ec);
+ return this->get_service().expires_at(
+ this->get_implementation(), expiry_time, ec);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
- /// Get the timer's expiry time relative to now.
+ /// Set the timer's expiry time relative to now.
+ /**
+ * This function sets the expiry time. Any pending asynchronous wait
+ * operations will be cancelled. The handler for each cancelled operation will
+ * be invoked with the boost::asio::error::operation_aborted error code.
+ *
+ * @param expiry_time The expiry time to be used for the timer.
+ *
+ * @return The number of asynchronous operations that were cancelled.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note If the timer has already expired when expires_after() is called,
+ * then the handlers for asynchronous wait operations will:
+ *
+ * @li have already been invoked; or
+ *
+ * @li have been queued for invocation in the near future.
+ *
+ * These handlers can no longer be cancelled, and therefore are passed an
+ * error code that indicates the successful completion of the wait operation.
+ */
+ std::size_t expires_after(const duration& expiry_time)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().expires_after(
+ this->get_implementation(), expiry_time, ec);
+ boost::asio::detail::throw_error(ec, "expires_after");
+ return s;
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use expiry().) Get the timer's expiry time relative to now.
/**
* This function may be used to obtain the timer's current expiry time.
* Whether the timer has expired or not does not affect this value.
*/
duration expires_from_now() const
{
- return this->service.expires_from_now(this->implementation);
+ return this->get_service().expires_from_now(this->get_implementation());
}
- /// Set the timer's expiry time relative to now.
+ /// (Deprecated: Use expires_after().) Set the timer's expiry time relative
+ /// to now.
/**
* This function sets the expiry time. Any pending asynchronous wait
* operations will be cancelled. The handler for each cancelled operation will
@@ -414,13 +578,14 @@ public:
std::size_t expires_from_now(const duration& expiry_time)
{
boost::system::error_code ec;
- std::size_t s = this->service.expires_from_now(
- this->implementation, expiry_time, ec);
+ std::size_t s = this->get_service().expires_from_now(
+ this->get_implementation(), expiry_time, ec);
boost::asio::detail::throw_error(ec, "expires_from_now");
return s;
}
- /// Set the timer's expiry time relative to now.
+ /// (Deprecated: Use expires_after().) Set the timer's expiry time relative
+ /// to now.
/**
* This function sets the expiry time. Any pending asynchronous wait
* operations will be cancelled. The handler for each cancelled operation will
@@ -445,9 +610,10 @@ public:
std::size_t expires_from_now(const duration& expiry_time,
boost::system::error_code& ec)
{
- return this->service.expires_from_now(
- this->implementation, expiry_time, ec);
+ return this->get_service().expires_from_now(
+ this->get_implementation(), expiry_time, ec);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Perform a blocking wait on the timer.
/**
@@ -459,7 +625,7 @@ public:
void wait()
{
boost::system::error_code ec;
- this->service.wait(this->implementation, ec);
+ this->get_service().wait(this->get_implementation(), ec);
boost::asio::detail::throw_error(ec, "wait");
}
@@ -472,7 +638,7 @@ public:
*/
void wait(boost::system::error_code& ec)
{
- this->service.wait(this->implementation, ec);
+ this->get_service().wait(this->get_implementation(), ec);
}
/// Start an asynchronous wait on the timer.
@@ -497,7 +663,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename WaitHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
@@ -508,9 +674,25 @@ public:
// not meet the documented type requirements for a WaitHandler.
BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
- return this->service.async_wait(this->implementation,
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_wait(this->get_implementation(),
BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_wait(this->get_implementation(),
+ init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
+
+private:
+ // Disallow copying and assignment.
+ basic_waitable_timer(const basic_waitable_timer&) BOOST_ASIO_DELETED;
+ basic_waitable_timer& operator=(
+ const basic_waitable_timer&) BOOST_ASIO_DELETED;
};
} // namespace asio
@@ -518,4 +700,8 @@ public:
#include <boost/asio/detail/pop_options.hpp>
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# undef BOOST_ASIO_SVC_T
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_BASIC_WAITABLE_TIMER_HPP
diff --git a/boost/asio/bind_executor.hpp b/boost/asio/bind_executor.hpp
new file mode 100644
index 0000000000..f6db65fc91
--- /dev/null
+++ b/boost/asio/bind_executor.hpp
@@ -0,0 +1,613 @@
+//
+// bind_executor.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_BIND_EXECUTOR_HPP
+#define BOOST_ASIO_BIND_EXECUTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/detail/variadic_templates.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/is_executor.hpp>
+#include <boost/asio/uses_executor.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+struct executor_binder_check
+{
+ typedef void type;
+};
+
+// Helper to automatically define nested typedef result_type.
+
+template <typename T, typename = void>
+struct executor_binder_result_type
+{
+protected:
+ typedef void result_type_or_void;
+};
+
+template <typename T>
+struct executor_binder_result_type<T,
+ typename executor_binder_check<typename T::result_type>::type>
+{
+ typedef typename T::result_type result_type;
+protected:
+ typedef result_type result_type_or_void;
+};
+
+template <typename R>
+struct executor_binder_result_type<R(*)()>
+{
+ typedef R result_type;
+protected:
+ typedef result_type result_type_or_void;
+};
+
+template <typename R>
+struct executor_binder_result_type<R(&)()>
+{
+ typedef R result_type;
+protected:
+ typedef result_type result_type_or_void;
+};
+
+template <typename R, typename A1>
+struct executor_binder_result_type<R(*)(A1)>
+{
+ typedef R result_type;
+protected:
+ typedef result_type result_type_or_void;
+};
+
+template <typename R, typename A1>
+struct 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 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 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 executor_binder_argument_type {};
+
+template <typename T>
+struct executor_binder_argument_type<T,
+ typename executor_binder_check<typename T::argument_type>::type>
+{
+ typedef typename T::argument_type argument_type;
+};
+
+template <typename R, typename A1>
+struct executor_binder_argument_type<R(*)(A1)>
+{
+ typedef A1 argument_type;
+};
+
+template <typename R, typename A1>
+struct 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 executor_binder_argument_types {};
+
+template <typename T>
+struct executor_binder_argument_types<T,
+ typename executor_binder_check<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 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 executor_binder_argument_type<R(&)(A1, A2)>
+{
+ typedef A1 first_argument_type;
+ typedef A2 second_argument_type;
+};
+
+// Helper to:
+// - Apply the empty base optimisation to the executor.
+// - Perform uses_executor construction of the target type, if required.
+
+template <typename T, typename Executor, bool UsesExecutor>
+class executor_binder_base;
+
+template <typename T, typename Executor>
+class executor_binder_base<T, Executor, true>
+ : protected Executor
+{
+protected:
+ template <typename E, typename U>
+ executor_binder_base(BOOST_ASIO_MOVE_ARG(E) e, BOOST_ASIO_MOVE_ARG(U) u)
+ : executor_(BOOST_ASIO_MOVE_CAST(E)(e)),
+ target_(executor_arg_t(), executor_, BOOST_ASIO_MOVE_CAST(U)(u))
+ {
+ }
+
+ Executor executor_;
+ T target_;
+};
+
+template <typename T, typename Executor>
+class executor_binder_base<T, Executor, false>
+{
+protected:
+ template <typename E, typename U>
+ executor_binder_base(BOOST_ASIO_MOVE_ARG(E) e, BOOST_ASIO_MOVE_ARG(U) u)
+ : executor_(BOOST_ASIO_MOVE_CAST(E)(e)),
+ target_(BOOST_ASIO_MOVE_CAST(U)(u))
+ {
+ }
+
+ Executor executor_;
+ T target_;
+};
+
+// Helper to enable SFINAE on zero-argument operator() below.
+
+template <typename T, typename = void>
+struct executor_binder_result_of0
+{
+ typedef void type;
+};
+
+template <typename T>
+struct executor_binder_result_of0<T,
+ typename executor_binder_check<typename result_of<T()>::type>::type>
+{
+ typedef typename result_of<T()>::type type;
+};
+
+} // namespace detail
+
+/// A call wrapper type to bind an executor of type @c Executor to an object of
+/// type @c T.
+template <typename T, typename Executor>
+class executor_binder
+#if !defined(GENERATING_DOCUMENTATION)
+ : public detail::executor_binder_result_type<T>,
+ public detail::executor_binder_argument_type<T>,
+ public detail::executor_binder_argument_types<T>,
+ private detail::executor_binder_base<
+ T, Executor, uses_executor<T, Executor>::value>
+#endif // !defined(GENERATING_DOCUMENTATION)
+{
+public:
+ /// The type of the target object.
+ typedef T target_type;
+
+ /// The type of the associated executor.
+ typedef Executor 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 an 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>
+ executor_binder(executor_arg_t, const executor_type& e,
+ BOOST_ASIO_MOVE_ARG(U) u)
+ : base_type(e, BOOST_ASIO_MOVE_CAST(U)(u))
+ {
+ }
+
+ /// Copy constructor.
+ executor_binder(const executor_binder& other)
+ : base_type(other.get_executor(), other.get())
+ {
+ }
+
+ /// Construct a copy, but specify a different executor.
+ executor_binder(executor_arg_t, const executor_type& e,
+ const executor_binder& other)
+ : base_type(e, other.get())
+ {
+ }
+
+ /// Construct a copy of a different 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>
+ executor_binder(const executor_binder<U, OtherExecutor>& other)
+ : base_type(other.get_executor(), other.get())
+ {
+ }
+
+ /// Construct a copy of a different executor wrapper type, but specify a
+ /// different executor.
+ /**
+ * This constructor is only valid if the type @c T is constructible from type
+ * @c U.
+ */
+ template <typename U, typename OtherExecutor>
+ executor_binder(executor_arg_t, const executor_type& e,
+ const executor_binder<U, OtherExecutor>& other)
+ : base_type(e, other.get())
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Move constructor.
+ executor_binder(executor_binder&& other)
+ : base_type(BOOST_ASIO_MOVE_CAST(executor_type)(other.get_executor()),
+ BOOST_ASIO_MOVE_CAST(T)(other.get()))
+ {
+ }
+
+ /// Move construct the target object, but specify a different executor.
+ executor_binder(executor_arg_t, const executor_type& e,
+ executor_binder&& other)
+ : base_type(e, BOOST_ASIO_MOVE_CAST(T)(other.get()))
+ {
+ }
+
+ /// Move construct from a different executor wrapper type.
+ template <typename U, typename OtherExecutor>
+ executor_binder(executor_binder<U, OtherExecutor>&& other)
+ : base_type(BOOST_ASIO_MOVE_CAST(OtherExecutor)(other.get_executor()),
+ BOOST_ASIO_MOVE_CAST(U)(other.get()))
+ {
+ }
+
+ /// Move construct from a different executor wrapper type, but specify a
+ /// different executor.
+ template <typename U, typename OtherExecutor>
+ executor_binder(executor_arg_t, const executor_type& e,
+ executor_binder<U, OtherExecutor>&& other)
+ : base_type(e, BOOST_ASIO_MOVE_CAST(U)(other.get()))
+ {
+ }
+
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destructor.
+ ~executor_binder()
+ {
+ }
+
+ /// Obtain a reference to the target object.
+ target_type& get() BOOST_ASIO_NOEXCEPT
+ {
+ return this->target_;
+ }
+
+ /// Obtain a reference to the target object.
+ const target_type& get() const BOOST_ASIO_NOEXCEPT
+ {
+ return this->target_;
+ }
+
+ /// Obtain the associated executor.
+ executor_type get_executor() const BOOST_ASIO_NOEXCEPT
+ {
+ return this->executor_;
+ }
+
+#if defined(GENERATING_DOCUMENTATION)
+
+ template <typename... Args> auto operator()(Args&& ...);
+ template <typename... Args> auto operator()(Args&& ...) const;
+
+#elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ /// Forwarding function call operator.
+ template <typename... Args>
+ typename result_of<T(Args...)>::type operator()(
+ BOOST_ASIO_MOVE_ARG(Args)... args)
+ {
+ return this->target_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ }
+
+ /// Forwarding function call operator.
+ template <typename... Args>
+ typename result_of<T(Args...)>::type operator()(
+ BOOST_ASIO_MOVE_ARG(Args)... args) const
+ {
+ return this->target_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ }
+
+#elif defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
+
+ typename detail::executor_binder_result_of0<T>::type operator()()
+ {
+ return this->target_();
+ }
+
+ typename detail::executor_binder_result_of0<T>::type operator()() const
+ {
+ return this->target_();
+ }
+
+#define BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \
+ template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ typename result_of<T(BOOST_ASIO_VARIADIC_TARGS(n))>::type operator()( \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ return this->target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ \
+ template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ typename result_of<T(BOOST_ASIO_VARIADIC_TARGS(n))>::type operator()( \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
+ { \
+ return this->target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF)
+#undef BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF
+
+#else // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
+
+ typedef typename detail::executor_binder_result_type<T>::result_type_or_void
+ result_type_or_void;
+
+ result_type_or_void operator()()
+ {
+ return this->target_();
+ }
+
+ result_type_or_void operator()() const
+ {
+ return this->target_();
+ }
+
+#define BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \
+ template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ result_type_or_void operator()( \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ return this->target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ \
+ template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ result_type_or_void operator()( \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
+ { \
+ return this->target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF)
+#undef BOOST_ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF
+
+#endif // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
+
+private:
+ typedef detail::executor_binder_base<T, Executor,
+ uses_executor<T, Executor>::value> base_type;
+};
+
+/// 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>
+bind_executor(const Executor& ex, BOOST_ASIO_MOVE_ARG(T) t,
+ typename enable_if<is_executor<Executor>::value>::type* = 0)
+{
+ return executor_binder<typename decay<T>::type, Executor>(
+ executor_arg_t(), ex, BOOST_ASIO_MOVE_CAST(T)(t));
+}
+
+/// 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,
+ typename ExecutionContext::executor_type>
+bind_executor(ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(T) t,
+ typename enable_if<is_convertible<
+ ExecutionContext&, execution_context&>::value>::type* = 0)
+{
+ return executor_binder<typename decay<T>::type,
+ typename ExecutionContext::executor_type>(
+ executor_arg_t(), ctx.get_executor(), BOOST_ASIO_MOVE_CAST(T)(t));
+}
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename T, typename Executor>
+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>
+{
+public:
+ typedef executor_binder<
+ typename async_result<T, Signature>::completion_handler_type, Executor>
+ completion_handler_type;
+
+ typedef typename async_result<T, Signature>::return_type return_type;
+
+ explicit async_result(executor_binder<T, Executor>& b)
+ : target_(b.get())
+ {
+ }
+
+ return_type get()
+ {
+ return target_.get();
+ }
+
+private:
+ async_result(const async_result&) BOOST_ASIO_DELETED;
+ async_result& operator=(const async_result&) BOOST_ASIO_DELETED;
+
+ async_result<T, Signature> target_;
+};
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+template <typename T, typename Executor, typename Signature>
+struct handler_type<executor_binder<T, Executor>, Signature>
+{
+ typedef executor_binder<
+ typename handler_type<T, Signature>::type, Executor> type;
+};
+
+template <typename T, typename Executor>
+class async_result<executor_binder<T, Executor> >
+{
+public:
+ typedef typename async_result<T>::type type;
+
+ explicit async_result(executor_binder<T, Executor>& b)
+ : target_(b.get())
+ {
+ }
+
+ type get()
+ {
+ return target_.get();
+ }
+
+private:
+ async_result<T> target_;
+};
+
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+template <typename T, typename Executor, typename Allocator>
+struct associated_allocator<executor_binder<T, Executor>, Allocator>
+{
+ typedef typename associated_allocator<T, Allocator>::type type;
+
+ static type get(const executor_binder<T, Executor>& b,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<T, Allocator>::get(b.get(), a);
+ }
+};
+
+template <typename T, typename Executor, typename Executor1>
+struct associated_executor<executor_binder<T, Executor>, Executor1>
+{
+ typedef Executor type;
+
+ static type get(const executor_binder<T, Executor>& b,
+ const Executor1& = Executor1()) BOOST_ASIO_NOEXCEPT
+ {
+ return b.get_executor();
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_BIND_EXECUTOR_HPP
diff --git a/boost/asio/buffer.hpp b/boost/asio/buffer.hpp
index 700654d21d..66d638ec51 100644
--- a/boost/asio/buffer.hpp
+++ b/boost/asio/buffer.hpp
@@ -18,17 +18,23 @@
#include <boost/asio/detail/config.hpp>
#include <cstddef>
#include <cstring>
+#include <limits>
+#include <stdexcept>
#include <string>
#include <vector>
#include <boost/asio/detail/array_fwd.hpp>
+#include <boost/asio/detail/is_buffer_sequence.hpp>
+#include <boost/asio/detail/string_view.hpp>
+#include <boost/asio/detail/throw_exception.hpp>
+#include <boost/asio/detail/type_traits.hpp>
-#if defined(BOOST_ASIO_MSVC)
+#if defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1700)
# if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)
# if !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
# define BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
# endif // !defined(BOOST_ASIO_DISABLE_BUFFER_DEBUGGING)
# endif // defined(_HAS_ITERATOR_DEBUGGING)
-#endif // defined(BOOST_ASIO_MSVC)
+#endif // defined(BOOST_ASIO_MSVC) && (BOOST_ASIO_MSVC >= 1700)
#if defined(__GNUC__)
# if defined(_GLIBCXX_DEBUG)
@@ -39,7 +45,7 @@
#endif // defined(__GNUC__)
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
-# include <boost/asio/detail/function.hpp>
+# include <boost/asio/detail/functional.hpp>
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
#if defined(BOOST_ASIO_HAS_BOOST_WORKAROUND)
@@ -63,13 +69,6 @@ namespace asio {
class mutable_buffer;
class const_buffer;
-namespace detail {
-void* buffer_cast_helper(const mutable_buffer&);
-const void* buffer_cast_helper(const const_buffer&);
-std::size_t buffer_size_helper(const mutable_buffer&);
-std::size_t buffer_size_helper(const const_buffer&);
-} // namespace detail
-
/// Holds a buffer that can be modified.
/**
* The mutable_buffer class provides a safe representation of a buffer that can
@@ -78,29 +77,29 @@ std::size_t buffer_size_helper(const const_buffer&);
*
* @par Accessing Buffer Contents
*
- * The contents of a buffer may be accessed using the @ref buffer_size
- * and @ref buffer_cast functions:
+ * The contents of a buffer may be accessed using the @c data() and @c size()
+ * member functions:
*
* @code boost::asio::mutable_buffer b1 = ...;
- * std::size_t s1 = boost::asio::buffer_size(b1);
- * unsigned char* p1 = boost::asio::buffer_cast<unsigned char*>(b1);
+ * std::size_t s1 = b1.size();
+ * unsigned char* p1 = static_cast<unsigned char*>(b1.data());
* @endcode
*
- * The boost::asio::buffer_cast function permits violations of type safety, so
- * uses of it in application code should be carefully considered.
+ * The @c data() member function permits violations of type safety, so uses of
+ * it in application code should be carefully considered.
*/
class mutable_buffer
{
public:
/// Construct an empty buffer.
- mutable_buffer()
+ mutable_buffer() BOOST_ASIO_NOEXCEPT
: data_(0),
size_(0)
{
}
/// Construct a buffer to represent a given memory range.
- mutable_buffer(void* data, std::size_t size)
+ mutable_buffer(void* data, std::size_t size) BOOST_ASIO_NOEXCEPT
: data_(data),
size_(size)
{
@@ -121,12 +120,32 @@ public:
}
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
-private:
- friend void* boost::asio::detail::buffer_cast_helper(
- const mutable_buffer& b);
- friend std::size_t boost::asio::detail::buffer_size_helper(
- const mutable_buffer& b);
+ /// Get a pointer to the beginning of the memory range.
+ void* data() const BOOST_ASIO_NOEXCEPT
+ {
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ if (size_ && debug_check_)
+ debug_check_();
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ return data_;
+ }
+
+ /// Get the size of the memory range.
+ std::size_t size() const BOOST_ASIO_NOEXCEPT
+ {
+ return size_;
+ }
+
+ /// Move the start of the buffer by the specified number of bytes.
+ mutable_buffer& operator+=(std::size_t n) BOOST_ASIO_NOEXCEPT
+ {
+ std::size_t offset = n < size_ ? n : size_;
+ data_ = static_cast<char*>(data_) + offset;
+ size_ -= offset;
+ return *this;
+ }
+private:
void* data_;
std::size_t size_;
@@ -135,26 +154,10 @@ private:
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
};
-namespace detail {
-
-inline void* buffer_cast_helper(const mutable_buffer& b)
-{
-#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- if (b.size_ && b.debug_check_)
- b.debug_check_();
-#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
- return b.data_;
-}
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
-inline std::size_t buffer_size_helper(const mutable_buffer& b)
-{
- return b.size_;
-}
-
-} // namespace detail
-
-/// Adapts a single modifiable buffer so that it meets the requirements of the
-/// MutableBufferSequence concept.
+/// (Deprecated: Use mutable_buffer.) Adapts a single modifiable buffer so that
+/// it meets the requirements of the MutableBufferSequence concept.
class mutable_buffers_1
: public mutable_buffer
{
@@ -166,30 +169,40 @@ public:
typedef const mutable_buffer* const_iterator;
/// Construct to represent a given memory range.
- mutable_buffers_1(void* data, std::size_t size)
+ mutable_buffers_1(void* data, std::size_t size) BOOST_ASIO_NOEXCEPT
: mutable_buffer(data, size)
{
}
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ mutable_buffers_1(void* data, std::size_t size,
+ boost::asio::detail::function<void()> debug_check)
+ : mutable_buffer(data, size, debug_check)
+ {
+ }
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+
/// Construct to represent a single modifiable buffer.
- explicit mutable_buffers_1(const mutable_buffer& b)
+ explicit mutable_buffers_1(const mutable_buffer& b) BOOST_ASIO_NOEXCEPT
: mutable_buffer(b)
{
}
/// Get a random-access iterator to the first element.
- const_iterator begin() const
+ const_iterator begin() const BOOST_ASIO_NOEXCEPT
{
return this;
}
/// Get a random-access iterator for one past the last element.
- const_iterator end() const
+ const_iterator end() const BOOST_ASIO_NOEXCEPT
{
return begin() + 1;
}
};
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
/// Holds a buffer that cannot be modified.
/**
* The const_buffer class provides a safe representation of a buffer that cannot
@@ -198,38 +211,38 @@ public:
*
* @par Accessing Buffer Contents
*
- * The contents of a buffer may be accessed using the @ref buffer_size
- * and @ref buffer_cast functions:
+ * The contents of a buffer may be accessed using the @c data() and @c size()
+ * member functions:
*
* @code boost::asio::const_buffer b1 = ...;
- * std::size_t s1 = boost::asio::buffer_size(b1);
- * const unsigned char* p1 = boost::asio::buffer_cast<const unsigned char*>(b1);
+ * std::size_t s1 = b1.size();
+ * const unsigned char* p1 = static_cast<const unsigned char*>(b1.data());
* @endcode
*
- * The boost::asio::buffer_cast function permits violations of type safety, so
- * uses of it in application code should be carefully considered.
+ * The @c data() member function permits violations of type safety, so uses of
+ * it in application code should be carefully considered.
*/
class const_buffer
{
public:
/// Construct an empty buffer.
- const_buffer()
+ const_buffer() BOOST_ASIO_NOEXCEPT
: data_(0),
size_(0)
{
}
/// Construct a buffer to represent a given memory range.
- const_buffer(const void* data, std::size_t size)
+ const_buffer(const void* data, std::size_t size) BOOST_ASIO_NOEXCEPT
: data_(data),
size_(size)
{
}
/// Construct a non-modifiable buffer from a modifiable one.
- const_buffer(const mutable_buffer& b)
- : data_(boost::asio::detail::buffer_cast_helper(b)),
- size_(boost::asio::detail::buffer_size_helper(b))
+ const_buffer(const mutable_buffer& b) BOOST_ASIO_NOEXCEPT
+ : data_(b.data()),
+ size_(b.size())
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
, debug_check_(b.get_debug_check())
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
@@ -251,12 +264,32 @@ public:
}
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
-private:
- friend const void* boost::asio::detail::buffer_cast_helper(
- const const_buffer& b);
- friend std::size_t boost::asio::detail::buffer_size_helper(
- const const_buffer& b);
+ /// Get a pointer to the beginning of the memory range.
+ const void* data() const BOOST_ASIO_NOEXCEPT
+ {
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ if (size_ && debug_check_)
+ debug_check_();
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ return data_;
+ }
+ /// Get the size of the memory range.
+ std::size_t size() const BOOST_ASIO_NOEXCEPT
+ {
+ return size_;
+ }
+
+ /// Move the start of the buffer by the specified number of bytes.
+ const_buffer& operator+=(std::size_t n) BOOST_ASIO_NOEXCEPT
+ {
+ std::size_t offset = n < size_ ? n : size_;
+ data_ = static_cast<const char*>(data_) + offset;
+ size_ -= offset;
+ return *this;
+ }
+
+private:
const void* data_;
std::size_t size_;
@@ -265,26 +298,10 @@ private:
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
};
-namespace detail {
-
-inline const void* buffer_cast_helper(const const_buffer& b)
-{
-#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- if (b.size_ && b.debug_check_)
- b.debug_check_();
-#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
- return b.data_;
-}
-
-inline std::size_t buffer_size_helper(const const_buffer& b)
-{
- return b.size_;
-}
-
-} // namespace detail
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
-/// Adapts a single non-modifiable buffer so that it meets the requirements of
-/// the ConstBufferSequence concept.
+/// (Deprecated: Use const_buffer.) Adapts a single non-modifiable buffer so
+/// that it meets the requirements of the ConstBufferSequence concept.
class const_buffers_1
: public const_buffer
{
@@ -296,32 +313,78 @@ public:
typedef const const_buffer* const_iterator;
/// Construct to represent a given memory range.
- const_buffers_1(const void* data, std::size_t size)
+ const_buffers_1(const void* data, std::size_t size) BOOST_ASIO_NOEXCEPT
: const_buffer(data, size)
{
}
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ const_buffers_1(const void* data, std::size_t size,
+ boost::asio::detail::function<void()> debug_check)
+ : const_buffer(data, size, debug_check)
+ {
+ }
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+
/// Construct to represent a single non-modifiable buffer.
- explicit const_buffers_1(const const_buffer& b)
+ explicit const_buffers_1(const const_buffer& b) BOOST_ASIO_NOEXCEPT
: const_buffer(b)
{
}
/// Get a random-access iterator to the first element.
- const_iterator begin() const
+ const_iterator begin() const BOOST_ASIO_NOEXCEPT
{
return this;
}
/// Get a random-access iterator for one past the last element.
- const_iterator end() const
+ const_iterator end() const BOOST_ASIO_NOEXCEPT
{
return begin() + 1;
}
};
-/// An implementation of both the ConstBufferSequence and MutableBufferSequence
-/// concepts to represent a null buffer sequence.
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+/// Trait to determine whether a type satisfies the MutableBufferSequence
+/// requirements.
+template <typename T>
+struct is_mutable_buffer_sequence
+#if defined(GENERATING_DOCUMENTATION)
+ : integral_constant<bool, automatically_determined>
+#else // defined(GENERATING_DOCUMENTATION)
+ : boost::asio::detail::is_buffer_sequence<T, mutable_buffer>
+#endif // defined(GENERATING_DOCUMENTATION)
+{
+};
+
+/// Trait to determine whether a type satisfies the ConstBufferSequence
+/// requirements.
+template <typename T>
+struct is_const_buffer_sequence
+#if defined(GENERATING_DOCUMENTATION)
+ : integral_constant<bool, automatically_determined>
+#else // defined(GENERATING_DOCUMENTATION)
+ : boost::asio::detail::is_buffer_sequence<T, const_buffer>
+#endif // defined(GENERATING_DOCUMENTATION)
+{
+};
+
+/// Trait to determine whether a type satisfies the DynamicBuffer requirements.
+template <typename T>
+struct is_dynamic_buffer
+#if defined(GENERATING_DOCUMENTATION)
+ : integral_constant<bool, automatically_determined>
+#else // defined(GENERATING_DOCUMENTATION)
+ : boost::asio::detail::is_dynamic_buffer<T>
+#endif // defined(GENERATING_DOCUMENTATION)
+{
+};
+
+/// (Deprecated: Use the socket/descriptor wait() and async_wait() member
+/// functions.) An implementation of both the ConstBufferSequence and
+/// MutableBufferSequence concepts to represent a null buffer sequence.
class null_buffers
{
public:
@@ -332,13 +395,13 @@ public:
typedef const mutable_buffer* const_iterator;
/// Get a random-access iterator to the first element.
- const_iterator begin() const
+ const_iterator begin() const BOOST_ASIO_NOEXCEPT
{
return &buf_;
}
/// Get a random-access iterator for one past the last element.
- const_iterator end() const
+ const_iterator end() const BOOST_ASIO_NOEXCEPT
{
return &buf_;
}
@@ -347,61 +410,189 @@ private:
mutable_buffer buf_;
};
-/** @defgroup buffer_size boost::asio::buffer_size
+/** @defgroup buffer_sequence_begin boost::asio::buffer_sequence_begin
*
- * @brief The boost::asio::buffer_size function determines the total number of
- * bytes in a buffer or buffer sequence.
+ * @brief The boost::asio::buffer_sequence_begin function returns an iterator
+ * pointing to the first element in a buffer sequence.
*/
/*@{*/
-/// Get the number of bytes in a modifiable buffer.
-inline std::size_t buffer_size(const mutable_buffer& b)
+/// Get an iterator to the first element in a buffer sequence.
+inline const mutable_buffer* buffer_sequence_begin(const mutable_buffer& b)
{
- return detail::buffer_size_helper(b);
+ return &b;
}
-/// Get the number of bytes in a modifiable buffer.
-inline std::size_t buffer_size(const mutable_buffers_1& b)
+/// Get an iterator to the first element in a buffer sequence.
+inline const const_buffer* buffer_sequence_begin(const const_buffer& b)
{
- return detail::buffer_size_helper(b);
+ return &b;
}
-/// Get the number of bytes in a non-modifiable buffer.
-inline std::size_t buffer_size(const const_buffer& b)
+#if defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
+
+/// Get an iterator to the first element in a buffer sequence.
+template <typename C>
+inline auto buffer_sequence_begin(C& c) -> decltype(c.begin())
{
- return detail::buffer_size_helper(b);
+ return c.begin();
}
-/// Get the number of bytes in a non-modifiable buffer.
-inline std::size_t buffer_size(const const_buffers_1& b)
+/// Get an iterator to the first element in a buffer sequence.
+template <typename C>
+inline auto buffer_sequence_begin(const C& c) -> decltype(c.begin())
{
- return detail::buffer_size_helper(b);
+ return c.begin();
}
-/// Get the total number of bytes in a buffer sequence.
-/**
- * The @c BufferSequence template parameter may meet either of the @c
- * ConstBufferSequence or @c MutableBufferSequence type requirements.
+#else // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
+
+template <typename C>
+inline typename C::iterator buffer_sequence_begin(C& c)
+{
+ return c.begin();
+}
+
+template <typename C>
+inline typename C::const_iterator buffer_sequence_begin(const C& c)
+{
+ return c.begin();
+}
+
+#endif // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
+
+/*@}*/
+
+/** @defgroup buffer_sequence_end boost::asio::buffer_sequence_end
+ *
+ * @brief The boost::asio::buffer_sequence_end function returns an iterator
+ * pointing to one past the end element in a buffer sequence.
*/
+/*@{*/
+
+/// Get an iterator to one past the end element in a buffer sequence.
+inline const mutable_buffer* buffer_sequence_end(const mutable_buffer& b)
+{
+ return &b + 1;
+}
+
+/// Get an iterator to one past the end element in a buffer sequence.
+inline const const_buffer* buffer_sequence_end(const const_buffer& b)
+{
+ return &b + 1;
+}
+
+#if defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
+
+/// Get an iterator to one past the end element in a buffer sequence.
+template <typename C>
+inline auto buffer_sequence_end(C& c) -> decltype(c.end())
+{
+ return c.end();
+}
+
+/// Get an iterator to one past the end element in a buffer sequence.
+template <typename C>
+inline auto buffer_sequence_end(const C& c) -> decltype(c.end())
+{
+ return c.end();
+}
+
+#else // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
+
+template <typename C>
+inline typename C::iterator buffer_sequence_end(C& c)
+{
+ return c.end();
+}
+
+template <typename C>
+inline typename C::const_iterator buffer_sequence_end(const C& c)
+{
+ return c.end();
+}
+
+#endif // defined(BOOST_ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)
+
+/*@}*/
+
+namespace detail {
+
+// Tag types used to select appropriately optimised overloads.
+struct one_buffer {};
+struct multiple_buffers {};
+
+// Helper trait to detect single buffers.
template <typename BufferSequence>
-inline std::size_t buffer_size(const BufferSequence& b)
+struct buffer_sequence_cardinality :
+ conditional<
+ is_same<BufferSequence, mutable_buffer>::value
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ || is_same<BufferSequence, mutable_buffers_1>::value
+ || is_same<BufferSequence, const_buffers_1>::value
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+ || is_same<BufferSequence, const_buffer>::value,
+ one_buffer, multiple_buffers>::type {};
+
+template <typename Iterator>
+inline std::size_t buffer_size(one_buffer,
+ Iterator begin, Iterator) BOOST_ASIO_NOEXCEPT
+{
+ return const_buffer(*begin).size();
+}
+
+template <typename Iterator>
+inline std::size_t buffer_size(multiple_buffers,
+ Iterator begin, Iterator end) BOOST_ASIO_NOEXCEPT
{
std::size_t total_buffer_size = 0;
- typename BufferSequence::const_iterator iter = b.begin();
- typename BufferSequence::const_iterator end = b.end();
+ Iterator iter = begin;
for (; iter != end; ++iter)
- total_buffer_size += detail::buffer_size_helper(*iter);
+ {
+ const_buffer b(*iter);
+ total_buffer_size += b.size();
+ }
return total_buffer_size;
}
-/*@}*/
+} // namespace detail
+
+/// Get the total number of bytes in a buffer sequence.
+/**
+ * The @c buffer_size function determines the total size of all buffers in the
+ * buffer sequence, as if computed as follows:
+ *
+ * @code size_t total_size = 0;
+ * auto i = boost::asio::buffer_sequence_begin(buffers);
+ * auto end = boost::asio::buffer_sequence_end(buffers);
+ * for (; i != end; ++i)
+ * {
+ * const_buffer b(*i);
+ * total_size += b.size();
+ * }
+ * return total_size; @endcode
+ *
+ * The @c BufferSequence template parameter may meet either of the @c
+ * ConstBufferSequence or @c MutableBufferSequence type requirements.
+ */
+template <typename BufferSequence>
+inline std::size_t buffer_size(const BufferSequence& b) BOOST_ASIO_NOEXCEPT
+{
+ return detail::buffer_size(
+ detail::buffer_sequence_cardinality<BufferSequence>(),
+ boost::asio::buffer_sequence_begin(b),
+ boost::asio::buffer_sequence_end(b));
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
/** @defgroup buffer_cast boost::asio::buffer_cast
*
- * @brief The boost::asio::buffer_cast function is used to obtain a pointer to
- * the underlying memory region associated with a buffer.
+ * @brief (Deprecated: Use the @c data() member function.) The
+ * boost::asio::buffer_cast function is used to obtain a pointer to the
+ * underlying memory region associated with a buffer.
*
* @par Examples:
*
@@ -422,30 +613,32 @@ inline std::size_t buffer_size(const BufferSequence& b)
/// Cast a non-modifiable buffer to a specified pointer to POD type.
template <typename PointerToPodType>
-inline PointerToPodType buffer_cast(const mutable_buffer& b)
+inline PointerToPodType buffer_cast(const mutable_buffer& b) BOOST_ASIO_NOEXCEPT
{
- return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
+ return static_cast<PointerToPodType>(b.data());
}
/// Cast a non-modifiable buffer to a specified pointer to POD type.
template <typename PointerToPodType>
-inline PointerToPodType buffer_cast(const const_buffer& b)
+inline PointerToPodType buffer_cast(const const_buffer& b) BOOST_ASIO_NOEXCEPT
{
- return static_cast<PointerToPodType>(detail::buffer_cast_helper(b));
+ return static_cast<PointerToPodType>(b.data());
}
/*@}*/
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
/// Create a new modifiable buffer that is offset from the start of another.
/**
* @relates mutable_buffer
*/
-inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start)
+inline mutable_buffer operator+(const mutable_buffer& b,
+ std::size_t n) BOOST_ASIO_NOEXCEPT
{
- if (start > buffer_size(b))
- return mutable_buffer();
- char* new_data = buffer_cast<char*>(b) + start;
- std::size_t new_size = buffer_size(b) - start;
+ std::size_t offset = n < b.size() ? n : b.size();
+ char* new_data = static_cast<char*>(b.data()) + offset;
+ std::size_t new_size = b.size() - offset;
return mutable_buffer(new_data, new_size
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
, b.get_debug_check()
@@ -457,29 +650,22 @@ inline mutable_buffer operator+(const mutable_buffer& b, std::size_t start)
/**
* @relates mutable_buffer
*/
-inline mutable_buffer operator+(std::size_t start, const mutable_buffer& b)
+inline mutable_buffer operator+(std::size_t n,
+ const mutable_buffer& b) BOOST_ASIO_NOEXCEPT
{
- if (start > buffer_size(b))
- return mutable_buffer();
- char* new_data = buffer_cast<char*>(b) + start;
- std::size_t new_size = buffer_size(b) - start;
- return mutable_buffer(new_data, new_size
-#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- , b.get_debug_check()
-#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
- );
+ return b + n;
}
/// Create a new non-modifiable buffer that is offset from the start of another.
/**
* @relates const_buffer
*/
-inline const_buffer operator+(const const_buffer& b, std::size_t start)
+inline const_buffer operator+(const const_buffer& b,
+ std::size_t n) BOOST_ASIO_NOEXCEPT
{
- if (start > buffer_size(b))
- return const_buffer();
- const char* new_data = buffer_cast<const char*>(b) + start;
- std::size_t new_size = buffer_size(b) - start;
+ std::size_t offset = n < b.size() ? n : b.size();
+ const char* new_data = static_cast<const char*>(b.data()) + offset;
+ std::size_t new_size = b.size() - offset;
return const_buffer(new_data, new_size
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
, b.get_debug_check()
@@ -491,17 +677,10 @@ inline const_buffer operator+(const const_buffer& b, std::size_t start)
/**
* @relates const_buffer
*/
-inline const_buffer operator+(std::size_t start, const const_buffer& b)
+inline const_buffer operator+(std::size_t n,
+ const const_buffer& b) BOOST_ASIO_NOEXCEPT
{
- if (start > buffer_size(b))
- return const_buffer();
- const char* new_data = buffer_cast<const char*>(b) + start;
- std::size_t new_size = buffer_size(b) - start;
- return const_buffer(new_data, new_size
-#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- , b.get_debug_check()
-#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
- );
+ return b + n;
}
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
@@ -586,32 +765,33 @@ private:
*
* @par Accessing Buffer Contents
*
- * The contents of a buffer may be accessed using the @ref buffer_size and
- * @ref buffer_cast functions:
+ * The contents of a buffer may be accessed using the @c data() and @c size()
+ * member functions:
*
* @code boost::asio::mutable_buffer b1 = ...;
- * std::size_t s1 = boost::asio::buffer_size(b1);
- * unsigned char* p1 = boost::asio::buffer_cast<unsigned char*>(b1);
+ * std::size_t s1 = b1.size();
+ * unsigned char* p1 = static_cast<unsigned char*>(b1.data());
*
* boost::asio::const_buffer b2 = ...;
- * std::size_t s2 = boost::asio::buffer_size(b2);
- * const void* p2 = boost::asio::buffer_cast<const void*>(b2); @endcode
+ * std::size_t s2 = b2.size();
+ * const void* p2 = b2.data(); @endcode
*
- * The boost::asio::buffer_cast function permits violations of type safety, so
+ * The @c data() member function permits violations of type safety, so
* uses of it in application code should be carefully considered.
*
- * For convenience, the @ref buffer_size function also works on buffer
- * sequences (that is, types meeting the ConstBufferSequence or
- * MutableBufferSequence type requirements). In this case, the function returns
- * the total size of all buffers in the sequence.
+ * For convenience, a @ref buffer_size function is provided that works with
+ * both buffers and buffer sequences (that is, types meeting the
+ * ConstBufferSequence or MutableBufferSequence type requirements). In this
+ * case, the function returns the total size of all buffers in the sequence.
*
* @par Buffer Copying
*
* The @ref buffer_copy function may be used to copy raw bytes between
* individual buffers and buffer sequences.
- *
- * In particular, when used with the @ref buffer_size, the @ref buffer_copy
- * function can be used to linearise a sequence of buffers. For example:
+*
+ * In particular, when used with the @ref buffer_size function, the @ref
+ * buffer_copy function can be used to linearise a sequence of buffers. For
+ * example:
*
* @code vector<const_buffer> buffers = ...;
*
@@ -700,29 +880,38 @@ private:
*/
/*@{*/
+#if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+# define BOOST_ASIO_MUTABLE_BUFFER mutable_buffer
+# define BOOST_ASIO_CONST_BUFFER const_buffer
+#else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+# define BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_1
+# define BOOST_ASIO_CONST_BUFFER const_buffers_1
+#endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
+
/// Create a new modifiable buffer from an existing buffer.
/**
- * @returns <tt>mutable_buffers_1(b)</tt>.
+ * @returns <tt>mutable_buffer(b)</tt>.
*/
-inline mutable_buffers_1 buffer(const mutable_buffer& b)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(
+ const mutable_buffer& b) BOOST_ASIO_NOEXCEPT
{
- return mutable_buffers_1(b);
+ return BOOST_ASIO_MUTABLE_BUFFER(b);
}
/// Create a new modifiable buffer from an existing buffer.
/**
- * @returns A mutable_buffers_1 value equivalent to:
- * @code mutable_buffers_1(
- * buffer_cast<void*>(b),
- * min(buffer_size(b), max_size_in_bytes)); @endcode
+ * @returns A mutable_buffer value equivalent to:
+ * @code mutable_buffer(
+ * b.data(),
+ * min(b.size(), max_size_in_bytes)); @endcode
*/
-inline mutable_buffers_1 buffer(const mutable_buffer& b,
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(const mutable_buffer& b,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return mutable_buffers_1(
- mutable_buffer(buffer_cast<void*>(b),
- buffer_size(b) < max_size_in_bytes
- ? buffer_size(b) : max_size_in_bytes
+ return BOOST_ASIO_MUTABLE_BUFFER(
+ mutable_buffer(b.data(),
+ b.size() < max_size_in_bytes
+ ? b.size() : max_size_in_bytes
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
, b.get_debug_check()
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
@@ -731,110 +920,110 @@ inline mutable_buffers_1 buffer(const mutable_buffer& b,
/// Create a new non-modifiable buffer from an existing buffer.
/**
- * @returns <tt>const_buffers_1(b)</tt>.
+ * @returns <tt>const_buffer(b)</tt>.
*/
-inline const_buffers_1 buffer(const const_buffer& b)
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ const const_buffer& b) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(b);
+ return BOOST_ASIO_CONST_BUFFER(b);
}
/// Create a new non-modifiable buffer from an existing buffer.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
- * buffer_cast<const void*>(b),
- * min(buffer_size(b), max_size_in_bytes)); @endcode
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
+ * b.data(),
+ * min(b.size(), max_size_in_bytes)); @endcode
*/
-inline const_buffers_1 buffer(const const_buffer& b,
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_CONST_BUFFER buffer(const const_buffer& b,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(buffer_cast<const void*>(b),
- buffer_size(b) < max_size_in_bytes
- ? buffer_size(b) : max_size_in_bytes
+ return BOOST_ASIO_CONST_BUFFER(b.data(),
+ b.size() < max_size_in_bytes
+ ? b.size() : max_size_in_bytes
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- , b.get_debug_check()
+ , b.get_debug_check()
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
- ));
+ );
}
/// Create a new modifiable buffer that represents the given memory range.
/**
- * @returns <tt>mutable_buffers_1(data, size_in_bytes)</tt>.
+ * @returns <tt>mutable_buffer(data, size_in_bytes)</tt>.
*/
-inline mutable_buffers_1 buffer(void* data, std::size_t size_in_bytes)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(void* data,
+ std::size_t size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return mutable_buffers_1(mutable_buffer(data, size_in_bytes));
+ return BOOST_ASIO_MUTABLE_BUFFER(data, size_in_bytes);
}
/// Create a new non-modifiable buffer that represents the given memory range.
/**
- * @returns <tt>const_buffers_1(data, size_in_bytes)</tt>.
+ * @returns <tt>const_buffer(data, size_in_bytes)</tt>.
*/
-inline const_buffers_1 buffer(const void* data,
- std::size_t size_in_bytes)
+inline BOOST_ASIO_CONST_BUFFER buffer(const void* data,
+ std::size_t size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(const_buffer(data, size_in_bytes));
+ return BOOST_ASIO_CONST_BUFFER(data, size_in_bytes);
}
/// Create a new modifiable buffer that represents the given POD array.
/**
- * @returns A mutable_buffers_1 value equivalent to:
- * @code mutable_buffers_1(
+ * @returns A mutable_buffer value equivalent to:
+ * @code mutable_buffer(
* static_cast<void*>(data),
* N * sizeof(PodType)); @endcode
*/
template <typename PodType, std::size_t N>
-inline mutable_buffers_1 buffer(PodType (&data)[N])
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N]) BOOST_ASIO_NOEXCEPT
{
- return mutable_buffers_1(mutable_buffer(data, N * sizeof(PodType)));
+ return BOOST_ASIO_MUTABLE_BUFFER(data, N * sizeof(PodType));
}
/// Create a new modifiable buffer that represents the given POD array.
/**
- * @returns A mutable_buffers_1 value equivalent to:
- * @code mutable_buffers_1(
+ * @returns A mutable_buffer value equivalent to:
+ * @code mutable_buffer(
* static_cast<void*>(data),
* min(N * sizeof(PodType), max_size_in_bytes)); @endcode
*/
template <typename PodType, std::size_t N>
-inline mutable_buffers_1 buffer(PodType (&data)[N],
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N],
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return mutable_buffers_1(
- mutable_buffer(data,
- N * sizeof(PodType) < max_size_in_bytes
- ? N * sizeof(PodType) : max_size_in_bytes));
+ return BOOST_ASIO_MUTABLE_BUFFER(data,
+ N * sizeof(PodType) < max_size_in_bytes
+ ? N * sizeof(PodType) : max_size_in_bytes);
}
/// Create a new non-modifiable buffer that represents the given POD array.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* static_cast<const void*>(data),
* N * sizeof(PodType)); @endcode
*/
template <typename PodType, std::size_t N>
-inline const_buffers_1 buffer(const PodType (&data)[N])
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ const PodType (&data)[N]) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(const_buffer(data, N * sizeof(PodType)));
+ return BOOST_ASIO_CONST_BUFFER(data, N * sizeof(PodType));
}
/// Create a new non-modifiable buffer that represents the given POD array.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* static_cast<const void*>(data),
* min(N * sizeof(PodType), max_size_in_bytes)); @endcode
*/
template <typename PodType, std::size_t N>
-inline const_buffers_1 buffer(const PodType (&data)[N],
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_CONST_BUFFER buffer(const PodType (&data)[N],
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data,
- N * sizeof(PodType) < max_size_in_bytes
- ? N * sizeof(PodType) : max_size_in_bytes));
+ return BOOST_ASIO_CONST_BUFFER(data,
+ N * sizeof(PodType) < max_size_in_bytes
+ ? N * sizeof(PodType) : max_size_in_bytes);
}
#if defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
@@ -860,14 +1049,14 @@ template <>
struct buffer_types_base<false>
{
typedef mutable_buffer buffer_type;
- typedef mutable_buffers_1 container_type;
+ typedef BOOST_ASIO_MUTABLE_BUFFER container_type;
};
template <>
struct buffer_types_base<true>
{
typedef const_buffer buffer_type;
- typedef const_buffers_1 container_type;
+ typedef BOOST_ASIO_CONST_BUFFER container_type;
};
template <typename PodType>
@@ -880,7 +1069,7 @@ struct buffer_types
template <typename PodType, std::size_t N>
inline typename detail::buffer_types<PodType>::container_type
-buffer(boost::array<PodType, N>& data)
+buffer(boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT
{
typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
buffer_type;
@@ -892,7 +1081,8 @@ buffer(boost::array<PodType, N>& data)
template <typename PodType, std::size_t N>
inline typename detail::buffer_types<PodType>::container_type
-buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes)
+buffer(boost::array<PodType, N>& data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
typedef typename boost::asio::detail::buffer_types<PodType>::buffer_type
buffer_type;
@@ -908,200 +1098,195 @@ buffer(boost::array<PodType, N>& data, std::size_t max_size_in_bytes)
/// Create a new modifiable buffer that represents the given POD array.
/**
- * @returns A mutable_buffers_1 value equivalent to:
- * @code mutable_buffers_1(
+ * @returns A mutable_buffer value equivalent to:
+ * @code mutable_buffer(
* data.data(),
* data.size() * sizeof(PodType)); @endcode
*/
template <typename PodType, std::size_t N>
-inline mutable_buffers_1 buffer(boost::array<PodType, N>& data)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(
+ boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT
{
- return mutable_buffers_1(
- mutable_buffer(data.c_array(), data.size() * sizeof(PodType)));
+ return BOOST_ASIO_MUTABLE_BUFFER(
+ data.c_array(), data.size() * sizeof(PodType));
}
/// Create a new modifiable buffer that represents the given POD array.
/**
- * @returns A mutable_buffers_1 value equivalent to:
- * @code mutable_buffers_1(
+ * @returns A mutable_buffer value equivalent to:
+ * @code mutable_buffer(
* data.data(),
* min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
*/
template <typename PodType, std::size_t N>
-inline mutable_buffers_1 buffer(boost::array<PodType, N>& data,
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(boost::array<PodType, N>& data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return mutable_buffers_1(
- mutable_buffer(data.c_array(),
- data.size() * sizeof(PodType) < max_size_in_bytes
- ? data.size() * sizeof(PodType) : max_size_in_bytes));
+ return BOOST_ASIO_MUTABLE_BUFFER(data.c_array(),
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes);
}
/// Create a new non-modifiable buffer that represents the given POD array.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* data.data(),
* data.size() * sizeof(PodType)); @endcode
*/
template <typename PodType, std::size_t N>
-inline const_buffers_1 buffer(boost::array<const PodType, N>& data)
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ boost::array<const PodType, N>& data) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data.data(), data.size() * sizeof(PodType)));
+ return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
}
/// Create a new non-modifiable buffer that represents the given POD array.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* data.data(),
* min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
*/
template <typename PodType, std::size_t N>
-inline const_buffers_1 buffer(boost::array<const PodType, N>& data,
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_CONST_BUFFER buffer(boost::array<const PodType, N>& data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data.data(),
- data.size() * sizeof(PodType) < max_size_in_bytes
- ? data.size() * sizeof(PodType) : max_size_in_bytes));
+ return BOOST_ASIO_CONST_BUFFER(data.data(),
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes);
}
#endif // defined(BOOST_ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)
/// Create a new non-modifiable buffer that represents the given POD array.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* data.data(),
* data.size() * sizeof(PodType)); @endcode
*/
template <typename PodType, std::size_t N>
-inline const_buffers_1 buffer(const boost::array<PodType, N>& data)
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ const boost::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data.data(), data.size() * sizeof(PodType)));
+ return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
}
/// Create a new non-modifiable buffer that represents the given POD array.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* data.data(),
* min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
*/
template <typename PodType, std::size_t N>
-inline const_buffers_1 buffer(const boost::array<PodType, N>& data,
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_CONST_BUFFER buffer(const boost::array<PodType, N>& data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data.data(),
- data.size() * sizeof(PodType) < max_size_in_bytes
- ? data.size() * sizeof(PodType) : max_size_in_bytes));
+ return BOOST_ASIO_CONST_BUFFER(data.data(),
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes);
}
#if defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION)
/// Create a new modifiable buffer that represents the given POD array.
/**
- * @returns A mutable_buffers_1 value equivalent to:
- * @code mutable_buffers_1(
+ * @returns A mutable_buffer value equivalent to:
+ * @code mutable_buffer(
* data.data(),
* data.size() * sizeof(PodType)); @endcode
*/
template <typename PodType, std::size_t N>
-inline mutable_buffers_1 buffer(std::array<PodType, N>& data)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(
+ std::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT
{
- return mutable_buffers_1(
- mutable_buffer(data.data(), data.size() * sizeof(PodType)));
+ return BOOST_ASIO_MUTABLE_BUFFER(data.data(), data.size() * sizeof(PodType));
}
/// Create a new modifiable buffer that represents the given POD array.
/**
- * @returns A mutable_buffers_1 value equivalent to:
- * @code mutable_buffers_1(
+ * @returns A mutable_buffer value equivalent to:
+ * @code mutable_buffer(
* data.data(),
* min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
*/
template <typename PodType, std::size_t N>
-inline mutable_buffers_1 buffer(std::array<PodType, N>& data,
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(std::array<PodType, N>& data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return mutable_buffers_1(
- mutable_buffer(data.data(),
- data.size() * sizeof(PodType) < max_size_in_bytes
- ? data.size() * sizeof(PodType) : max_size_in_bytes));
+ return BOOST_ASIO_MUTABLE_BUFFER(data.data(),
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes);
}
/// Create a new non-modifiable buffer that represents the given POD array.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* data.data(),
* data.size() * sizeof(PodType)); @endcode
*/
template <typename PodType, std::size_t N>
-inline const_buffers_1 buffer(std::array<const PodType, N>& data)
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ std::array<const PodType, N>& data) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data.data(), data.size() * sizeof(PodType)));
+ return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
}
/// Create a new non-modifiable buffer that represents the given POD array.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* data.data(),
* min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
*/
template <typename PodType, std::size_t N>
-inline const_buffers_1 buffer(std::array<const PodType, N>& data,
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_CONST_BUFFER buffer(std::array<const PodType, N>& data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data.data(),
- data.size() * sizeof(PodType) < max_size_in_bytes
- ? data.size() * sizeof(PodType) : max_size_in_bytes));
+ return BOOST_ASIO_CONST_BUFFER(data.data(),
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes);
}
/// Create a new non-modifiable buffer that represents the given POD array.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* data.data(),
* data.size() * sizeof(PodType)); @endcode
*/
template <typename PodType, std::size_t N>
-inline const_buffers_1 buffer(const std::array<PodType, N>& data)
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ const std::array<PodType, N>& data) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data.data(), data.size() * sizeof(PodType)));
+ return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));
}
/// Create a new non-modifiable buffer that represents the given POD array.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* data.data(),
* min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
*/
template <typename PodType, std::size_t N>
-inline const_buffers_1 buffer(const std::array<PodType, N>& data,
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_CONST_BUFFER buffer(const std::array<PodType, N>& data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data.data(),
- data.size() * sizeof(PodType) < max_size_in_bytes
- ? data.size() * sizeof(PodType) : max_size_in_bytes));
+ return BOOST_ASIO_CONST_BUFFER(data.data(),
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes);
}
#endif // defined(BOOST_ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION)
/// Create a new modifiable buffer that represents the given POD vector.
/**
- * @returns A mutable_buffers_1 value equivalent to:
- * @code mutable_buffers_1(
+ * @returns A mutable_buffer value equivalent to:
+ * @code mutable_buffer(
* data.size() ? &data[0] : 0,
* data.size() * sizeof(PodType)); @endcode
*
@@ -1109,22 +1294,23 @@ inline const_buffers_1 buffer(const std::array<PodType, N>& data,
* invalidate iterators.
*/
template <typename PodType, typename Allocator>
-inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(
+ std::vector<PodType, Allocator>& data) BOOST_ASIO_NOEXCEPT
{
- return mutable_buffers_1(
- mutable_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
+ return BOOST_ASIO_MUTABLE_BUFFER(
+ data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- , detail::buffer_debug_check<
- typename std::vector<PodType, Allocator>::iterator
- >(data.begin())
+ , detail::buffer_debug_check<
+ typename std::vector<PodType, Allocator>::iterator
+ >(data.begin())
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
- ));
+ );
}
/// Create a new modifiable buffer that represents the given POD vector.
/**
- * @returns A mutable_buffers_1 value equivalent to:
- * @code mutable_buffers_1(
+ * @returns A mutable_buffer value equivalent to:
+ * @code mutable_buffer(
* data.size() ? &data[0] : 0,
* min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
*
@@ -1132,25 +1318,24 @@ inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data)
* invalidate iterators.
*/
template <typename PodType, typename Allocator>
-inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data,
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(std::vector<PodType, Allocator>& data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return mutable_buffers_1(
- mutable_buffer(data.size() ? &data[0] : 0,
- data.size() * sizeof(PodType) < max_size_in_bytes
- ? data.size() * sizeof(PodType) : max_size_in_bytes
+ return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- , detail::buffer_debug_check<
- typename std::vector<PodType, Allocator>::iterator
- >(data.begin())
+ , detail::buffer_debug_check<
+ typename std::vector<PodType, Allocator>::iterator
+ >(data.begin())
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
- ));
+ );
}
/// Create a new non-modifiable buffer that represents the given POD vector.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* data.size() ? &data[0] : 0,
* data.size() * sizeof(PodType)); @endcode
*
@@ -1158,23 +1343,23 @@ inline mutable_buffers_1 buffer(std::vector<PodType, Allocator>& data,
* invalidate iterators.
*/
template <typename PodType, typename Allocator>
-inline const_buffers_1 buffer(
- const std::vector<PodType, Allocator>& data)
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ const std::vector<PodType, Allocator>& data) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
+ return BOOST_ASIO_CONST_BUFFER(
+ data.size() ? &data[0] : 0, data.size() * sizeof(PodType)
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- , detail::buffer_debug_check<
- typename std::vector<PodType, Allocator>::const_iterator
- >(data.begin())
+ , detail::buffer_debug_check<
+ typename std::vector<PodType, Allocator>::const_iterator
+ >(data.begin())
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
- ));
+ );
}
/// Create a new non-modifiable buffer that represents the given POD vector.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
* data.size() ? &data[0] : 0,
* min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode
*
@@ -1182,527 +1367,640 @@ inline const_buffers_1 buffer(
* invalidate iterators.
*/
template <typename PodType, typename Allocator>
-inline const_buffers_1 buffer(
- const std::vector<PodType, Allocator>& data, std::size_t max_size_in_bytes)
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ const std::vector<PodType, Allocator>& data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data.size() ? &data[0] : 0,
- data.size() * sizeof(PodType) < max_size_in_bytes
- ? data.size() * sizeof(PodType) : max_size_in_bytes
+ return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,
+ data.size() * sizeof(PodType) < max_size_in_bytes
+ ? data.size() * sizeof(PodType) : max_size_in_bytes
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- , detail::buffer_debug_check<
- typename std::vector<PodType, Allocator>::const_iterator
- >(data.begin())
+ , detail::buffer_debug_check<
+ typename std::vector<PodType, Allocator>::const_iterator
+ >(data.begin())
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
- ));
+ );
}
-/// Create a new non-modifiable buffer that represents the given string.
+/// Create a new modifiable buffer that represents the given string.
/**
- * @returns <tt>const_buffers_1(data.data(), data.size() * sizeof(Elem))</tt>.
+ * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0,
+ * data.size() * sizeof(Elem))</tt>.
*
* @note The buffer is invalidated by any non-const operation called on the
* given string object.
*/
template <typename Elem, typename Traits, typename Allocator>
-inline const_buffers_1 buffer(
- const std::basic_string<Elem, Traits, Allocator>& data)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(
+ std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(const_buffer(data.data(), data.size() * sizeof(Elem)
+ return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,
+ data.size() * sizeof(Elem)
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- , detail::buffer_debug_check<
- typename std::basic_string<Elem, Traits, Allocator>::const_iterator
- >(data.begin())
+ , detail::buffer_debug_check<
+ typename std::basic_string<Elem, Traits, Allocator>::iterator
+ >(data.begin())
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
- ));
+ );
}
/// Create a new non-modifiable buffer that represents the given string.
/**
- * @returns A const_buffers_1 value equivalent to:
- * @code const_buffers_1(
- * data.data(),
+ * @returns A mutable_buffer value equivalent to:
+ * @code mutable_buffer(
+ * data.size() ? &data[0] : 0,
* min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode
*
* @note The buffer is invalidated by any non-const operation called on the
* given string object.
*/
template <typename Elem, typename Traits, typename Allocator>
-inline const_buffers_1 buffer(
- const std::basic_string<Elem, Traits, Allocator>& data,
- std::size_t max_size_in_bytes)
+inline BOOST_ASIO_MUTABLE_BUFFER buffer(
+ std::basic_string<Elem, Traits, Allocator>& data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return const_buffers_1(
- const_buffer(data.data(),
- data.size() * sizeof(Elem) < max_size_in_bytes
- ? data.size() * sizeof(Elem) : max_size_in_bytes
+ return BOOST_ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,
+ data.size() * sizeof(Elem) < max_size_in_bytes
+ ? data.size() * sizeof(Elem) : max_size_in_bytes
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
- , detail::buffer_debug_check<
- typename std::basic_string<Elem, Traits, Allocator>::const_iterator
- >(data.begin())
+ , detail::buffer_debug_check<
+ typename std::basic_string<Elem, Traits, Allocator>::iterator
+ >(data.begin())
#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
- ));
+ );
}
-/*@}*/
-
-/** @defgroup buffer_copy boost::asio::buffer_copy
- *
- * @brief The boost::asio::buffer_copy function is used to copy bytes from a
- * source buffer (or buffer sequence) to a target buffer (or buffer sequence).
- *
- * The @c buffer_copy function is available in two forms:
- *
- * @li A 2-argument form: @c buffer_copy(target, source)
- *
- * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy)
-
- * Both forms return the number of bytes actually copied. The number of bytes
- * copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c If specified, @c max_bytes_to_copy.
- *
- * This prevents buffer overflow, regardless of the buffer sizes used in the
- * copy operation.
- *
- * Note that @ref buffer_copy is implemented in terms of @c memcpy, and
- * consequently it cannot be used to copy between overlapping memory regions.
- */
-/*@{*/
-
-/// Copies bytes from a source buffer to a target buffer.
+/// Create a new non-modifiable buffer that represents the given string.
/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
+ * @returns <tt>const_buffer(data.data(), data.size() * sizeof(Elem))</tt>.
*
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
+ * @note The buffer is invalidated by any non-const operation called on the
+ * given string object.
*/
-inline std::size_t buffer_copy(const mutable_buffer& target,
- const const_buffer& source)
+template <typename Elem, typename Traits, typename Allocator>
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ const std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT
{
- using namespace std; // For memcpy.
- std::size_t target_size = buffer_size(target);
- std::size_t source_size = buffer_size(source);
- std::size_t n = target_size < source_size ? target_size : source_size;
- memcpy(buffer_cast<void*>(target), buffer_cast<const void*>(source), n);
- return n;
+ return BOOST_ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(Elem)
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , detail::buffer_debug_check<
+ typename std::basic_string<Elem, Traits, Allocator>::const_iterator
+ >(data.begin())
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ );
}
-/// Copies bytes from a source buffer to a target buffer.
+/// Create a new non-modifiable buffer that represents the given string.
/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
+ * @returns A const_buffer value equivalent to:
+ * @code const_buffer(
+ * data.data(),
+ * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode
*
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
+ * @note The buffer is invalidated by any non-const operation called on the
+ * given string object.
*/
-inline std::size_t buffer_copy(const mutable_buffer& target,
- const const_buffers_1& source)
+template <typename Elem, typename Traits, typename Allocator>
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ const std::basic_string<Elem, Traits, Allocator>& data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return buffer_copy(target, static_cast<const const_buffer&>(source));
+ return BOOST_ASIO_CONST_BUFFER(data.data(),
+ data.size() * sizeof(Elem) < max_size_in_bytes
+ ? data.size() * sizeof(Elem) : max_size_in_bytes
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , detail::buffer_debug_check<
+ typename std::basic_string<Elem, Traits, Allocator>::const_iterator
+ >(data.begin())
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ );
}
-/// Copies bytes from a source buffer to a target buffer.
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW) \
+ || defined(GENERATING_DOCUMENTATION)
+
+/// Create a new modifiable buffer that represents the given string_view.
/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
+ * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0,
+ * data.size() * sizeof(Elem))</tt>.
*/
-inline std::size_t buffer_copy(const mutable_buffer& target,
- const mutable_buffer& source)
+template <typename Elem, typename Traits>
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ basic_string_view<Elem, Traits> data) BOOST_ASIO_NOEXCEPT
{
- return buffer_copy(target, const_buffer(source));
+ return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,
+ data.size() * sizeof(Elem)
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , detail::buffer_debug_check<
+ typename basic_string_view<Elem, Traits>::iterator
+ >(data.begin())
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ );
}
-/// Copies bytes from a source buffer to a target buffer.
+/// Create a new non-modifiable buffer that represents the given string.
/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
+ * @returns A mutable_buffer value equivalent to:
+ * @code mutable_buffer(
+ * data.size() ? &data[0] : 0,
+ * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode
*/
-inline std::size_t buffer_copy(const mutable_buffer& target,
- const mutable_buffers_1& source)
+template <typename Elem, typename Traits>
+inline BOOST_ASIO_CONST_BUFFER buffer(
+ basic_string_view<Elem, Traits> data,
+ std::size_t max_size_in_bytes) BOOST_ASIO_NOEXCEPT
{
- return buffer_copy(target, const_buffer(source));
+ return BOOST_ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,
+ data.size() * sizeof(Elem) < max_size_in_bytes
+ ? data.size() * sizeof(Elem) : max_size_in_bytes
+#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
+ , detail::buffer_debug_check<
+ typename basic_string_view<Elem, Traits>::iterator
+ >(data.begin())
+#endif // BOOST_ASIO_ENABLE_BUFFER_DEBUGGING
+ );
}
-/// Copies bytes from a source buffer sequence to a target buffer.
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ // || defined(GENERATING_DOCUMENTATION)
+
+/*@}*/
+
+/// Adapt a basic_string to the DynamicBuffer requirements.
/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A non-modifiable buffer sequence representing the memory
- * regions from which the bytes will be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
+ * Requires that <tt>sizeof(Elem) == 1</tt>.
*/
-template <typename ConstBufferSequence>
-std::size_t buffer_copy(const mutable_buffer& target,
- const ConstBufferSequence& source)
+template <typename Elem, typename Traits, typename Allocator>
+class dynamic_string_buffer
{
- std::size_t total_bytes_copied = 0;
+public:
+ /// The type used to represent the input sequence as a list of buffers.
+ typedef BOOST_ASIO_CONST_BUFFER const_buffers_type;
+
+ /// The type used to represent the output sequence as a list of buffers.
+ typedef BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_type;
+
+ /// Construct a dynamic buffer from a string.
+ /**
+ * @param s The string to be used as backing storage for the dynamic buffer.
+ * Any existing data in the string is treated as the dynamic buffer's input
+ * sequence. The object stores a reference to the string and the user is
+ * responsible for ensuring that the string object remains valid until the
+ * dynamic_string_buffer object is destroyed.
+ *
+ * @param maximum_size Specifies a maximum size for the buffer, in bytes.
+ */
+ explicit dynamic_string_buffer(std::basic_string<Elem, Traits, Allocator>& s,
+ std::size_t maximum_size =
+ (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT
+ : string_(s),
+ size_(string_.size()),
+ max_size_(maximum_size)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move construct a dynamic buffer.
+ dynamic_string_buffer(dynamic_string_buffer&& other) BOOST_ASIO_NOEXCEPT
+ : string_(other.string_),
+ size_(other.size_),
+ max_size_(other.max_size_)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
- typename ConstBufferSequence::const_iterator source_iter = source.begin();
- typename ConstBufferSequence::const_iterator source_end = source.end();
+ /// Get the size of the input sequence.
+ std::size_t size() const BOOST_ASIO_NOEXCEPT
+ {
+ return size_;
+ }
- for (mutable_buffer target_buffer(target);
- buffer_size(target_buffer) && source_iter != source_end; ++source_iter)
+ /// Get the maximum size of the dynamic buffer.
+ /**
+ * @returns The allowed maximum of the sum of the sizes of the input sequence
+ * and output sequence.
+ */
+ std::size_t max_size() const BOOST_ASIO_NOEXCEPT
{
- const_buffer source_buffer(*source_iter);
- std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer);
- total_bytes_copied += bytes_copied;
- target_buffer = target_buffer + bytes_copied;
+ return max_size_;
}
- return total_bytes_copied;
-}
+ /// Get the current capacity of the dynamic buffer.
+ /**
+ * @returns The current total capacity of the buffer, i.e. for both the input
+ * sequence and output sequence.
+ */
+ std::size_t capacity() const BOOST_ASIO_NOEXCEPT
+ {
+ return string_.capacity();
+ }
+
+ /// Get a list of buffers that represents the input sequence.
+ /**
+ * @returns An object of type @c const_buffers_type that satisfies
+ * ConstBufferSequence requirements, representing the basic_string memory in
+ * input sequence.
+ *
+ * @note The returned object is invalidated by any @c dynamic_string_buffer
+ * or @c basic_string member function that modifies the input sequence or
+ * output sequence.
+ */
+ const_buffers_type data() const BOOST_ASIO_NOEXCEPT
+ {
+ return const_buffers_type(boost::asio::buffer(string_, size_));
+ }
+
+ /// Get a list of buffers that represents the output sequence, with the given
+ /// size.
+ /**
+ * Ensures that the output sequence can accommodate @c n bytes, resizing the
+ * basic_string object as necessary.
+ *
+ * @returns An object of type @c mutable_buffers_type that satisfies
+ * MutableBufferSequence requirements, representing basic_string memory
+ * at the start of the output sequence of size @c n.
+ *
+ * @throws std::length_error If <tt>size() + n > max_size()</tt>.
+ *
+ * @note The returned object is invalidated by any @c dynamic_string_buffer
+ * or @c basic_string member function that modifies the input sequence or
+ * output sequence.
+ */
+ mutable_buffers_type prepare(std::size_t n)
+ {
+ if (size () > max_size() || max_size() - size() < n)
+ {
+ std::length_error ex("dynamic_string_buffer too long");
+ boost::asio::detail::throw_exception(ex);
+ }
+
+ string_.resize(size_ + n);
+
+ return boost::asio::buffer(boost::asio::buffer(string_) + size_, n);
+ }
+
+ /// Move bytes from the output sequence to the input sequence.
+ /**
+ * @param n The number of bytes to append from the start of the output
+ * sequence to the end of the input sequence. The remainder of the output
+ * sequence is discarded.
+ *
+ * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and
+ * no intervening operations that modify the input or output sequence.
+ *
+ * @note If @c n is greater than the size of the output sequence, the entire
+ * output sequence is moved to the input sequence and no error is issued.
+ */
+ void commit(std::size_t n)
+ {
+ size_ += (std::min)(n, string_.size() - size_);
+ string_.resize(size_);
+ }
+
+ /// Remove characters from the input sequence.
+ /**
+ * Removes @c n characters from the beginning of the input sequence.
+ *
+ * @note If @c n is greater than the size of the input sequence, the entire
+ * input sequence is consumed and no error is issued.
+ */
+ void consume(std::size_t n)
+ {
+ std::size_t consume_length = (std::min)(n, size_);
+ string_.erase(0, consume_length);
+ size_ -= consume_length;
+ }
+
+private:
+ std::basic_string<Elem, Traits, Allocator>& string_;
+ std::size_t size_;
+ const std::size_t max_size_;
+};
-/// Copies bytes from a source buffer to a target buffer.
+/// Adapt a vector to the DynamicBuffer requirements.
/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
+ * Requires that <tt>sizeof(Elem) == 1</tt>.
*/
-inline std::size_t buffer_copy(const mutable_buffers_1& target,
- const const_buffer& source)
+template <typename Elem, typename Allocator>
+class dynamic_vector_buffer
{
- return buffer_copy(static_cast<const mutable_buffer&>(target), source);
-}
+public:
+ /// The type used to represent the input sequence as a list of buffers.
+ typedef BOOST_ASIO_CONST_BUFFER const_buffers_type;
+
+ /// The type used to represent the output sequence as a list of buffers.
+ typedef BOOST_ASIO_MUTABLE_BUFFER mutable_buffers_type;
+
+ /// Construct a dynamic buffer from a string.
+ /**
+ * @param v The vector to be used as backing storage for the dynamic buffer.
+ * Any existing data in the vector is treated as the dynamic buffer's input
+ * sequence. The object stores a reference to the vector and the user is
+ * responsible for ensuring that the vector object remains valid until the
+ * dynamic_vector_buffer object is destroyed.
+ *
+ * @param maximum_size Specifies a maximum size for the buffer, in bytes.
+ */
+ explicit dynamic_vector_buffer(std::vector<Elem, Allocator>& v,
+ std::size_t maximum_size =
+ (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT
+ : vector_(v),
+ size_(vector_.size()),
+ max_size_(maximum_size)
+ {
+ }
-/// Copies bytes from a source buffer to a target buffer.
-/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move construct a dynamic buffer.
+ dynamic_vector_buffer(dynamic_vector_buffer&& other) BOOST_ASIO_NOEXCEPT
+ : vector_(other.vector_),
+ size_(other.size_),
+ max_size_(other.max_size_)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Get the size of the input sequence.
+ std::size_t size() const BOOST_ASIO_NOEXCEPT
+ {
+ return size_;
+ }
+
+ /// Get the maximum size of the dynamic buffer.
+ /**
+ * @returns The allowed maximum of the sum of the sizes of the input sequence
+ * and output sequence.
+ */
+ std::size_t max_size() const BOOST_ASIO_NOEXCEPT
+ {
+ return max_size_;
+ }
+
+ /// Get the current capacity of the dynamic buffer.
+ /**
+ * @returns The current total capacity of the buffer, i.e. for both the input
+ * sequence and output sequence.
+ */
+ std::size_t capacity() const BOOST_ASIO_NOEXCEPT
+ {
+ return vector_.capacity();
+ }
+
+ /// Get a list of buffers that represents the input sequence.
+ /**
+ * @returns An object of type @c const_buffers_type that satisfies
+ * ConstBufferSequence requirements, representing the basic_string memory in
+ * input sequence.
+ *
+ * @note The returned object is invalidated by any @c dynamic_vector_buffer
+ * or @c basic_string member function that modifies the input sequence or
+ * output sequence.
+ */
+ const_buffers_type data() const BOOST_ASIO_NOEXCEPT
+ {
+ return const_buffers_type(boost::asio::buffer(vector_, size_));
+ }
+
+ /// Get a list of buffers that represents the output sequence, with the given
+ /// size.
+ /**
+ * Ensures that the output sequence can accommodate @c n bytes, resizing the
+ * basic_string object as necessary.
+ *
+ * @returns An object of type @c mutable_buffers_type that satisfies
+ * MutableBufferSequence requirements, representing basic_string memory
+ * at the start of the output sequence of size @c n.
+ *
+ * @throws std::length_error If <tt>size() + n > max_size()</tt>.
+ *
+ * @note The returned object is invalidated by any @c dynamic_vector_buffer
+ * or @c basic_string member function that modifies the input sequence or
+ * output sequence.
+ */
+ mutable_buffers_type prepare(std::size_t n)
+ {
+ if (size () > max_size() || max_size() - size() < n)
+ {
+ std::length_error ex("dynamic_vector_buffer too long");
+ boost::asio::detail::throw_exception(ex);
+ }
+
+ vector_.resize(size_ + n);
+
+ return boost::asio::buffer(boost::asio::buffer(vector_) + size_, n);
+ }
+
+ /// Move bytes from the output sequence to the input sequence.
+ /**
+ * @param n The number of bytes to append from the start of the output
+ * sequence to the end of the input sequence. The remainder of the output
+ * sequence is discarded.
+ *
+ * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and
+ * no intervening operations that modify the input or output sequence.
+ *
+ * @note If @c n is greater than the size of the output sequence, the entire
+ * output sequence is moved to the input sequence and no error is issued.
+ */
+ void commit(std::size_t n)
+ {
+ size_ += (std::min)(n, vector_.size() - size_);
+ vector_.resize(size_);
+ }
+
+ /// Remove characters from the input sequence.
+ /**
+ * Removes @c n characters from the beginning of the input sequence.
+ *
+ * @note If @c n is greater than the size of the input sequence, the entire
+ * input sequence is consumed and no error is issued.
+ */
+ void consume(std::size_t n)
+ {
+ std::size_t consume_length = (std::min)(n, size_);
+ vector_.erase(vector_.begin(), vector_.begin() + consume_length);
+ size_ -= consume_length;
+ }
+
+private:
+ std::vector<Elem, Allocator>& vector_;
+ std::size_t size_;
+ const std::size_t max_size_;
+};
+
+/** @defgroup dynamic_buffer boost::asio::dynamic_buffer
*
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
+ * @brief The boost::asio::dynamic_buffer function is used to create a
+ * dynamically resized buffer from a @c std::basic_string or @c std::vector.
+ */
+/*@{*/
+
+/// Create a new dynamic buffer that represents the given string.
+/**
+ * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data)</tt>.
*/
-inline std::size_t buffer_copy(const mutable_buffers_1& target,
- const const_buffers_1& source)
+template <typename Elem, typename Traits, typename Allocator>
+inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(
+ std::basic_string<Elem, Traits, Allocator>& data) BOOST_ASIO_NOEXCEPT
{
- return buffer_copy(static_cast<const mutable_buffer&>(target),
- static_cast<const const_buffer&>(source));
+ return dynamic_string_buffer<Elem, Traits, Allocator>(data);
}
-/// Copies bytes from a source buffer to a target buffer.
+/// Create a new dynamic buffer that represents the given string.
/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
+ * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data,
+ * max_size)</tt>.
*/
-inline std::size_t buffer_copy(const mutable_buffers_1& target,
- const mutable_buffer& source)
+template <typename Elem, typename Traits, typename Allocator>
+inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(
+ std::basic_string<Elem, Traits, Allocator>& data,
+ std::size_t max_size) BOOST_ASIO_NOEXCEPT
{
- return buffer_copy(static_cast<const mutable_buffer&>(target),
- const_buffer(source));
+ return dynamic_string_buffer<Elem, Traits, Allocator>(data, max_size);
}
-/// Copies bytes from a source buffer to a target buffer.
+/// Create a new dynamic buffer that represents the given vector.
/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
+ * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data)</tt>.
*/
-inline std::size_t buffer_copy(const mutable_buffers_1& target,
- const mutable_buffers_1& source)
+template <typename Elem, typename Allocator>
+inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(
+ std::vector<Elem, Allocator>& data) BOOST_ASIO_NOEXCEPT
{
- return buffer_copy(static_cast<const mutable_buffer&>(target),
- const_buffer(source));
+ return dynamic_vector_buffer<Elem, Allocator>(data);
}
-/// Copies bytes from a source buffer sequence to a target buffer.
+/// Create a new dynamic buffer that represents the given vector.
/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A non-modifiable buffer sequence representing the memory
- * regions from which the bytes will be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
+ * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data, max_size)</tt>.
*/
-template <typename ConstBufferSequence>
-inline std::size_t buffer_copy(const mutable_buffers_1& target,
- const ConstBufferSequence& source)
+template <typename Elem, typename Allocator>
+inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(
+ std::vector<Elem, Allocator>& data,
+ std::size_t max_size) BOOST_ASIO_NOEXCEPT
{
- return buffer_copy(static_cast<const mutable_buffer&>(target), source);
+ return dynamic_vector_buffer<Elem, Allocator>(data, max_size);
}
-/// Copies bytes from a source buffer to a target buffer sequence.
-/**
- * @param target A modifiable buffer sequence representing the memory regions to
- * which the bytes will be copied.
+/*@}*/
+
+/** @defgroup buffer_copy boost::asio::buffer_copy
*
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
+ * @brief The boost::asio::buffer_copy function is used to copy bytes from a
+ * source buffer (or buffer sequence) to a target buffer (or buffer sequence).
*
- * @returns The number of bytes copied.
+ * The @c buffer_copy function is available in two forms:
*
- * @note The number of bytes copied is the lesser of:
+ * @li A 2-argument form: @c buffer_copy(target, source)
+ *
+ * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy)
+ *
+ * Both forms return the number of bytes actually copied. The number of bytes
+ * copied is the lesser of:
*
* @li @c buffer_size(target)
*
* @li @c buffer_size(source)
*
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
+ * @li @c If specified, @c max_bytes_to_copy.
+ *
+ * This prevents buffer overflow, regardless of the buffer sizes used in the
+ * copy operation.
+ *
+ * Note that @ref buffer_copy is implemented in terms of @c memcpy, and
+ * consequently it cannot be used to copy between overlapping memory regions.
*/
-template <typename MutableBufferSequence>
-std::size_t buffer_copy(const MutableBufferSequence& target,
+/*@{*/
+
+namespace detail {
+
+inline std::size_t buffer_copy_1(const mutable_buffer& target,
const const_buffer& source)
{
- std::size_t total_bytes_copied = 0;
+ using namespace std; // For memcpy.
+ std::size_t target_size = target.size();
+ std::size_t source_size = source.size();
+ std::size_t n = target_size < source_size ? target_size : source_size;
+ if (n > 0)
+ memcpy(target.data(), source.data(), n);
+ return n;
+}
- typename MutableBufferSequence::const_iterator target_iter = target.begin();
- typename MutableBufferSequence::const_iterator target_end = target.end();
+template <typename TargetIterator, typename SourceIterator>
+inline std::size_t buffer_copy(one_buffer, one_buffer,
+ TargetIterator target_begin, TargetIterator,
+ SourceIterator source_begin, SourceIterator) BOOST_ASIO_NOEXCEPT
+{
+ return (buffer_copy_1)(*target_begin, *source_begin);
+}
- for (const_buffer source_buffer(source);
- buffer_size(source_buffer) && target_iter != target_end; ++target_iter)
+template <typename TargetIterator, typename SourceIterator>
+inline std::size_t buffer_copy(one_buffer, one_buffer,
+ TargetIterator target_begin, TargetIterator,
+ SourceIterator source_begin, SourceIterator,
+ std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT
+{
+ return (buffer_copy_1)(*target_begin,
+ boost::asio::buffer(*source_begin, max_bytes_to_copy));
+}
+
+template <typename TargetIterator, typename SourceIterator>
+std::size_t buffer_copy(one_buffer, multiple_buffers,
+ TargetIterator target_begin, TargetIterator,
+ SourceIterator source_begin, SourceIterator source_end,
+ std::size_t max_bytes_to_copy
+ = (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT
+{
+ std::size_t total_bytes_copied = 0;
+ SourceIterator source_iter = source_begin;
+
+ for (mutable_buffer target_buffer(
+ boost::asio::buffer(*target_begin, max_bytes_to_copy));
+ target_buffer.size() && source_iter != source_end; ++source_iter)
{
- mutable_buffer target_buffer(*target_iter);
- std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer);
+ const_buffer source_buffer(*source_iter);
+ std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
total_bytes_copied += bytes_copied;
- source_buffer = source_buffer + bytes_copied;
+ target_buffer += bytes_copied;
}
return total_bytes_copied;
}
-/// Copies bytes from a source buffer to a target buffer sequence.
-/**
- * @param target A modifiable buffer sequence representing the memory regions to
- * which the bytes will be copied.
- *
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-template <typename MutableBufferSequence>
-inline std::size_t buffer_copy(const MutableBufferSequence& target,
- const const_buffers_1& source)
+template <typename TargetIterator, typename SourceIterator>
+std::size_t buffer_copy(multiple_buffers, one_buffer,
+ TargetIterator target_begin, TargetIterator target_end,
+ SourceIterator source_begin, SourceIterator,
+ std::size_t max_bytes_to_copy
+ = (std::numeric_limits<std::size_t>::max)()) BOOST_ASIO_NOEXCEPT
{
- return buffer_copy(target, static_cast<const const_buffer&>(source));
-}
+ std::size_t total_bytes_copied = 0;
+ TargetIterator target_iter = target_begin;
-/// Copies bytes from a source buffer to a target buffer sequence.
-/**
- * @param target A modifiable buffer sequence representing the memory regions to
- * which the bytes will be copied.
- *
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-template <typename MutableBufferSequence>
-inline std::size_t buffer_copy(const MutableBufferSequence& target,
- const mutable_buffer& source)
-{
- return buffer_copy(target, const_buffer(source));
-}
+ for (const_buffer source_buffer(
+ boost::asio::buffer(*source_begin, max_bytes_to_copy));
+ source_buffer.size() && target_iter != target_end; ++target_iter)
+ {
+ mutable_buffer target_buffer(*target_iter);
+ std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
+ total_bytes_copied += bytes_copied;
+ source_buffer += bytes_copied;
+ }
-/// Copies bytes from a source buffer to a target buffer sequence.
-/**
- * @param target A modifiable buffer sequence representing the memory regions to
- * which the bytes will be copied.
- *
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-template <typename MutableBufferSequence>
-inline std::size_t buffer_copy(const MutableBufferSequence& target,
- const mutable_buffers_1& source)
-{
- return buffer_copy(target, const_buffer(source));
+ return total_bytes_copied;
}
-/// Copies bytes from a source buffer sequence to a target buffer sequence.
-/**
- * @param target A modifiable buffer sequence representing the memory regions to
- * which the bytes will be copied.
- *
- * @param source A non-modifiable buffer sequence representing the memory
- * regions from which the bytes will be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-template <typename MutableBufferSequence, typename ConstBufferSequence>
-std::size_t buffer_copy(const MutableBufferSequence& target,
- const ConstBufferSequence& source)
+template <typename TargetIterator, typename SourceIterator>
+std::size_t buffer_copy(multiple_buffers, multiple_buffers,
+ TargetIterator target_begin, TargetIterator target_end,
+ SourceIterator source_begin, SourceIterator source_end) BOOST_ASIO_NOEXCEPT
{
std::size_t total_bytes_copied = 0;
- typename MutableBufferSequence::const_iterator target_iter = target.begin();
- typename MutableBufferSequence::const_iterator target_end = target.end();
+ TargetIterator target_iter = target_begin;
std::size_t target_buffer_offset = 0;
- typename ConstBufferSequence::const_iterator source_iter = source.begin();
- typename ConstBufferSequence::const_iterator source_end = source.end();
+ SourceIterator source_iter = source_begin;
std::size_t source_buffer_offset = 0;
while (target_iter != target_end && source_iter != source_end)
@@ -1713,10 +2011,10 @@ std::size_t buffer_copy(const MutableBufferSequence& target,
const_buffer source_buffer =
const_buffer(*source_iter) + source_buffer_offset;
- std::size_t bytes_copied = buffer_copy(target_buffer, source_buffer);
+ std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);
total_bytes_copied += bytes_copied;
- if (bytes_copied == buffer_size(target_buffer))
+ if (bytes_copied == target_buffer.size())
{
++target_iter;
target_buffer_offset = 0;
@@ -1724,7 +2022,7 @@ std::size_t buffer_copy(const MutableBufferSequence& target,
else
target_buffer_offset += bytes_copied;
- if (bytes_copied == buffer_size(source_buffer))
+ if (bytes_copied == source_buffer.size())
{
++source_iter;
source_buffer_offset = 0;
@@ -1736,409 +2034,63 @@ std::size_t buffer_copy(const MutableBufferSequence& target,
return total_bytes_copied;
}
-/// Copies a limited number of bytes from a source buffer to a target buffer.
-/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-inline std::size_t buffer_copy(const mutable_buffer& target,
- const const_buffer& source, std::size_t max_bytes_to_copy)
+template <typename TargetIterator, typename SourceIterator>
+std::size_t buffer_copy(multiple_buffers, multiple_buffers,
+ TargetIterator target_begin, TargetIterator target_end,
+ SourceIterator source_begin, SourceIterator source_end,
+ std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT
{
- return buffer_copy(buffer(target, max_bytes_to_copy), source);
-}
-
-/// Copies a limited number of bytes from a source buffer to a target buffer.
-/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-inline std::size_t buffer_copy(const mutable_buffer& target,
- const const_buffers_1& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(buffer(target, max_bytes_to_copy), source);
-}
-
-/// Copies a limited number of bytes from a source buffer to a target buffer.
-/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-inline std::size_t buffer_copy(const mutable_buffer& target,
- const mutable_buffer& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(buffer(target, max_bytes_to_copy), source);
-}
-
-/// Copies a limited number of bytes from a source buffer to a target buffer.
-/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-inline std::size_t buffer_copy(const mutable_buffer& target,
- const mutable_buffers_1& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(buffer(target, max_bytes_to_copy), source);
-}
+ std::size_t total_bytes_copied = 0;
-/// Copies a limited number of bytes from a source buffer sequence to a target
-/// buffer.
-/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A non-modifiable buffer sequence representing the memory
- * regions from which the bytes will be copied.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-template <typename ConstBufferSequence>
-inline std::size_t buffer_copy(const mutable_buffer& target,
- const ConstBufferSequence& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(buffer(target, max_bytes_to_copy), source);
-}
+ TargetIterator target_iter = target_begin;
+ std::size_t target_buffer_offset = 0;
-/// Copies a limited number of bytes from a source buffer to a target buffer.
-/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-inline std::size_t buffer_copy(const mutable_buffers_1& target,
- const const_buffer& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(buffer(target, max_bytes_to_copy), source);
-}
+ SourceIterator source_iter = source_begin;
+ std::size_t source_buffer_offset = 0;
-/// Copies a limited number of bytes from a source buffer to a target buffer.
-/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-inline std::size_t buffer_copy(const mutable_buffers_1& target,
- const const_buffers_1& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(buffer(target, max_bytes_to_copy), source);
-}
+ while (total_bytes_copied != max_bytes_to_copy
+ && target_iter != target_end && source_iter != source_end)
+ {
+ mutable_buffer target_buffer =
+ mutable_buffer(*target_iter) + target_buffer_offset;
-/// Copies a limited number of bytes from a source buffer to a target buffer.
-/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-inline std::size_t buffer_copy(const mutable_buffers_1& target,
- const mutable_buffer& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(buffer(target, max_bytes_to_copy), source);
-}
+ const_buffer source_buffer =
+ const_buffer(*source_iter) + source_buffer_offset;
-/// Copies a limited number of bytes from a source buffer to a target buffer.
-/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-inline std::size_t buffer_copy(const mutable_buffers_1& target,
- const mutable_buffers_1& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(buffer(target, max_bytes_to_copy), source);
-}
+ std::size_t bytes_copied = (buffer_copy_1)(
+ target_buffer, boost::asio::buffer(source_buffer,
+ max_bytes_to_copy - total_bytes_copied));
+ total_bytes_copied += bytes_copied;
-/// Copies a limited number of bytes from a source buffer sequence to a target
-/// buffer.
-/**
- * @param target A modifiable buffer representing the memory region to which
- * the bytes will be copied.
- *
- * @param source A non-modifiable buffer sequence representing the memory
- * regions from which the bytes will be copied.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-template <typename ConstBufferSequence>
-inline std::size_t buffer_copy(const mutable_buffers_1& target,
- const ConstBufferSequence& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(buffer(target, max_bytes_to_copy), source);
-}
+ if (bytes_copied == target_buffer.size())
+ {
+ ++target_iter;
+ target_buffer_offset = 0;
+ }
+ else
+ target_buffer_offset += bytes_copied;
-/// Copies a limited number of bytes from a source buffer to a target buffer
-/// sequence.
-/**
- * @param target A modifiable buffer sequence representing the memory regions to
- * which the bytes will be copied.
- *
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-template <typename MutableBufferSequence>
-inline std::size_t buffer_copy(const MutableBufferSequence& target,
- const const_buffer& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(target, buffer(source, max_bytes_to_copy));
-}
+ if (bytes_copied == source_buffer.size())
+ {
+ ++source_iter;
+ source_buffer_offset = 0;
+ }
+ else
+ source_buffer_offset += bytes_copied;
+ }
-/// Copies a limited number of bytes from a source buffer to a target buffer
-/// sequence.
-/**
- * @param target A modifiable buffer sequence representing the memory regions to
- * which the bytes will be copied.
- *
- * @param source A non-modifiable buffer representing the memory region from
- * which the bytes will be copied.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-template <typename MutableBufferSequence>
-inline std::size_t buffer_copy(const MutableBufferSequence& target,
- const const_buffers_1& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(target, buffer(source, max_bytes_to_copy));
+ return total_bytes_copied;
}
-/// Copies a limited number of bytes from a source buffer to a target buffer
-/// sequence.
-/**
- * @param target A modifiable buffer sequence representing the memory regions to
- * which the bytes will be copied.
- *
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
- *
- * @returns The number of bytes copied.
- *
- * @note The number of bytes copied is the lesser of:
- *
- * @li @c buffer_size(target)
- *
- * @li @c buffer_size(source)
- *
- * @li @c max_bytes_to_copy
- *
- * This function is implemented in terms of @c memcpy, and consequently it
- * cannot be used to copy between overlapping memory regions.
- */
-template <typename MutableBufferSequence>
-inline std::size_t buffer_copy(const MutableBufferSequence& target,
- const mutable_buffer& source, std::size_t max_bytes_to_copy)
-{
- return buffer_copy(target, buffer(source, max_bytes_to_copy));
-}
+} // namespace detail
-/// Copies a limited number of bytes from a source buffer to a target buffer
-/// sequence.
+/// Copies bytes from a source buffer sequence to a target buffer sequence.
/**
* @param target A modifiable buffer sequence representing the memory regions to
* which the bytes will be copied.
*
- * @param source A modifiable buffer representing the memory region from which
- * the bytes will be copied. The contents of the source buffer will not be
- * modified.
- *
- * @param max_bytes_to_copy The maximum number of bytes to be copied.
+ * @param source A non-modifiable buffer sequence representing the memory
+ * regions from which the bytes will be copied.
*
* @returns The number of bytes copied.
*
@@ -2148,16 +2100,20 @@ inline std::size_t buffer_copy(const MutableBufferSequence& target,
*
* @li @c buffer_size(source)
*
- * @li @c max_bytes_to_copy
- *
* This function is implemented in terms of @c memcpy, and consequently it
* cannot be used to copy between overlapping memory regions.
*/
-template <typename MutableBufferSequence>
+template <typename MutableBufferSequence, typename ConstBufferSequence>
inline std::size_t buffer_copy(const MutableBufferSequence& target,
- const mutable_buffers_1& source, std::size_t max_bytes_to_copy)
+ const ConstBufferSequence& source) BOOST_ASIO_NOEXCEPT
{
- return buffer_copy(target, buffer(source, max_bytes_to_copy));
+ return detail::buffer_copy(
+ detail::buffer_sequence_cardinality<MutableBufferSequence>(),
+ detail::buffer_sequence_cardinality<ConstBufferSequence>(),
+ boost::asio::buffer_sequence_begin(target),
+ boost::asio::buffer_sequence_end(target),
+ boost::asio::buffer_sequence_begin(source),
+ boost::asio::buffer_sequence_end(source));
}
/// Copies a limited number of bytes from a source buffer sequence to a target
@@ -2185,50 +2141,17 @@ inline std::size_t buffer_copy(const MutableBufferSequence& target,
* cannot be used to copy between overlapping memory regions.
*/
template <typename MutableBufferSequence, typename ConstBufferSequence>
-std::size_t buffer_copy(const MutableBufferSequence& target,
- const ConstBufferSequence& source, std::size_t max_bytes_to_copy)
-{
- std::size_t total_bytes_copied = 0;
-
- typename MutableBufferSequence::const_iterator target_iter = target.begin();
- typename MutableBufferSequence::const_iterator target_end = target.end();
- std::size_t target_buffer_offset = 0;
-
- typename ConstBufferSequence::const_iterator source_iter = source.begin();
- typename ConstBufferSequence::const_iterator source_end = source.end();
- std::size_t source_buffer_offset = 0;
-
- while (total_bytes_copied != max_bytes_to_copy
- && target_iter != target_end && source_iter != source_end)
- {
- mutable_buffer target_buffer =
- mutable_buffer(*target_iter) + target_buffer_offset;
-
- const_buffer source_buffer =
- const_buffer(*source_iter) + source_buffer_offset;
-
- std::size_t bytes_copied = buffer_copy(target_buffer,
- source_buffer, max_bytes_to_copy - total_bytes_copied);
- total_bytes_copied += bytes_copied;
-
- if (bytes_copied == buffer_size(target_buffer))
- {
- ++target_iter;
- target_buffer_offset = 0;
- }
- else
- target_buffer_offset += bytes_copied;
-
- if (bytes_copied == buffer_size(source_buffer))
- {
- ++source_iter;
- source_buffer_offset = 0;
- }
- else
- source_buffer_offset += bytes_copied;
- }
-
- return total_bytes_copied;
+inline std::size_t buffer_copy(const MutableBufferSequence& target,
+ const ConstBufferSequence& source,
+ std::size_t max_bytes_to_copy) BOOST_ASIO_NOEXCEPT
+{
+ return detail::buffer_copy(
+ detail::buffer_sequence_cardinality<MutableBufferSequence>(),
+ detail::buffer_sequence_cardinality<ConstBufferSequence>(),
+ boost::asio::buffer_sequence_begin(target),
+ boost::asio::buffer_sequence_end(target),
+ boost::asio::buffer_sequence_begin(source),
+ boost::asio::buffer_sequence_end(source), max_bytes_to_copy);
}
/*@}*/
diff --git a/boost/asio/buffered_read_stream.hpp b/boost/asio/buffered_read_stream.hpp
index ece138b599..9774ee9d52 100644
--- a/boost/asio/buffered_read_stream.hpp
+++ b/boost/asio/buffered_read_stream.hpp
@@ -26,7 +26,7 @@
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -56,6 +56,9 @@ public:
/// The type of the lowest layer.
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
+ /// The type of the executor associated with the object.
+ typedef typename lowest_layer_type::executor_type executor_type;
+
#if defined(GENERATING_DOCUMENTATION)
/// The default buffer size.
static const std::size_t default_buffer_size = implementation_defined;
@@ -97,11 +100,27 @@ public:
return next_layer_.lowest_layer();
}
- /// Get the io_service associated with the object.
- boost::asio::io_service& get_io_service()
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return next_layer_.lowest_layer().get_executor();
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ boost::asio::io_context& get_io_context()
+ {
+ return next_layer_.get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ boost::asio::io_context& get_io_service()
{
return next_layer_.get_io_service();
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Close the stream.
void close()
@@ -110,9 +129,10 @@ public:
}
/// Close the stream.
- boost::system::error_code close(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
- return next_layer_.close(ec);
+ next_layer_.close(ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Write the given data to the stream. Returns the number of bytes written.
@@ -140,15 +160,8 @@ public:
async_write_some(const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
+ return next_layer_.async_write_some(buffers,
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
-
- next_layer_.async_write_some(buffers,
- BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(WriteHandler,
- void (boost::system::error_code, std::size_t)))(init.handler));
-
- return init.result.get();
}
/// Fill the buffer with some data. Returns the number of bytes placed in the
diff --git a/boost/asio/buffered_stream.hpp b/boost/asio/buffered_stream.hpp
index fae7c27113..a468370ffe 100644
--- a/boost/asio/buffered_stream.hpp
+++ b/boost/asio/buffered_stream.hpp
@@ -23,7 +23,7 @@
#include <boost/asio/buffered_stream_fwd.hpp>
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -53,6 +53,9 @@ public:
/// The type of the lowest layer.
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
+ /// The type of the executor associated with the object.
+ typedef typename lowest_layer_type::executor_type executor_type;
+
/// Construct, passing the specified argument to initialise the next layer.
template <typename Arg>
explicit buffered_stream(Arg& a)
@@ -88,11 +91,27 @@ public:
return stream_impl_.lowest_layer();
}
- /// Get the io_service associated with the object.
- boost::asio::io_service& get_io_service()
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return stream_impl_.lowest_layer().get_executor();
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ boost::asio::io_context& get_io_context()
+ {
+ return stream_impl_.get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ boost::asio::io_context& get_io_service()
{
return stream_impl_.get_io_service();
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Close the stream.
void close()
@@ -101,9 +120,10 @@ public:
}
/// Close the stream.
- boost::system::error_code close(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
- return stream_impl_.close(ec);
+ stream_impl_.close(ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Flush all data from the buffer to the next layer. Returns the number of
diff --git a/boost/asio/buffered_write_stream.hpp b/boost/asio/buffered_write_stream.hpp
index 5b8f31378d..a1b9c44016 100644
--- a/boost/asio/buffered_write_stream.hpp
+++ b/boost/asio/buffered_write_stream.hpp
@@ -25,7 +25,7 @@
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/write.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -56,6 +56,9 @@ public:
/// The type of the lowest layer.
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
+ /// The type of the executor associated with the object.
+ typedef typename lowest_layer_type::executor_type executor_type;
+
#if defined(GENERATING_DOCUMENTATION)
/// The default buffer size.
static const std::size_t default_buffer_size = implementation_defined;
@@ -97,11 +100,27 @@ public:
return next_layer_.lowest_layer();
}
- /// Get the io_service associated with the object.
- boost::asio::io_service& get_io_service()
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return next_layer_.lowest_layer().get_executor();
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ boost::asio::io_context& get_io_context()
+ {
+ return next_layer_.get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ boost::asio::io_context& get_io_service()
{
return next_layer_.get_io_service();
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Close the stream.
void close()
@@ -110,9 +129,10 @@ public:
}
/// Close the stream.
- boost::system::error_code close(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
- return next_layer_.close(ec);
+ next_layer_.close(ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Flush all data from the buffer to the next layer. Returns the number of
@@ -175,15 +195,8 @@ public:
async_read_some(const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
+ return next_layer_.async_read_some(buffers,
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
-
- next_layer_.async_read_some(buffers,
- BOOST_ASIO_MOVE_CAST(BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t)))(init.handler));
-
- return init.result.get();
}
/// Peek at the incoming data on the stream. Returns the number of bytes read.
diff --git a/boost/asio/buffers_iterator.hpp b/boost/asio/buffers_iterator.hpp
index c64b341b5b..bebbca1b9e 100644
--- a/boost/asio/buffers_iterator.hpp
+++ b/boost/asio/buffers_iterator.hpp
@@ -66,7 +66,44 @@ namespace detail
typedef buffers_iterator_types_helper<is_mutable> helper;
typedef typename helper::buffer_type buffer_type;
typedef typename helper::template byte_type<ByteType>::type byte_type;
+ typedef typename BufferSequence::const_iterator const_iterator;
};
+
+ template <typename ByteType>
+ struct buffers_iterator_types<mutable_buffer, ByteType>
+ {
+ typedef mutable_buffer buffer_type;
+ typedef ByteType byte_type;
+ typedef const mutable_buffer* const_iterator;
+ };
+
+ template <typename ByteType>
+ struct buffers_iterator_types<const_buffer, ByteType>
+ {
+ typedef const_buffer buffer_type;
+ typedef typename add_const<ByteType>::type byte_type;
+ typedef const const_buffer* const_iterator;
+ };
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ template <typename ByteType>
+ struct buffers_iterator_types<mutable_buffers_1, ByteType>
+ {
+ typedef mutable_buffer buffer_type;
+ typedef ByteType byte_type;
+ typedef const mutable_buffer* const_iterator;
+ };
+
+ template <typename ByteType>
+ struct buffers_iterator_types<const_buffers_1, ByteType>
+ {
+ typedef const_buffer buffer_type;
+ typedef typename add_const<ByteType>::type byte_type;
+ typedef const const_buffer* const_iterator;
+ };
+
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
}
/// A random access iterator over the bytes in a buffer sequence.
@@ -77,6 +114,9 @@ private:
typedef typename detail::buffers_iterator_types<
BufferSequence, ByteType>::buffer_type buffer_type;
+ typedef typename detail::buffers_iterator_types<BufferSequence,
+ ByteType>::const_iterator buffer_sequence_iterator_type;
+
public:
/// The type used for the distance between two iterators.
typedef std::ptrdiff_t difference_type;
@@ -131,13 +171,13 @@ public:
#endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
{
buffers_iterator new_iter;
- new_iter.begin_ = buffers.begin();
- new_iter.current_ = buffers.begin();
- new_iter.end_ = buffers.end();
+ new_iter.begin_ = boost::asio::buffer_sequence_begin(buffers);
+ new_iter.current_ = boost::asio::buffer_sequence_begin(buffers);
+ new_iter.end_ = boost::asio::buffer_sequence_end(buffers);
while (new_iter.current_ != new_iter.end_)
{
new_iter.current_buffer_ = *new_iter.current_;
- if (boost::asio::buffer_size(new_iter.current_buffer_) > 0)
+ if (new_iter.current_buffer_.size() > 0)
break;
++new_iter.current_;
}
@@ -151,13 +191,13 @@ public:
#endif // defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3)
{
buffers_iterator new_iter;
- new_iter.begin_ = buffers.begin();
- new_iter.current_ = buffers.begin();
- new_iter.end_ = buffers.end();
+ new_iter.begin_ = boost::asio::buffer_sequence_begin(buffers);
+ new_iter.current_ = boost::asio::buffer_sequence_begin(buffers);
+ new_iter.end_ = boost::asio::buffer_sequence_end(buffers);
while (new_iter.current_ != new_iter.end_)
{
buffer_type buffer = *new_iter.current_;
- new_iter.position_ += boost::asio::buffer_size(buffer);
+ new_iter.position_ += buffer.size();
++new_iter.current_;
}
return new_iter;
@@ -301,7 +341,8 @@ private:
// Dereference the iterator.
reference dereference() const
{
- return buffer_cast<pointer>(current_buffer_)[current_buffer_position_];
+ return static_cast<pointer>(
+ current_buffer_.data())[current_buffer_position_];
}
// Compare two iterators for equality.
@@ -318,7 +359,7 @@ private:
// Check if the increment can be satisfied by the current buffer.
++current_buffer_position_;
- if (current_buffer_position_ != boost::asio::buffer_size(current_buffer_))
+ if (current_buffer_position_ != current_buffer_.size())
return;
// Find the next non-empty buffer.
@@ -327,7 +368,7 @@ private:
while (current_ != end_)
{
current_buffer_ = *current_;
- if (boost::asio::buffer_size(current_buffer_) > 0)
+ if (current_buffer_.size() > 0)
return;
++current_;
}
@@ -347,12 +388,12 @@ private:
}
// Find the previous non-empty buffer.
- typename BufferSequence::const_iterator iter = current_;
+ buffer_sequence_iterator_type iter = current_;
while (iter != begin_)
{
--iter;
buffer_type buffer = *iter;
- std::size_t buffer_size = boost::asio::buffer_size(buffer);
+ std::size_t buffer_size = buffer.size();
if (buffer_size > 0)
{
current_ = iter;
@@ -372,8 +413,7 @@ private:
for (;;)
{
std::ptrdiff_t current_buffer_balance
- = boost::asio::buffer_size(current_buffer_)
- - current_buffer_position_;
+ = current_buffer_.size() - current_buffer_position_;
// Check if the advance can be satisfied by the current buffer.
if (current_buffer_balance > n)
@@ -427,12 +467,12 @@ private:
}
// Find the previous non-empty buffer.
- typename BufferSequence::const_iterator iter = current_;
+ buffer_sequence_iterator_type iter = current_;
while (iter != begin_)
{
--iter;
buffer_type buffer = *iter;
- std::size_t buffer_size = boost::asio::buffer_size(buffer);
+ std::size_t buffer_size = buffer.size();
if (buffer_size > 0)
{
current_ = iter;
@@ -453,9 +493,9 @@ private:
buffer_type current_buffer_;
std::size_t current_buffer_position_;
- typename BufferSequence::const_iterator begin_;
- typename BufferSequence::const_iterator current_;
- typename BufferSequence::const_iterator end_;
+ buffer_sequence_iterator_type begin_;
+ buffer_sequence_iterator_type current_;
+ buffer_sequence_iterator_type end_;
std::size_t position_;
};
diff --git a/boost/asio/connect.hpp b/boost/asio/connect.hpp
index 635a8ad9bd..e31e8c92cd 100644
--- a/boost/asio/connect.hpp
+++ b/boost/asio/connect.hpp
@@ -18,6 +18,7 @@
#include <boost/asio/detail/config.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -25,6 +26,36 @@
namespace boost {
namespace asio {
+namespace detail
+{
+ char (&has_iterator_helper(...))[2];
+
+ template <typename T>
+ char has_iterator_helper(T*, typename T::iterator* = 0);
+
+ template <typename T>
+ struct has_iterator_typedef
+ {
+ enum { value = (sizeof((has_iterator_helper)((T*)(0))) == 1) };
+ };
+} // namespace detail
+
+/// Type trait used to determine whether a type is an endpoint sequence that can
+/// be used with with @c connect and @c async_connect.
+template <typename T>
+struct is_endpoint_sequence
+{
+#if defined(GENERATING_DOCUMENTATION)
+ /// The value member is true if the type may be used as an endpoint sequence.
+ static const bool value;
+#else
+ enum
+ {
+ value = detail::has_iterator_typedef<T>::value
+ };
+#endif
+};
+
/**
* @defgroup connect boost::asio::connect
*
@@ -42,27 +73,26 @@ namespace asio {
* @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 endpoints A sequence of endpoints.
*
- * @returns On success, an iterator denoting the successfully connected
- * endpoint. Otherwise, the end iterator.
+ * @returns The successfully connected endpoint.
*
* @throws boost::system::system_error Thrown on failure. If the sequence is
* empty, the associated @c error_code is boost::asio::error::not_found.
* Otherwise, contains the error from the last connection attempt.
*
- * @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 boost::asio::ip::tcp::resolver::iterator.
- *
* @par Example
- * @code tcp::resolver r(io_service);
+ * @code tcp::resolver r(io_context);
* tcp::resolver::query q("host", "service");
- * tcp::socket s(io_service);
+ * tcp::socket s(io_context);
* boost::asio::connect(s, r.resolve(q)); @endcode
*/
-template <typename Protocol, typename SocketService, typename Iterator>
-Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin);
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence>
+typename Protocol::endpoint connect(
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type* = 0);
/// Establishes a socket connection by trying each endpoint in a sequence.
/**
@@ -74,23 +104,19 @@ Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin);
* @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 endpoints A sequence of endpoints.
*
* @param ec Set to indicate what error occurred, if any. If the sequence is
* empty, set to boost::asio::error::not_found. Otherwise, contains the error
* from the last connection attempt.
*
- * @returns On success, an iterator denoting the successfully connected
- * endpoint. Otherwise, the end iterator.
- *
- * @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 boost::asio::ip::tcp::resolver::iterator.
+ * @returns On success, the successfully connected endpoint. Otherwise, a
+ * default-constructed endpoint.
*
* @par Example
- * @code tcp::resolver r(io_service);
+ * @code tcp::resolver r(io_context);
* tcp::resolver::query q("host", "service");
- * tcp::socket s(io_service);
+ * tcp::socket s(io_context);
* boost::system::error_code ec;
* boost::asio::connect(s, r.resolve(q), ec);
* if (ec)
@@ -98,11 +124,16 @@ Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin);
* // An error occurred.
* } @endcode
*/
-template <typename Protocol, typename SocketService, typename Iterator>
-Iterator connect(basic_socket<Protocol, SocketService>& s,
- Iterator begin, boost::system::error_code& ec);
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence>
+typename Protocol::endpoint connect(
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints, boost::system::error_code& ec,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type* = 0);
-/// Establishes a socket connection by trying each endpoint in a sequence.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+/// (Deprecated.) Establishes a socket connection by trying each endpoint in a
+/// sequence.
/**
* 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 connect member
@@ -114,24 +145,80 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
*
* @param begin An iterator pointing to the start of a sequence of endpoints.
*
- * @param end An iterator pointing to the end of a sequence of endpoints.
+ * @returns On success, an iterator denoting the successfully connected
+ * endpoint. Otherwise, the end iterator.
+ *
+ * @throws boost::system::system_error Thrown on failure. If the sequence is
+ * empty, the associated @c error_code is boost::asio::error::not_found.
+ * Otherwise, contains the error from the last connection attempt.
+ *
+ * @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 boost::asio::ip::tcp::resolver::iterator.
+ */
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
+
+/// (Deprecated.) Establishes a socket connection by trying each endpoint in a
+/// sequence.
+/**
+ * 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 connect member
+ * function, once for each endpoint in the sequence, until a connection is
+ * successfully established.
+ *
+ * @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 ec Set to indicate what error occurred, if any. If the sequence is
+ * empty, set to boost::asio::error::not_found. Otherwise, contains the error
+ * from the last connection attempt.
*
* @returns On success, an iterator denoting the successfully connected
* endpoint. Otherwise, the end iterator.
*
+ * @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 boost::asio::ip::tcp::resolver::iterator.
+ */
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ Iterator begin, boost::system::error_code& ec,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+/// Establishes a socket connection by trying each endpoint in a sequence.
+/**
+ * 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 connect member
+ * function, once for each endpoint in the sequence, until a connection is
+ * successfully established.
+ *
+ * @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 end An iterator pointing to the end of a sequence of endpoints.
+ *
+ * @returns An iterator denoting the successfully connected endpoint.
+ *
* @throws boost::system::system_error Thrown on failure. If the sequence is
* empty, the associated @c error_code is boost::asio::error::not_found.
* Otherwise, contains the error from the last connection attempt.
*
* @par Example
- * @code tcp::resolver r(io_service);
+ * @code tcp::resolver r(io_context);
* tcp::resolver::query q("host", "service");
- * tcp::resolver::iterator i = r.resolve(q), end;
- * tcp::socket s(io_service);
- * boost::asio::connect(s, i, end); @endcode
+ * tcp::resolver::results_type e = r.resolve(q);
+ * tcp::socket s(io_context);
+ * boost::asio::connect(s, e.begin(), e.end()); @endcode
*/
-template <typename Protocol, typename SocketService, typename Iterator>
-Iterator connect(basic_socket<Protocol, SocketService>& s,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, Iterator end);
/// Establishes a socket connection by trying each endpoint in a sequence.
@@ -156,19 +243,19 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
* endpoint. Otherwise, the end iterator.
*
* @par Example
- * @code tcp::resolver r(io_service);
+ * @code tcp::resolver r(io_context);
* tcp::resolver::query q("host", "service");
- * tcp::resolver::iterator i = r.resolve(q), end;
- * tcp::socket s(io_service);
+ * tcp::resolver::results_type e = r.resolve(q);
+ * tcp::socket s(io_context);
* boost::system::error_code ec;
- * boost::asio::connect(s, i, end, ec);
+ * boost::asio::connect(s, e.begin(), e.end(), ec);
* if (ec)
* {
* // An error occurred.
* } @endcode
*/
-template <typename Protocol, typename SocketService, typename Iterator>
-Iterator connect(basic_socket<Protocol, SocketService>& s,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, boost::system::error_code& ec);
/// Establishes a socket connection by trying each endpoint in a sequence.
@@ -181,59 +268,54 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
* @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 endpoints A sequence of endpoints.
*
* @param connect_condition A function object that is called prior to each
* connection attempt. The signature of the function object must be:
- * @code Iterator connect_condition(
+ * @code bool connect_condition(
* const boost::system::error_code& ec,
- * Iterator next); @endcode
+ * const typename Protocol::endpoint& next); @endcode
* The @c ec parameter contains the result from the most recent connect
* operation. Before the first connection attempt, @c ec is always set to
- * indicate success. The @c next parameter is an iterator pointing to the next
- * endpoint to be tried. The function object should return the next iterator,
- * but is permitted to return a different iterator so that endpoints may be
- * skipped. The implementation guarantees that the function object will never
- * be called with the end iterator.
+ * indicate success. The @c next parameter is the next endpoint to be tried.
+ * The function object should return true if the next endpoint should be tried,
+ * and false if it should be skipped.
*
- * @returns On success, an iterator denoting the successfully connected
- * endpoint. Otherwise, the end iterator.
+ * @returns The successfully connected endpoint.
*
* @throws boost::system::system_error Thrown on failure. If the sequence is
* empty, the associated @c error_code is boost::asio::error::not_found.
* Otherwise, contains the error from the last connection attempt.
*
- * @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 boost::asio::ip::tcp::resolver::iterator.
- *
* @par Example
* The following connect condition function object can be used to output
* information about the individual connection attempts:
* @code struct my_connect_condition
* {
- * template <typename Iterator>
- * Iterator operator()(
+ * bool operator()(
* const boost::system::error_code& ec,
- * Iterator next)
+ * const::tcp::endpoint& next)
* {
* if (ec) std::cout << "Error: " << ec.message() << std::endl;
- * std::cout << "Trying: " << next->endpoint() << std::endl;
- * return next;
+ * std::cout << "Trying: " << next << std::endl;
+ * return true;
* }
* }; @endcode
* It would be used with the boost::asio::connect function as follows:
- * @code tcp::resolver r(io_service);
+ * @code tcp::resolver r(io_context);
* tcp::resolver::query q("host", "service");
- * tcp::socket s(io_service);
- * tcp::resolver::iterator i = boost::asio::connect(
- * s, r.resolve(q), my_connect_condition());
- * std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode
+ * tcp::socket s(io_context);
+ * tcp::endpoint e = boost::asio::connect(s,
+ * r.resolve(q), my_connect_condition());
+ * std::cout << "Connected to: " << e << std::endl; @endcode
*/
-template <typename Protocol, typename SocketService,
- typename Iterator, typename ConnectCondition>
-Iterator connect(basic_socket<Protocol, SocketService>& s,
- Iterator begin, ConnectCondition connect_condition);
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename ConnectCondition>
+typename Protocol::endpoint connect(
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints, ConnectCondition connect_condition,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type* = 0);
/// Establishes a socket connection by trying each endpoint in a sequence.
/**
@@ -245,67 +327,148 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
* @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 endpoints A sequence of endpoints.
*
* @param connect_condition A function object that is called prior to each
* connection attempt. The signature of the function object must be:
- * @code Iterator connect_condition(
+ * @code bool connect_condition(
* const boost::system::error_code& ec,
- * Iterator next); @endcode
+ * const typename Protocol::endpoint& next); @endcode
* The @c ec parameter contains the result from the most recent connect
* operation. Before the first connection attempt, @c ec is always set to
- * indicate success. The @c next parameter is an iterator pointing to the next
- * endpoint to be tried. The function object should return the next iterator,
- * but is permitted to return a different iterator so that endpoints may be
- * skipped. The implementation guarantees that the function object will never
- * be called with the end iterator.
+ * indicate success. The @c next parameter is the next endpoint to be tried.
+ * The function object should return true if the next endpoint should be tried,
+ * and false if it should be skipped.
*
* @param ec Set to indicate what error occurred, if any. If the sequence is
* empty, set to boost::asio::error::not_found. Otherwise, contains the error
* from the last connection attempt.
*
- * @returns On success, an iterator denoting the successfully connected
- * endpoint. Otherwise, the end iterator.
- *
- * @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 boost::asio::ip::tcp::resolver::iterator.
+ * @returns On success, the successfully connected endpoint. Otherwise, a
+ * default-constructed endpoint.
*
* @par Example
* The following connect condition function object can be used to output
* information about the individual connection attempts:
* @code struct my_connect_condition
* {
- * template <typename Iterator>
- * Iterator operator()(
+ * bool operator()(
* const boost::system::error_code& ec,
- * Iterator next)
+ * const::tcp::endpoint& next)
* {
* if (ec) std::cout << "Error: " << ec.message() << std::endl;
- * std::cout << "Trying: " << next->endpoint() << std::endl;
- * return next;
+ * std::cout << "Trying: " << next << std::endl;
+ * return true;
* }
* }; @endcode
* It would be used with the boost::asio::connect function as follows:
- * @code tcp::resolver r(io_service);
+ * @code tcp::resolver r(io_context);
* tcp::resolver::query q("host", "service");
- * tcp::socket s(io_service);
+ * tcp::socket s(io_context);
* boost::system::error_code ec;
- * tcp::resolver::iterator i = boost::asio::connect(
- * s, r.resolve(q), my_connect_condition(), ec);
+ * tcp::endpoint e = boost::asio::connect(s,
+ * r.resolve(q), my_connect_condition(), ec);
* if (ec)
* {
* // An error occurred.
* }
* else
* {
- * std::cout << "Connected to: " << i->endpoint() << std::endl;
+ * std::cout << "Connected to: " << e << std::endl;
* } @endcode
*/
-template <typename Protocol, typename SocketService,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename ConnectCondition>
+typename Protocol::endpoint connect(
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints, ConnectCondition connect_condition,
+ boost::system::error_code& ec,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type* = 0);
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+/// (Deprecated.) Establishes a socket connection by trying each endpoint in a
+/// sequence.
+/**
+ * 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 connect member
+ * function, once for each endpoint in the sequence, until a connection is
+ * successfully established.
+ *
+ * @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 connect_condition A function object that is called prior to each
+ * connection attempt. The signature of the function object must be:
+ * @code bool connect_condition(
+ * const boost::system::error_code& ec,
+ * const typename Protocol::endpoint& next); @endcode
+ * The @c ec parameter contains the result from the most recent connect
+ * operation. Before the first connection attempt, @c ec is always set to
+ * indicate success. The @c next parameter is the next endpoint to be tried.
+ * The function object should return true if the next endpoint should be tried,
+ * and false if it should be skipped.
+ *
+ * @returns On success, an iterator denoting the successfully connected
+ * endpoint. Otherwise, the end iterator.
+ *
+ * @throws boost::system::system_error Thrown on failure. If the sequence is
+ * empty, the associated @c error_code is boost::asio::error::not_found.
+ * Otherwise, contains the error from the last connection attempt.
+ *
+ * @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 boost::asio::ip::tcp::resolver::iterator.
+ */
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition>
-Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin,
- ConnectCondition connect_condition, boost::system::error_code& ec);
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ Iterator begin, ConnectCondition connect_condition,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
+
+/// (Deprecated.) Establishes a socket connection by trying each endpoint in a
+/// sequence.
+/**
+ * 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 connect member
+ * function, once for each endpoint in the sequence, until a connection is
+ * successfully established.
+ *
+ * @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 connect_condition A function object that is called prior to each
+ * connection attempt. The signature of the function object must be:
+ * @code bool connect_condition(
+ * const boost::system::error_code& ec,
+ * const typename Protocol::endpoint& next); @endcode
+ * The @c ec parameter contains the result from the most recent connect
+ * operation. Before the first connection attempt, @c ec is always set to
+ * indicate success. The @c next parameter is the next endpoint to be tried.
+ * The function object should return true if the next endpoint should be tried,
+ * and false if it should be skipped.
+ *
+ * @param ec Set to indicate what error occurred, if any. If the sequence is
+ * empty, set to boost::asio::error::not_found. Otherwise, contains the error
+ * from the last connection attempt.
+ *
+ * @returns On success, an iterator denoting the successfully connected
+ * endpoint. Otherwise, the end iterator.
+ *
+ * @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 boost::asio::ip::tcp::resolver::iterator.
+ */
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename Iterator, typename ConnectCondition>
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin,
+ ConnectCondition connect_condition, boost::system::error_code& ec,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Establishes a socket connection by trying each endpoint in a sequence.
/**
@@ -323,19 +486,16 @@ Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin,
*
* @param connect_condition A function object that is called prior to each
* connection attempt. The signature of the function object must be:
- * @code Iterator connect_condition(
+ * @code bool connect_condition(
* const boost::system::error_code& ec,
- * Iterator next); @endcode
+ * const typename Protocol::endpoint& next); @endcode
* The @c ec parameter contains the result from the most recent connect
* operation. Before the first connection attempt, @c ec is always set to
- * indicate success. The @c next parameter is an iterator pointing to the next
- * endpoint to be tried. The function object should return the next iterator,
- * but is permitted to return a different iterator so that endpoints may be
- * skipped. The implementation guarantees that the function object will never
- * be called with the end iterator.
+ * indicate success. The @c next parameter is the next endpoint to be tried.
+ * The function object should return true if the next endpoint should be tried,
+ * and false if it should be skipped.
*
- * @returns On success, an iterator denoting the successfully connected
- * endpoint. Otherwise, the end iterator.
+ * @returns An iterator denoting the successfully connected endpoint.
*
* @throws boost::system::system_error Thrown on failure. If the sequence is
* empty, the associated @c error_code is boost::asio::error::not_found.
@@ -346,27 +506,27 @@ Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin,
* information about the individual connection attempts:
* @code struct my_connect_condition
* {
- * template <typename Iterator>
- * Iterator operator()(
+ * bool operator()(
* const boost::system::error_code& ec,
- * Iterator next)
+ * const::tcp::endpoint& next)
* {
* if (ec) std::cout << "Error: " << ec.message() << std::endl;
- * std::cout << "Trying: " << next->endpoint() << std::endl;
- * return next;
+ * std::cout << "Trying: " << next << std::endl;
+ * return true;
* }
* }; @endcode
* It would be used with the boost::asio::connect function as follows:
- * @code tcp::resolver r(io_service);
+ * @code tcp::resolver r(io_context);
* tcp::resolver::query q("host", "service");
- * tcp::resolver::iterator i = r.resolve(q), end;
- * tcp::socket s(io_service);
- * i = boost::asio::connect(s, i, end, my_connect_condition());
+ * tcp::resolver::results_type e = r.resolve(q);
+ * tcp::socket s(io_context);
+ * tcp::resolver::results_type::iterator i = boost::asio::connect(
+ * s, e.begin(), e.end(), my_connect_condition());
* std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode
*/
-template <typename Protocol, typename SocketService,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition>
-Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin,
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin,
Iterator end, ConnectCondition connect_condition);
/// Establishes a socket connection by trying each endpoint in a sequence.
@@ -385,16 +545,14 @@ Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin,
*
* @param connect_condition A function object that is called prior to each
* connection attempt. The signature of the function object must be:
- * @code Iterator connect_condition(
+ * @code bool connect_condition(
* const boost::system::error_code& ec,
- * Iterator next); @endcode
+ * const typename Protocol::endpoint& next); @endcode
* The @c ec parameter contains the result from the most recent connect
* operation. Before the first connection attempt, @c ec is always set to
- * indicate success. The @c next parameter is an iterator pointing to the next
- * endpoint to be tried. The function object should return the next iterator,
- * but is permitted to return a different iterator so that endpoints may be
- * skipped. The implementation guarantees that the function object will never
- * be called with the end iterator.
+ * indicate success. The @c next parameter is the next endpoint to be tried.
+ * The function object should return true if the next endpoint should be tried,
+ * and false if it should be skipped.
*
* @param ec Set to indicate what error occurred, if any. If the sequence is
* empty, set to boost::asio::error::not_found. Otherwise, contains the error
@@ -408,23 +566,23 @@ Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin,
* information about the individual connection attempts:
* @code struct my_connect_condition
* {
- * template <typename Iterator>
- * Iterator operator()(
+ * bool operator()(
* const boost::system::error_code& ec,
- * Iterator next)
+ * const::tcp::endpoint& next)
* {
* if (ec) std::cout << "Error: " << ec.message() << std::endl;
- * std::cout << "Trying: " << next->endpoint() << std::endl;
- * return next;
+ * std::cout << "Trying: " << next << std::endl;
+ * return true;
* }
* }; @endcode
* It would be used with the boost::asio::connect function as follows:
- * @code tcp::resolver r(io_service);
+ * @code tcp::resolver r(io_context);
* tcp::resolver::query q("host", "service");
- * tcp::resolver::iterator i = r.resolve(q), end;
- * tcp::socket s(io_service);
+ * tcp::resolver::results_type e = r.resolve(q);
+ * tcp::socket s(io_context);
* boost::system::error_code ec;
- * i = boost::asio::connect(s, i, end, my_connect_condition(), ec);
+ * tcp::resolver::results_type::iterator i = boost::asio::connect(
+ * s, e.begin(), e.end(), my_connect_condition());
* if (ec)
* {
* // An error occurred.
@@ -434,9 +592,9 @@ Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin,
* std::cout << "Connected to: " << i->endpoint() << std::endl;
* } @endcode
*/
-template <typename Protocol, typename SocketService,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition>
-Iterator connect(basic_socket<Protocol, SocketService>& s,
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition,
boost::system::error_code& ec);
@@ -461,7 +619,7 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
* @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 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
@@ -472,23 +630,19 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
* // error from the last connection attempt.
* const boost::system::error_code& error,
*
- * // On success, an iterator denoting the successfully
- * // connected endpoint. Otherwise, the end iterator.
- * Iterator iterator
+ * // On success, the successfully connected endpoint.
+ * // Otherwise, a default-constructed endpoint.
+ * 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. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
- *
- * @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 boost::asio::ip::tcp::resolver::iterator.
+ * boost::asio::io_context::post().
*
* @par Example
- * @code tcp::resolver r(io_service);
+ * @code tcp::resolver r(io_context);
* tcp::resolver::query q("host", "service");
- * tcp::socket s(io_service);
+ * tcp::socket s(io_context);
*
* // ...
*
@@ -498,11 +652,11 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
*
* void resolve_handler(
* const boost::system::error_code& ec,
- * tcp::resolver::iterator i)
+ * tcp::resolver::results_type results)
* {
* if (!ec)
* {
- * boost::asio::async_connect(s, i, connect_handler);
+ * boost::asio::async_connect(s, results, connect_handler);
* }
* }
*
@@ -510,17 +664,65 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
*
* void connect_handler(
* const boost::system::error_code& ec,
- * tcp::resolver::iterator i)
+ * const tcp::endpoint& endpoint)
* {
* // ...
* } @endcode
*/
-template <typename Protocol, typename SocketService,
- typename Iterator, typename ComposedConnectHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename RangeConnectHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
+ void (boost::system::error_code, typename Protocol::endpoint))
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints,
+ BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type* = 0);
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+/// (Deprecated.) Asynchronously establishes a socket connection by trying each
+/// endpoint in a sequence.
+/**
+ * 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.
+ *
+ * @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:
+ * @code void handler(
+ * // Result of operation. if the sequence is empty, set to
+ * // boost::asio::error::not_found. Otherwise, contains the
+ * // error from the last connection attempt.
+ * const boost::system::error_code& error,
+ *
+ * // On success, an iterator denoting the successfully
+ * // connected endpoint. Otherwise, the end iterator.
+ * Iterator iterator
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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 boost::asio::ip::tcp::resolver::iterator.
+ */
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename Iterator, typename IteratorConnectHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol, SocketService>& s,
- Iterator begin, BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler);
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ Iterator begin, BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Asynchronously establishes a socket connection by trying each endpoint in a
/// sequence.
@@ -553,46 +755,31 @@ async_connect(basic_socket<Protocol, SocketService>& s,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
- * @code tcp::resolver r(io_service);
- * tcp::resolver::query q("host", "service");
- * tcp::socket s(io_service);
- *
- * // ...
- *
- * r.async_resolve(q, resolve_handler);
- *
- * // ...
- *
- * void resolve_handler(
- * const boost::system::error_code& ec,
- * tcp::resolver::iterator i)
- * {
- * if (!ec)
- * {
- * tcp::resolver::iterator end;
- * boost::asio::async_connect(s, i, end, connect_handler);
- * }
- * }
+ * @code std::vector<tcp::endpoint> endpoints = ...;
+ * tcp::socket s(io_context);
+ * boost::asio::async_connect(s,
+ * endpoints.begin(), endpoints.end(),
+ * connect_handler);
*
* // ...
*
* void connect_handler(
* const boost::system::error_code& ec,
- * tcp::resolver::iterator i)
+ * std::vector<tcp::endpoint>::iterator i)
* {
* // ...
* } @endcode
*/
-template <typename Protocol, typename SocketService,
- typename Iterator, typename ComposedConnectHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename Iterator, typename IteratorConnectHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol, SocketService>& s,
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, Iterator end,
- BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler);
+ BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler);
/// Asynchronously establishes a socket connection by trying each endpoint in a
/// sequence.
@@ -605,20 +792,18 @@ async_connect(basic_socket<Protocol, SocketService>& s,
* @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 endpoints A sequence of endpoints.
*
* @param connect_condition A function object that is called prior to each
* connection attempt. The signature of the function object must be:
- * @code Iterator connect_condition(
+ * @code bool connect_condition(
* const boost::system::error_code& ec,
- * Iterator next); @endcode
+ * const typename Protocol::endpoint& next); @endcode
* The @c ec parameter contains the result from the most recent connect
* operation. Before the first connection attempt, @c ec is always set to
- * indicate success. The @c next parameter is an iterator pointing to the next
- * endpoint to be tried. The function object should return the next iterator,
- * but is permitted to return a different iterator so that endpoints may be
- * skipped. The implementation guarantees that the function object will never
- * be called with the end iterator.
+ * indicate success. The @c next parameter is the next endpoint to be tried.
+ * 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
@@ -636,31 +821,26 @@ async_connect(basic_socket<Protocol, SocketService>& s,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
- *
- * @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 boost::asio::ip::tcp::resolver::iterator.
+ * boost::asio::io_context::post().
*
* @par Example
* The following connect condition function object can be used to output
* information about the individual connection attempts:
* @code struct my_connect_condition
* {
- * template <typename Iterator>
- * Iterator operator()(
+ * bool operator()(
* const boost::system::error_code& ec,
- * Iterator next)
+ * const::tcp::endpoint& next)
* {
* if (ec) std::cout << "Error: " << ec.message() << std::endl;
- * std::cout << "Trying: " << next->endpoint() << std::endl;
- * return next;
+ * std::cout << "Trying: " << next << std::endl;
+ * return true;
* }
* }; @endcode
* It would be used with the boost::asio::connect function as follows:
- * @code tcp::resolver r(io_service);
+ * @code tcp::resolver r(io_context);
* tcp::resolver::query q("host", "service");
- * tcp::socket s(io_service);
+ * tcp::socket s(io_context);
*
* // ...
*
@@ -670,11 +850,11 @@ async_connect(basic_socket<Protocol, SocketService>& s,
*
* void resolve_handler(
* const boost::system::error_code& ec,
- * tcp::resolver::iterator i)
+ * tcp::resolver::results_type results)
* {
* if (!ec)
* {
- * boost::asio::async_connect(s, i,
+ * boost::asio::async_connect(s, results,
* my_connect_condition(),
* connect_handler);
* }
@@ -684,7 +864,7 @@ async_connect(basic_socket<Protocol, SocketService>& s,
*
* void connect_handler(
* const boost::system::error_code& ec,
- * tcp::resolver::iterator i)
+ * const tcp::endpoint& endpoint)
* {
* if (ec)
* {
@@ -692,17 +872,76 @@ async_connect(basic_socket<Protocol, SocketService>& s,
* }
* else
* {
- * std::cout << "Connected to: " << i->endpoint() << std::endl;
+ * std::cout << "Connected to: " << endpoint << std::endl;
* }
* } @endcode
*/
-template <typename Protocol, typename SocketService, typename Iterator,
- typename ConnectCondition, typename ComposedConnectHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence,
+ typename ConnectCondition, typename RangeConnectHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
+ void (boost::system::error_code, typename Protocol::endpoint))
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints, ConnectCondition connect_condition,
+ BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type* = 0);
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+/// (Deprecated.) Asynchronously establishes a socket connection by trying each
+/// endpoint in a sequence.
+/**
+ * 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.
+ *
+ * @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 connect_condition A function object that is called prior to each
+ * connection attempt. The signature of the function object must be:
+ * @code bool connect_condition(
+ * const boost::system::error_code& ec,
+ * const typename Protocol::endpoint& next); @endcode
+ * The @c ec parameter contains the result from the most recent connect
+ * operation. Before the first connection attempt, @c ec is always set to
+ * indicate success. The @c next parameter is the next endpoint to be tried.
+ * 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:
+ * @code void handler(
+ * // Result of operation. if the sequence is empty, set to
+ * // boost::asio::error::not_found. Otherwise, contains the
+ * // error from the last connection attempt.
+ * const boost::system::error_code& error,
+ *
+ * // On success, an iterator denoting the successfully
+ * // connected endpoint. Otherwise, the end iterator.
+ * Iterator iterator
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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 boost::asio::ip::tcp::resolver::iterator.
+ */
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin,
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin,
ConnectCondition connect_condition,
- BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler);
+ BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Asynchronously establishes a socket connection by trying each endpoint in a
/// sequence.
@@ -721,16 +960,14 @@ async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin,
*
* @param connect_condition A function object that is called prior to each
* connection attempt. The signature of the function object must be:
- * @code Iterator connect_condition(
+ * @code bool connect_condition(
* const boost::system::error_code& ec,
- * Iterator next); @endcode
+ * const typename Protocol::endpoint& next); @endcode
* The @c ec parameter contains the result from the most recent connect
* operation. Before the first connection attempt, @c ec is always set to
- * indicate success. The @c next parameter is an iterator pointing to the next
- * endpoint to be tried. The function object should return the next iterator,
- * but is permitted to return a different iterator so that endpoints may be
- * skipped. The implementation guarantees that the function object will never
- * be called with the end iterator.
+ * indicate success. The @c next parameter is the next endpoint to be tried.
+ * 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
@@ -748,27 +985,26 @@ async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* The following connect condition function object can be used to output
* information about the individual connection attempts:
* @code struct my_connect_condition
* {
- * template <typename Iterator>
- * Iterator operator()(
+ * bool operator()(
* const boost::system::error_code& ec,
- * Iterator next)
+ * const::tcp::endpoint& next)
* {
* if (ec) std::cout << "Error: " << ec.message() << std::endl;
- * std::cout << "Trying: " << next->endpoint() << std::endl;
- * return next;
+ * std::cout << "Trying: " << next << std::endl;
+ * return true;
* }
* }; @endcode
* It would be used with the boost::asio::connect function as follows:
- * @code tcp::resolver r(io_service);
+ * @code tcp::resolver r(io_context);
* tcp::resolver::query q("host", "service");
- * tcp::socket s(io_service);
+ * tcp::socket s(io_context);
*
* // ...
*
@@ -805,13 +1041,13 @@ async_connect(basic_socket<Protocol, SocketService>& s, Iterator begin,
* }
* } @endcode
*/
-template <typename Protocol, typename SocketService, typename Iterator,
- typename ConnectCondition, typename ComposedConnectHandler>
-BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol, SocketService>& s,
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition,
- BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler);
+ BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler);
/*@}*/
diff --git a/boost/asio/coroutine.hpp b/boost/asio/coroutine.hpp
index c4763f8524..7ac354de82 100644
--- a/boost/asio/coroutine.hpp
+++ b/boost/asio/coroutine.hpp
@@ -206,7 +206,7 @@ class coroutine_ref;
* {
* do
* {
- * socket_.reset(new tcp::socket(io_service_));
+ * socket_.reset(new tcp::socket(io_context_));
* yield acceptor->async_accept(*socket_, *this);
* fork server(*this)();
* } while (is_parent());
@@ -228,7 +228,7 @@ class coroutine_ref;
* Note that @c fork doesn't do the actual forking by itself. It is the
* application's responsibility to create a clone of the coroutine and call it.
* The clone can be called immediately, as above, or scheduled for delayed
- * execution using something like io_service::post().
+ * execution using something like io_context::post().
*
* @par Alternate macro names
*
@@ -291,7 +291,7 @@ private:
bail_out_of_coroutine: \
break; \
} \
- else case 0:
+ else /* fall-through */ case 0:
#define BOOST_ASIO_CORO_YIELD_IMPL(n) \
for (_coro_value = (n);;) \
@@ -303,12 +303,12 @@ private:
else \
switch (_coro_value ? 0 : 1) \
for (;;) \
- case -1: if (_coro_value) \
+ /* fall-through */ case -1: if (_coro_value) \
goto terminate_coroutine; \
else for (;;) \
- case 1: if (_coro_value) \
+ /* fall-through */ case 1: if (_coro_value) \
goto bail_out_of_coroutine; \
- else case 0:
+ else /* fall-through */ case 0:
#define BOOST_ASIO_CORO_FORK_IMPL(n) \
for (_coro_value = -(n);; _coro_value = (n)) \
diff --git a/boost/asio/datagram_socket_service.hpp b/boost/asio/datagram_socket_service.hpp
index 95f179acfd..35bc2f5feb 100644
--- a/boost/asio/datagram_socket_service.hpp
+++ b/boost/asio/datagram_socket_service.hpp
@@ -16,11 +16,14 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <cstddef>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
# include <boost/asio/detail/null_socket_service.hpp>
@@ -39,7 +42,7 @@ namespace asio {
template <typename Protocol>
class datagram_socket_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<datagram_socket_service<Protocol> >
#endif
@@ -47,7 +50,7 @@ class datagram_socket_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
/// The protocol type.
@@ -74,13 +77,6 @@ public:
typedef typename service_impl_type::implementation_type implementation_type;
#endif
- /// (Deprecated: Use native_handle_type.) The native socket type.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined native_type;
-#else
- typedef typename service_impl_type::native_handle_type native_type;
-#endif
-
/// The native socket type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
@@ -88,11 +84,11 @@ public:
typedef typename service_impl_type::native_handle_type native_handle_type;
#endif
- /// Construct a new datagram socket service for the specified io_service.
- explicit datagram_socket_service(boost::asio::io_service& io_service)
+ /// Construct a new datagram socket service for the specified io_context.
+ explicit datagram_socket_service(boost::asio::io_context& io_context)
: boost::asio::detail::service_base<
- datagram_socket_service<Protocol> >(io_service),
- service_impl_(io_service)
+ datagram_socket_service<Protocol> >(io_context),
+ service_impl_(io_context)
{
}
@@ -143,22 +139,23 @@ public:
}
// Open a new datagram socket implementation.
- boost::system::error_code open(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl,
const protocol_type& protocol, boost::system::error_code& ec)
{
if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_DGRAM))
service_impl_.open(impl, protocol, ec);
else
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Assign an existing native socket to a datagram socket.
- boost::system::error_code assign(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl,
const protocol_type& protocol, const native_handle_type& native_socket,
boost::system::error_code& ec)
{
- return service_impl_.assign(impl, protocol, native_socket, ec);
+ service_impl_.assign(impl, protocol, native_socket, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is open.
@@ -168,16 +165,18 @@ public:
}
/// Close a datagram socket implementation.
- boost::system::error_code close(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.close(impl, ec);
+ service_impl_.close(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
- /// (Deprecated: Use native_handle().) Get the native socket implementation.
- native_type native(implementation_type& impl)
+ /// Release ownership of the underlying socket.
+ native_handle_type release(implementation_type& impl,
+ boost::system::error_code& ec)
{
- return service_impl_.native_handle(impl);
+ return service_impl_.release(impl, ec);
}
/// Get the native socket implementation.
@@ -187,10 +186,11 @@ public:
}
/// Cancel all asynchronous operations associated with the socket.
- boost::system::error_code cancel(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.cancel(impl, ec);
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is at the out-of-band data mark.
@@ -208,17 +208,19 @@ public:
}
// Bind the datagram socket to the specified local endpoint.
- boost::system::error_code bind(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID bind(implementation_type& impl,
const endpoint_type& endpoint, boost::system::error_code& ec)
{
- return service_impl_.bind(impl, endpoint, ec);
+ service_impl_.bind(impl, endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Connect the datagram socket to the specified endpoint.
- boost::system::error_code connect(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID connect(implementation_type& impl,
const endpoint_type& peer_endpoint, boost::system::error_code& ec)
{
- return service_impl_.connect(impl, peer_endpoint, ec);
+ service_impl_.connect(impl, peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Start an asynchronous connect.
@@ -229,37 +231,39 @@ public:
const endpoint_type& peer_endpoint,
BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
{
- detail::async_result_init<
- ConnectHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
+ async_completion<ConnectHandler,
+ void (boost::system::error_code)> init(handler);
- service_impl_.async_connect(impl, peer_endpoint, init.handler);
+ service_impl_.async_connect(impl, peer_endpoint, init.completion_handler);
return init.result.get();
}
/// Set a socket option.
template <typename SettableSocketOption>
- boost::system::error_code set_option(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl,
const SettableSocketOption& option, boost::system::error_code& ec)
{
- return service_impl_.set_option(impl, option, ec);
+ service_impl_.set_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get a socket option.
template <typename GettableSocketOption>
- boost::system::error_code get_option(const implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl,
GettableSocketOption& option, boost::system::error_code& ec) const
{
- return service_impl_.get_option(impl, option, ec);
+ service_impl_.get_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform an IO control command on the socket.
template <typename IoControlCommand>
- boost::system::error_code io_control(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl,
IoControlCommand& command, boost::system::error_code& ec)
{
- return service_impl_.io_control(impl, command, ec);
+ service_impl_.io_control(impl, command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the socket.
@@ -269,10 +273,11 @@ public:
}
/// Sets the non-blocking mode of the socket.
- boost::system::error_code non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.non_blocking(impl, mode, ec);
+ service_impl_.non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the native socket implementation.
@@ -282,10 +287,11 @@ public:
}
/// Sets the non-blocking mode of the native socket implementation.
- boost::system::error_code native_non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.native_non_blocking(impl, mode, ec);
+ service_impl_.native_non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the local endpoint.
@@ -303,10 +309,36 @@ public:
}
/// Disable sends or receives on the socket.
- boost::system::error_code shutdown(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID shutdown(implementation_type& impl,
socket_base::shutdown_type what, boost::system::error_code& ec)
{
- return service_impl_.shutdown(impl, what, ec);
+ service_impl_.shutdown(impl, what, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
+ {
+ service_impl_.wait(impl, w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the socket to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(implementation_type& impl, socket_base::wait_type w,
+ BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ service_impl_.async_wait(impl, w, init.completion_handler);
+
+ return init.result.get();
}
/// Send the given data to the peer.
@@ -326,11 +358,10 @@ public:
socket_base::message_flags flags,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_send(impl, buffers, flags, init.handler);
+ service_impl_.async_send(impl, buffers, flags, init.completion_handler);
return init.result.get();
}
@@ -353,12 +384,11 @@ public:
socket_base::message_flags flags,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
service_impl_.async_send_to(impl, buffers,
- destination, flags, init.handler);
+ destination, flags, init.completion_handler);
return init.result.get();
}
@@ -381,11 +411,10 @@ public:
socket_base::message_flags flags,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_receive(impl, buffers, flags, init.handler);
+ service_impl_.async_receive(impl, buffers, flags, init.completion_handler);
return init.result.get();
}
@@ -409,21 +438,20 @@ public:
socket_base::message_flags flags,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
service_impl_.async_receive_from(impl, buffers,
- sender_endpoint, flags, init.handler);
+ sender_endpoint, flags, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -435,4 +463,6 @@ private:
#include <boost/asio/detail/pop_options.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_DATAGRAM_SOCKET_SERVICE_HPP
diff --git a/boost/asio/deadline_timer_service.hpp b/boost/asio/deadline_timer_service.hpp
index 26dcb42e4c..d109815188 100644
--- a/boost/asio/deadline_timer_service.hpp
+++ b/boost/asio/deadline_timer_service.hpp
@@ -17,15 +17,16 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
|| defined(GENERATING_DOCUMENTATION)
#include <cstddef>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/deadline_timer_service.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/time_traits.hpp>
-#include <boost/asio/detail/timer_queue_ptime.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -37,7 +38,7 @@ template <typename TimeType,
typename TimeTraits = boost::asio::time_traits<TimeType> >
class deadline_timer_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<
deadline_timer_service<TimeType, TimeTraits> >
@@ -46,7 +47,7 @@ class deadline_timer_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
/// The time traits type.
@@ -70,11 +71,11 @@ public:
typedef typename service_impl_type::implementation_type implementation_type;
#endif
- /// Construct a new timer service for the specified io_service.
- explicit deadline_timer_service(boost::asio::io_service& io_service)
+ /// Construct a new timer service for the specified io_context.
+ explicit deadline_timer_service(boost::asio::io_context& io_context)
: boost::asio::detail::service_base<
- deadline_timer_service<TimeType, TimeTraits> >(io_service),
- service_impl_(io_service)
+ deadline_timer_service<TimeType, TimeTraits> >(io_context),
+ service_impl_(io_context)
{
}
@@ -106,7 +107,7 @@ public:
/// Get the expiry time for the timer as an absolute time.
time_type expires_at(const implementation_type& impl) const
{
- return service_impl_.expires_at(impl);
+ return service_impl_.expiry(impl);
}
/// Set the expiry time for the timer as an absolute time.
@@ -119,14 +120,14 @@ public:
/// Get the expiry time for the timer relative to now.
duration_type expires_from_now(const implementation_type& impl) const
{
- return service_impl_.expires_from_now(impl);
+ return TimeTraits::subtract(service_impl_.expiry(impl), TimeTraits::now());
}
/// Set the expiry time for the timer relative to now.
std::size_t expires_from_now(implementation_type& impl,
const duration_type& expiry_time, boost::system::error_code& ec)
{
- return service_impl_.expires_from_now(impl, expiry_time, ec);
+ return service_impl_.expires_after(impl, expiry_time, ec);
}
// Perform a blocking wait on the timer.
@@ -142,20 +143,19 @@ public:
async_wait(implementation_type& impl,
BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
{
- detail::async_result_init<
- WaitHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
- service_impl_.async_wait(impl, init.handler);
+ service_impl_.async_wait(impl, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -170,4 +170,6 @@ private:
#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_DEADLINE_TIMER_SERVICE_HPP
diff --git a/boost/asio/defer.hpp b/boost/asio/defer.hpp
new file mode 100644
index 0000000000..966bfb4e14
--- /dev/null
+++ b/boost/asio/defer.hpp
@@ -0,0 +1,109 @@
+//
+// defer.hpp
+// ~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DEFER_HPP
+#define BOOST_ASIO_DEFER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/is_executor.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Submits a completion token or function object for execution.
+/**
+ * This function submits an object for execution using the object's associated
+ * executor. The function object is queued for execution, and is never called
+ * from the current thread prior to returning from <tt>defer()</tt>.
+ *
+ * This function has the following effects:
+ *
+ * @li Constructs a function object handler of type @c Handler, initialized
+ * with <tt>handler(forward<CompletionToken>(token))</tt>.
+ *
+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,
+ * initializing the object as <tt>result(handler)</tt>.
+ *
+ * @li Obtains the handler's associated executor object @c ex by performing
+ * <tt>get_associated_executor(handler)</tt>.
+ *
+ * @li Obtains the handler's associated allocator object @c alloc by performing
+ * <tt>get_associated_allocator(handler)</tt>.
+ *
+ * @li Performs <tt>ex.defer(std::move(handler), alloc)</tt>.
+ *
+ * @li Returns <tt>result.get()</tt>.
+ */
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
+ BOOST_ASIO_MOVE_ARG(CompletionToken) token);
+
+/// Submits a completion token or function object for execution.
+/**
+ * This function submits an object for execution using the specified executor.
+ * The function object is queued for execution, and is never called from the
+ * current thread prior to returning from <tt>defer()</tt>.
+ *
+ * This function has the following effects:
+ *
+ * @li Constructs a function object handler of type @c Handler, initialized
+ * with <tt>handler(forward<CompletionToken>(token))</tt>.
+ *
+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,
+ * initializing the object as <tt>result(handler)</tt>.
+ *
+ * @li Obtains the handler's associated executor object @c ex1 by performing
+ * <tt>get_associated_executor(handler)</tt>.
+ *
+ * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.
+ *
+ * @li Obtains the handler's associated allocator object @c alloc by performing
+ * <tt>get_associated_allocator(handler)</tt>.
+ *
+ * @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 Performs <tt>Executor(ex).defer(std::move(f), alloc)</tt>.
+ *
+ * @li Returns <tt>result.get()</tt>.
+ */
+template <typename Executor, typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
+ const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_executor<Executor>::value>::type* = 0);
+
+/// Submits a completion token or function object for execution.
+/**
+ * @returns <tt>defer(ctx.get_executor(), forward<CompletionToken>(token))</tt>.
+ */
+template <typename ExecutionContext, typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
+ ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_convertible<
+ ExecutionContext&, execution_context&>::value>::type* = 0);
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/impl/defer.hpp>
+
+#endif // BOOST_ASIO_DEFER_HPP
diff --git a/boost/asio/detail/addressof.hpp b/boost/asio/detail/addressof.hpp
deleted file mode 100644
index cc1099764d..0000000000
--- a/boost/asio/detail/addressof.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// detail/addressof.hpp
-// ~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_DETAIL_ADDRESSOF_HPP
-#define BOOST_ASIO_DETAIL_ADDRESSOF_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-
-#if defined(BOOST_ASIO_HAS_STD_ADDRESSOF)
-# include <memory>
-#else // defined(BOOST_ASIO_HAS_STD_ADDRESSOF)
-# include <boost/utility/addressof.hpp>
-#endif // defined(BOOST_ASIO_HAS_STD_ADDRESSOF)
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-#if defined(BOOST_ASIO_HAS_STD_ADDRESSOF)
-using std::addressof;
-#else // defined(BOOST_ASIO_HAS_STD_ADDRESSOF)
-using boost::addressof;
-#endif // defined(BOOST_ASIO_HAS_STD_ADDRESSOF)
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#endif // BOOST_ASIO_DETAIL_ADDRESSOF_HPP
diff --git a/boost/asio/detail/bind_handler.hpp b/boost/asio/detail/bind_handler.hpp
index 0f3672edab..b55c2acd5e 100644
--- a/boost/asio/detail/bind_handler.hpp
+++ b/boost/asio/detail/bind_handler.hpp
@@ -16,9 +16,12 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -30,8 +33,9 @@ template <typename Handler, typename Arg1>
class binder1
{
public:
- binder1(const Handler& handler, const Arg1& arg1)
- : handler_(handler),
+ template <typename T>
+ binder1(int, BOOST_ASIO_MOVE_ARG(T) handler, const Arg1& arg1)
+ : handler_(BOOST_ASIO_MOVE_CAST(T)(handler)),
arg1_(arg1)
{
}
@@ -42,6 +46,20 @@ public:
{
}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ binder1(const binder1& other)
+ : handler_(other.handler_),
+ arg1_(other.arg1_)
+ {
+ }
+
+ binder1(binder1&& other)
+ : handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
+ arg1_(BOOST_ASIO_MOVE_CAST(Arg1)(other.arg1_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
void operator()()
{
handler_(static_cast<const Arg1&>(arg1_));
@@ -98,18 +116,21 @@ inline void asio_handler_invoke(const Function& function,
}
template <typename Handler, typename Arg1>
-inline binder1<Handler, Arg1> bind_handler(Handler handler,
- const Arg1& arg1)
+inline binder1<typename decay<Handler>::type, Arg1> bind_handler(
+ BOOST_ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1)
{
- return binder1<Handler, Arg1>(handler, arg1);
+ return binder1<typename decay<Handler>::type, Arg1>(0,
+ BOOST_ASIO_MOVE_CAST(Handler)(handler), arg1);
}
template <typename Handler, typename Arg1, typename Arg2>
class binder2
{
public:
- binder2(const Handler& handler, const Arg1& arg1, const Arg2& arg2)
- : handler_(handler),
+ template <typename T>
+ binder2(int, BOOST_ASIO_MOVE_ARG(T) handler,
+ const Arg1& arg1, const Arg2& arg2)
+ : handler_(BOOST_ASIO_MOVE_CAST(T)(handler)),
arg1_(arg1),
arg2_(arg2)
{
@@ -122,6 +143,22 @@ public:
{
}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ binder2(const binder2& other)
+ : handler_(other.handler_),
+ arg1_(other.arg1_),
+ arg2_(other.arg2_)
+ {
+ }
+
+ binder2(binder2&& other)
+ : handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
+ arg1_(BOOST_ASIO_MOVE_CAST(Arg1)(other.arg1_)),
+ arg2_(BOOST_ASIO_MOVE_CAST(Arg2)(other.arg2_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
void operator()()
{
handler_(static_cast<const Arg1&>(arg1_),
@@ -180,27 +217,29 @@ inline void asio_handler_invoke(const Function& function,
}
template <typename Handler, typename Arg1, typename Arg2>
-inline binder2<Handler, Arg1, Arg2> bind_handler(Handler handler,
- const Arg1& arg1, const Arg2& arg2)
+inline binder2<typename decay<Handler>::type, Arg1, Arg2> bind_handler(
+ BOOST_ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1, const Arg2& arg2)
{
- return binder2<Handler, Arg1, Arg2>(handler, arg1, arg2);
+ return binder2<typename decay<Handler>::type, Arg1, Arg2>(0,
+ BOOST_ASIO_MOVE_CAST(Handler)(handler), arg1, arg2);
}
template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
class binder3
{
public:
- binder3(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
- const Arg3& arg3)
- : handler_(handler),
+ template <typename T>
+ binder3(int, BOOST_ASIO_MOVE_ARG(T) handler, const Arg1& arg1,
+ const Arg2& arg2, const Arg3& arg3)
+ : handler_(BOOST_ASIO_MOVE_CAST(T)(handler)),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3)
{
}
- binder3(Handler& handler, const Arg1& arg1, const Arg2& arg2,
- const Arg3& arg3)
+ binder3(Handler& handler, const Arg1& arg1,
+ const Arg2& arg2, const Arg3& arg3)
: handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
arg1_(arg1),
arg2_(arg2),
@@ -208,11 +247,28 @@ public:
{
}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ binder3(const binder3& other)
+ : handler_(other.handler_),
+ arg1_(other.arg1_),
+ arg2_(other.arg2_),
+ arg3_(other.arg3_)
+ {
+ }
+
+ binder3(binder3&& other)
+ : handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
+ arg1_(BOOST_ASIO_MOVE_CAST(Arg1)(other.arg1_)),
+ arg2_(BOOST_ASIO_MOVE_CAST(Arg2)(other.arg2_)),
+ arg3_(BOOST_ASIO_MOVE_CAST(Arg3)(other.arg3_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
void operator()()
{
handler_(static_cast<const Arg1&>(arg1_),
- static_cast<const Arg2&>(arg2_),
- static_cast<const Arg3&>(arg3_));
+ static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_));
}
void operator()() const
@@ -251,8 +307,8 @@ inline bool asio_handler_is_continuation(
this_handler->handler_);
}
-template <typename Function, typename Handler, typename Arg1, typename Arg2,
- typename Arg3>
+template <typename Function, typename Handler,
+ typename Arg1, typename Arg2, typename Arg3>
inline void asio_handler_invoke(Function& function,
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
{
@@ -260,8 +316,8 @@ inline void asio_handler_invoke(Function& function,
function, this_handler->handler_);
}
-template <typename Function, typename Handler, typename Arg1, typename Arg2,
- typename Arg3>
+template <typename Function, typename Handler,
+ typename Arg1, typename Arg2, typename Arg3>
inline void asio_handler_invoke(const Function& function,
binder3<Handler, Arg1, Arg2, Arg3>* this_handler)
{
@@ -270,20 +326,23 @@ inline void asio_handler_invoke(const Function& function,
}
template <typename Handler, typename Arg1, typename Arg2, typename Arg3>
-inline binder3<Handler, Arg1, Arg2, Arg3> bind_handler(Handler handler,
- const Arg1& arg1, const Arg2& arg2, const Arg3& arg3)
+inline binder3<typename decay<Handler>::type, Arg1, Arg2, Arg3> bind_handler(
+ BOOST_ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1, const Arg2& arg2,
+ const Arg3& arg3)
{
- return binder3<Handler, Arg1, Arg2, Arg3>(handler, arg1, arg2, arg3);
+ return binder3<typename decay<Handler>::type, Arg1, Arg2, Arg3>(0,
+ BOOST_ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3);
}
-template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4>
+template <typename Handler, typename Arg1,
+ typename Arg2, typename Arg3, typename Arg4>
class binder4
{
public:
- binder4(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
- const Arg3& arg3, const Arg4& arg4)
- : handler_(handler),
+ template <typename T>
+ binder4(int, BOOST_ASIO_MOVE_ARG(T) handler, const Arg1& arg1,
+ const Arg2& arg2, const Arg3& arg3, const Arg4& arg4)
+ : handler_(BOOST_ASIO_MOVE_CAST(T)(handler)),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3),
@@ -291,8 +350,8 @@ public:
{
}
- binder4(Handler& handler, const Arg1& arg1, const Arg2& arg2,
- const Arg3& arg3, const Arg4& arg4)
+ binder4(Handler& handler, const Arg1& arg1,
+ const Arg2& arg2, const Arg3& arg3, const Arg4& arg4)
: handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
arg1_(arg1),
arg2_(arg2),
@@ -301,11 +360,30 @@ public:
{
}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ binder4(const binder4& other)
+ : handler_(other.handler_),
+ arg1_(other.arg1_),
+ arg2_(other.arg2_),
+ arg3_(other.arg3_),
+ arg4_(other.arg4_)
+ {
+ }
+
+ binder4(binder4&& other)
+ : handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
+ arg1_(BOOST_ASIO_MOVE_CAST(Arg1)(other.arg1_)),
+ arg2_(BOOST_ASIO_MOVE_CAST(Arg2)(other.arg2_)),
+ arg3_(BOOST_ASIO_MOVE_CAST(Arg3)(other.arg3_)),
+ arg4_(BOOST_ASIO_MOVE_CAST(Arg4)(other.arg4_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
void operator()()
{
handler_(static_cast<const Arg1&>(arg1_),
- static_cast<const Arg2&>(arg2_),
- static_cast<const Arg3&>(arg3_),
+ static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),
static_cast<const Arg4&>(arg4_));
}
@@ -322,8 +400,8 @@ public:
Arg4 arg4_;
};
-template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4>
+template <typename Handler, typename Arg1,
+ typename Arg2, typename Arg3, typename Arg4>
inline void* asio_handler_allocate(std::size_t size,
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
@@ -331,8 +409,8 @@ inline void* asio_handler_allocate(std::size_t size,
size, this_handler->handler_);
}
-template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4>
+template <typename Handler, typename Arg1,
+ typename Arg2, typename Arg3, typename Arg4>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
@@ -340,8 +418,8 @@ inline void asio_handler_deallocate(void* pointer, std::size_t size,
pointer, size, this_handler->handler_);
}
-template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4>
+template <typename Handler, typename Arg1,
+ typename Arg2, typename Arg3, typename Arg4>
inline bool asio_handler_is_continuation(
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
@@ -349,8 +427,8 @@ inline bool asio_handler_is_continuation(
this_handler->handler_);
}
-template <typename Function, typename Handler, typename Arg1, typename Arg2,
- typename Arg3, typename Arg4>
+template <typename Function, typename Handler, typename Arg1,
+ typename Arg2, typename Arg3, typename Arg4>
inline void asio_handler_invoke(Function& function,
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
@@ -358,8 +436,8 @@ inline void asio_handler_invoke(Function& function,
function, this_handler->handler_);
}
-template <typename Function, typename Handler, typename Arg1, typename Arg2,
- typename Arg3, typename Arg4>
+template <typename Function, typename Handler, typename Arg1,
+ typename Arg2, typename Arg3, typename Arg4>
inline void asio_handler_invoke(const Function& function,
binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)
{
@@ -367,24 +445,25 @@ inline void asio_handler_invoke(const Function& function,
function, this_handler->handler_);
}
-template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4>
-inline binder4<Handler, Arg1, Arg2, Arg3, Arg4> bind_handler(
- Handler handler, const Arg1& arg1, const Arg2& arg2,
- const Arg3& arg3, const Arg4& arg4)
+template <typename Handler, typename Arg1,
+ typename Arg2, typename Arg3, typename Arg4>
+inline binder4<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4>
+bind_handler(BOOST_ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1,
+ const Arg2& arg2, const Arg3& arg3, const Arg4& arg4)
{
- return binder4<Handler, Arg1, Arg2, Arg3, Arg4>(handler, arg1, arg2, arg3,
- arg4);
+ return binder4<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4>(0,
+ BOOST_ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3, arg4);
}
-template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4, typename Arg5>
+template <typename Handler, typename Arg1, typename Arg2,
+ typename Arg3, typename Arg4, typename Arg5>
class binder5
{
public:
- binder5(const Handler& handler, const Arg1& arg1, const Arg2& arg2,
- const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
- : handler_(handler),
+ template <typename T>
+ binder5(int, BOOST_ASIO_MOVE_ARG(T) handler, const Arg1& arg1,
+ const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
+ : handler_(BOOST_ASIO_MOVE_CAST(T)(handler)),
arg1_(arg1),
arg2_(arg2),
arg3_(arg3),
@@ -404,13 +483,33 @@ public:
{
}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ binder5(const binder5& other)
+ : handler_(other.handler_),
+ arg1_(other.arg1_),
+ arg2_(other.arg2_),
+ arg3_(other.arg3_),
+ arg4_(other.arg4_),
+ arg5_(other.arg5_)
+ {
+ }
+
+ binder5(binder5&& other)
+ : handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
+ arg1_(BOOST_ASIO_MOVE_CAST(Arg1)(other.arg1_)),
+ arg2_(BOOST_ASIO_MOVE_CAST(Arg2)(other.arg2_)),
+ arg3_(BOOST_ASIO_MOVE_CAST(Arg3)(other.arg3_)),
+ arg4_(BOOST_ASIO_MOVE_CAST(Arg4)(other.arg4_)),
+ arg5_(BOOST_ASIO_MOVE_CAST(Arg5)(other.arg5_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
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_));
+ static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),
+ static_cast<const Arg4&>(arg4_), static_cast<const Arg5&>(arg5_));
}
void operator()() const
@@ -427,8 +526,8 @@ public:
Arg5 arg5_;
};
-template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4, typename Arg5>
+template <typename Handler, typename Arg1, typename Arg2,
+ typename Arg3, typename Arg4, typename Arg5>
inline void* asio_handler_allocate(std::size_t size,
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
@@ -436,8 +535,8 @@ inline void* asio_handler_allocate(std::size_t size,
size, this_handler->handler_);
}
-template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4, typename Arg5>
+template <typename Handler, typename Arg1, typename Arg2,
+ typename Arg3, typename Arg4, typename Arg5>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
@@ -445,8 +544,8 @@ inline void asio_handler_deallocate(void* pointer, std::size_t size,
pointer, size, this_handler->handler_);
}
-template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4, typename Arg5>
+template <typename Handler, typename Arg1, typename Arg2,
+ typename Arg3, typename Arg4, typename Arg5>
inline bool asio_handler_is_continuation(
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
@@ -454,8 +553,8 @@ inline bool asio_handler_is_continuation(
this_handler->handler_);
}
-template <typename Function, typename Handler, typename Arg1, typename Arg2,
- typename Arg3, typename Arg4, typename Arg5>
+template <typename Function, typename Handler, typename Arg1,
+ typename Arg2, typename Arg3, typename Arg4, typename Arg5>
inline void asio_handler_invoke(Function& function,
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
@@ -463,8 +562,8 @@ inline void asio_handler_invoke(Function& function,
function, this_handler->handler_);
}
-template <typename Function, typename Handler, typename Arg1, typename Arg2,
- typename Arg3, typename Arg4, typename Arg5>
+template <typename Function, typename Handler, typename Arg1,
+ typename Arg2, typename Arg3, typename Arg4, typename Arg5>
inline void asio_handler_invoke(const Function& function,
binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)
{
@@ -472,17 +571,245 @@ inline void asio_handler_invoke(const Function& function,
function, this_handler->handler_);
}
-template <typename Handler, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4, typename Arg5>
-inline binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5> bind_handler(
- Handler handler, const Arg1& arg1, const Arg2& arg2,
- const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
+template <typename Handler, typename Arg1, typename Arg2,
+ typename Arg3, typename Arg4, typename Arg5>
+inline binder5<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4, Arg5>
+bind_handler(BOOST_ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1,
+ const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)
+{
+ return binder5<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4, Arg5>(0,
+ BOOST_ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3, arg4, arg5);
+}
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+
+template <typename Handler, typename Arg1>
+class move_binder1
+{
+public:
+ move_binder1(int, BOOST_ASIO_MOVE_ARG(Handler) handler,
+ BOOST_ASIO_MOVE_ARG(Arg1) arg1)
+ : handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ arg1_(BOOST_ASIO_MOVE_CAST(Arg1)(arg1))
+ {
+ }
+
+ move_binder1(move_binder1&& other)
+ : handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
+ arg1_(BOOST_ASIO_MOVE_CAST(Arg1)(other.arg1_))
+ {
+ }
+
+ void operator()()
+ {
+ handler_(BOOST_ASIO_MOVE_CAST(Arg1)(arg1_));
+ }
+
+//private:
+ Handler handler_;
+ Arg1 arg1_;
+};
+
+template <typename Handler, typename Arg1>
+inline void* asio_handler_allocate(std::size_t size,
+ move_binder1<Handler, Arg1>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ move_binder1<Handler, Arg1>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1>
+inline bool asio_handler_is_continuation(
+ move_binder1<Handler, Arg1>* this_handler)
+{
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+}
+
+template <typename Function, typename Handler, typename Arg1>
+inline void asio_handler_invoke(BOOST_ASIO_MOVE_ARG(Function) function,
+ move_binder1<Handler, Arg1>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ BOOST_ASIO_MOVE_CAST(Function)(function), this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+class move_binder2
+{
+public:
+ move_binder2(int, BOOST_ASIO_MOVE_ARG(Handler) handler,
+ const Arg1& arg1, BOOST_ASIO_MOVE_ARG(Arg2) arg2)
+ : handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ arg1_(arg1),
+ arg2_(BOOST_ASIO_MOVE_CAST(Arg2)(arg2))
+ {
+ }
+
+ move_binder2(move_binder2&& other)
+ : handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_)),
+ arg1_(BOOST_ASIO_MOVE_CAST(Arg1)(other.arg1_)),
+ arg2_(BOOST_ASIO_MOVE_CAST(Arg2)(other.arg2_))
+ {
+ }
+
+ void operator()()
+ {
+ handler_(static_cast<const Arg1&>(arg1_),
+ BOOST_ASIO_MOVE_CAST(Arg2)(arg2_));
+ }
+
+//private:
+ Handler handler_;
+ Arg1 arg1_;
+ Arg2 arg2_;
+};
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline void* asio_handler_allocate(std::size_t size,
+ move_binder2<Handler, Arg1, Arg2>* this_handler)
+{
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ move_binder2<Handler, Arg1, Arg2>* this_handler)
+{
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+}
+
+template <typename Handler, typename Arg1, typename Arg2>
+inline bool asio_handler_is_continuation(
+ move_binder2<Handler, Arg1, Arg2>* this_handler)
{
- return binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>(handler, arg1, arg2,
- arg3, arg4, arg5);
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
}
+template <typename Function, typename Handler, typename Arg1, typename Arg2>
+inline void asio_handler_invoke(BOOST_ASIO_MOVE_ARG(Function) function,
+ move_binder2<Handler, Arg1, Arg2>* this_handler)
+{
+ boost_asio_handler_invoke_helpers::invoke(
+ BOOST_ASIO_MOVE_CAST(Function)(function), this_handler->handler_);
+}
+
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
} // namespace detail
+
+template <typename Handler, typename Arg1, typename Allocator>
+struct associated_allocator<detail::binder1<Handler, Arg1>, Allocator>
+{
+ typedef typename associated_allocator<Handler, Allocator>::type type;
+
+ static type get(const detail::binder1<Handler, Arg1>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<Handler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Allocator>
+struct associated_allocator<detail::binder2<Handler, Arg1, Arg2>, Allocator>
+{
+ typedef typename associated_allocator<Handler, Allocator>::type type;
+
+ static type get(const detail::binder2<Handler, Arg1, Arg2>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<Handler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename Handler, typename Arg1, typename Executor>
+struct associated_executor<detail::binder1<Handler, Arg1>, Executor>
+{
+ typedef typename associated_executor<Handler, Executor>::type type;
+
+ static type get(const detail::binder1<Handler, Arg1>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<Handler, Executor>::get(h.handler_, ex);
+ }
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Executor>
+struct associated_executor<detail::binder2<Handler, Arg1, Arg2>, Executor>
+{
+ typedef typename associated_executor<Handler, Executor>::type type;
+
+ static type get(const detail::binder2<Handler, Arg1, Arg2>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<Handler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+
+template <typename Handler, typename Arg1, typename Allocator>
+struct associated_allocator<detail::move_binder1<Handler, Arg1>, Allocator>
+{
+ typedef typename associated_allocator<Handler, Allocator>::type type;
+
+ static type get(const detail::move_binder1<Handler, Arg1>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<Handler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Allocator>
+struct associated_allocator<
+ detail::move_binder2<Handler, Arg1, Arg2>, Allocator>
+{
+ typedef typename associated_allocator<Handler, Allocator>::type type;
+
+ static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<Handler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename Handler, typename Arg1, typename Executor>
+struct associated_executor<detail::move_binder1<Handler, Arg1>, Executor>
+{
+ typedef typename associated_executor<Handler, Executor>::type type;
+
+ static type get(const detail::move_binder1<Handler, Arg1>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<Handler, Executor>::get(h.handler_, ex);
+ }
+};
+
+template <typename Handler, typename Arg1, typename Arg2, typename Executor>
+struct associated_executor<detail::move_binder2<Handler, Arg1, Arg2>, Executor>
+{
+ typedef typename associated_executor<Handler, Executor>::type type;
+
+ static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<Handler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
} // namespace asio
} // namespace boost
diff --git a/boost/asio/detail/buffer_sequence_adapter.hpp b/boost/asio/detail/buffer_sequence_adapter.hpp
index 20c529e0a2..e04b292266 100644
--- a/boost/asio/detail/buffer_sequence_adapter.hpp
+++ b/boost/asio/detail/buffer_sequence_adapter.hpp
@@ -28,11 +28,12 @@ namespace detail {
class buffer_sequence_adapter_base
{
-protected:
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+public:
// The maximum number of buffers to support in a single operation.
enum { max_buffers = 1 };
+protected:
typedef Windows::Storage::Streams::IBuffer^ native_buffer_type;
BOOST_ASIO_DECL static void init_native_buffer(
@@ -43,28 +44,32 @@ protected:
native_buffer_type& buf,
const boost::asio::const_buffer& buffer);
#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+public:
// The maximum number of buffers to support in a single operation.
enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
+protected:
typedef WSABUF native_buffer_type;
static void init_native_buffer(WSABUF& buf,
const boost::asio::mutable_buffer& buffer)
{
- buf.buf = boost::asio::buffer_cast<char*>(buffer);
- buf.len = static_cast<ULONG>(boost::asio::buffer_size(buffer));
+ buf.buf = static_cast<char*>(buffer.data());
+ buf.len = static_cast<ULONG>(buffer.size());
}
static void init_native_buffer(WSABUF& buf,
const boost::asio::const_buffer& buffer)
{
- buf.buf = const_cast<char*>(boost::asio::buffer_cast<const char*>(buffer));
- buf.len = static_cast<ULONG>(boost::asio::buffer_size(buffer));
+ buf.buf = const_cast<char*>(static_cast<const char*>(buffer.data()));
+ buf.len = static_cast<ULONG>(buffer.size());
}
#else // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+public:
// The maximum number of buffers to support in a single operation.
enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };
+protected:
typedef iovec native_buffer_type;
static void init_iov_base(void*& base, void* addr)
@@ -81,16 +86,15 @@ protected:
static void init_native_buffer(iovec& iov,
const boost::asio::mutable_buffer& buffer)
{
- init_iov_base(iov.iov_base, boost::asio::buffer_cast<void*>(buffer));
- iov.iov_len = boost::asio::buffer_size(buffer);
+ init_iov_base(iov.iov_base, buffer.data());
+ iov.iov_len = buffer.size();
}
static void init_native_buffer(iovec& iov,
const boost::asio::const_buffer& buffer)
{
- init_iov_base(iov.iov_base, const_cast<void*>(
- boost::asio::buffer_cast<const void*>(buffer)));
- iov.iov_len = boost::asio::buffer_size(buffer);
+ init_iov_base(iov.iov_base, const_cast<void*>(buffer.data()));
+ iov.iov_len = buffer.size();
}
#endif // defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
};
@@ -104,14 +108,9 @@ public:
explicit buffer_sequence_adapter(const Buffers& buffer_sequence)
: count_(0), total_buffer_size_(0)
{
- typename Buffers::const_iterator iter = buffer_sequence.begin();
- typename Buffers::const_iterator end = buffer_sequence.end();
- for (; iter != end && count_ < max_buffers; ++iter, ++count_)
- {
- Buffer buffer(*iter);
- init_native_buffer(buffers_[count_], buffer);
- total_buffer_size_ += boost::asio::buffer_size(buffer);
- }
+ buffer_sequence_adapter::init(
+ boost::asio::buffer_sequence_begin(buffer_sequence),
+ boost::asio::buffer_sequence_end(buffer_sequence));
}
native_buffer_type* buffers()
@@ -124,6 +123,11 @@ public:
return count_;
}
+ std::size_t total_size() const
+ {
+ return total_buffer_size_;
+ }
+
bool all_empty() const
{
return total_buffer_size_ == 0;
@@ -131,46 +135,185 @@ public:
static bool all_empty(const Buffers& buffer_sequence)
{
- typename Buffers::const_iterator iter = buffer_sequence.begin();
- typename Buffers::const_iterator end = buffer_sequence.end();
+ return buffer_sequence_adapter::all_empty(
+ boost::asio::buffer_sequence_begin(buffer_sequence),
+ boost::asio::buffer_sequence_end(buffer_sequence));
+ }
+
+ static void validate(const Buffers& buffer_sequence)
+ {
+ buffer_sequence_adapter::validate(
+ boost::asio::buffer_sequence_begin(buffer_sequence),
+ boost::asio::buffer_sequence_end(buffer_sequence));
+ }
+
+ static Buffer first(const Buffers& buffer_sequence)
+ {
+ return buffer_sequence_adapter::first(
+ boost::asio::buffer_sequence_begin(buffer_sequence),
+ boost::asio::buffer_sequence_end(buffer_sequence));
+ }
+
+private:
+ template <typename Iterator>
+ void init(Iterator begin, Iterator end)
+ {
+ Iterator iter = begin;
+ for (; iter != end && count_ < max_buffers; ++iter, ++count_)
+ {
+ Buffer buffer(*iter);
+ init_native_buffer(buffers_[count_], buffer);
+ total_buffer_size_ += buffer.size();
+ }
+ }
+
+ template <typename Iterator>
+ static bool all_empty(Iterator begin, Iterator end)
+ {
+ Iterator iter = begin;
std::size_t i = 0;
for (; iter != end && i < max_buffers; ++iter, ++i)
- if (boost::asio::buffer_size(Buffer(*iter)) > 0)
+ if (Buffer(*iter).size() > 0)
return false;
return true;
}
- static void validate(const Buffers& buffer_sequence)
+ template <typename Iterator>
+ static void validate(Iterator begin, Iterator end)
{
- typename Buffers::const_iterator iter = buffer_sequence.begin();
- typename Buffers::const_iterator end = buffer_sequence.end();
+ Iterator iter = begin;
for (; iter != end; ++iter)
{
Buffer buffer(*iter);
- boost::asio::buffer_cast<const void*>(buffer);
+ buffer.data();
}
}
- static Buffer first(const Buffers& buffer_sequence)
+ template <typename Iterator>
+ static Buffer first(Iterator begin, Iterator end)
{
- typename Buffers::const_iterator iter = buffer_sequence.begin();
- typename Buffers::const_iterator end = buffer_sequence.end();
+ Iterator iter = begin;
for (; iter != end; ++iter)
{
Buffer buffer(*iter);
- if (boost::asio::buffer_size(buffer) != 0)
+ if (buffer.size() != 0)
return buffer;
}
return Buffer();
}
-private:
native_buffer_type buffers_[max_buffers];
std::size_t count_;
std::size_t total_buffer_size_;
};
template <typename Buffer>
+class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffer>
+ : buffer_sequence_adapter_base
+{
+public:
+ explicit buffer_sequence_adapter(
+ const boost::asio::mutable_buffer& buffer_sequence)
+ {
+ init_native_buffer(buffer_, Buffer(buffer_sequence));
+ total_buffer_size_ = buffer_sequence.size();
+ }
+
+ native_buffer_type* buffers()
+ {
+ return &buffer_;
+ }
+
+ std::size_t count() const
+ {
+ return 1;
+ }
+
+ std::size_t total_size() const
+ {
+ return total_buffer_size_;
+ }
+
+ bool all_empty() const
+ {
+ return total_buffer_size_ == 0;
+ }
+
+ static bool all_empty(const boost::asio::mutable_buffer& buffer_sequence)
+ {
+ return buffer_sequence.size() == 0;
+ }
+
+ static void validate(const boost::asio::mutable_buffer& buffer_sequence)
+ {
+ buffer_sequence.data();
+ }
+
+ static Buffer first(const boost::asio::mutable_buffer& buffer_sequence)
+ {
+ return Buffer(buffer_sequence);
+ }
+
+private:
+ native_buffer_type buffer_;
+ std::size_t total_buffer_size_;
+};
+
+template <typename Buffer>
+class buffer_sequence_adapter<Buffer, boost::asio::const_buffer>
+ : buffer_sequence_adapter_base
+{
+public:
+ explicit buffer_sequence_adapter(
+ const boost::asio::const_buffer& buffer_sequence)
+ {
+ init_native_buffer(buffer_, Buffer(buffer_sequence));
+ total_buffer_size_ = buffer_sequence.size();
+ }
+
+ native_buffer_type* buffers()
+ {
+ return &buffer_;
+ }
+
+ std::size_t count() const
+ {
+ return 1;
+ }
+
+ std::size_t total_size() const
+ {
+ return total_buffer_size_;
+ }
+
+ bool all_empty() const
+ {
+ return total_buffer_size_ == 0;
+ }
+
+ static bool all_empty(const boost::asio::const_buffer& buffer_sequence)
+ {
+ return buffer_sequence.size() == 0;
+ }
+
+ static void validate(const boost::asio::const_buffer& buffer_sequence)
+ {
+ buffer_sequence.data();
+ }
+
+ static Buffer first(const boost::asio::const_buffer& buffer_sequence)
+ {
+ return Buffer(buffer_sequence);
+ }
+
+private:
+ native_buffer_type buffer_;
+ std::size_t total_buffer_size_;
+};
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+template <typename Buffer>
class buffer_sequence_adapter<Buffer, boost::asio::mutable_buffers_1>
: buffer_sequence_adapter_base
{
@@ -179,7 +322,7 @@ public:
const boost::asio::mutable_buffers_1& buffer_sequence)
{
init_native_buffer(buffer_, Buffer(buffer_sequence));
- total_buffer_size_ = boost::asio::buffer_size(buffer_sequence);
+ total_buffer_size_ = buffer_sequence.size();
}
native_buffer_type* buffers()
@@ -192,6 +335,11 @@ public:
return 1;
}
+ std::size_t total_size() const
+ {
+ return total_buffer_size_;
+ }
+
bool all_empty() const
{
return total_buffer_size_ == 0;
@@ -199,12 +347,12 @@ public:
static bool all_empty(const boost::asio::mutable_buffers_1& buffer_sequence)
{
- return boost::asio::buffer_size(buffer_sequence) == 0;
+ return buffer_sequence.size() == 0;
}
static void validate(const boost::asio::mutable_buffers_1& buffer_sequence)
{
- boost::asio::buffer_cast<const void*>(buffer_sequence);
+ buffer_sequence.data();
}
static Buffer first(const boost::asio::mutable_buffers_1& buffer_sequence)
@@ -226,7 +374,7 @@ public:
const boost::asio::const_buffers_1& buffer_sequence)
{
init_native_buffer(buffer_, Buffer(buffer_sequence));
- total_buffer_size_ = boost::asio::buffer_size(buffer_sequence);
+ total_buffer_size_ = buffer_sequence.size();
}
native_buffer_type* buffers()
@@ -239,6 +387,11 @@ public:
return 1;
}
+ std::size_t total_size() const
+ {
+ return total_buffer_size_;
+ }
+
bool all_empty() const
{
return total_buffer_size_ == 0;
@@ -246,12 +399,12 @@ public:
static bool all_empty(const boost::asio::const_buffers_1& buffer_sequence)
{
- return boost::asio::buffer_size(buffer_sequence) == 0;
+ return buffer_sequence.size() == 0;
}
static void validate(const boost::asio::const_buffers_1& buffer_sequence)
{
- boost::asio::buffer_cast<const void*>(buffer_sequence);
+ buffer_sequence.data();
}
static Buffer first(const boost::asio::const_buffers_1& buffer_sequence)
@@ -264,6 +417,8 @@ private:
std::size_t total_buffer_size_;
};
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
template <typename Buffer, typename Elem>
class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> >
: buffer_sequence_adapter_base
@@ -274,8 +429,7 @@ public:
{
init_native_buffer(buffers_[0], Buffer(buffer_sequence[0]));
init_native_buffer(buffers_[1], Buffer(buffer_sequence[1]));
- total_buffer_size_ = boost::asio::buffer_size(buffer_sequence[0])
- + boost::asio::buffer_size(buffer_sequence[1]);
+ total_buffer_size_ = buffer_sequence[0].size() + buffer_sequence[1].size();
}
native_buffer_type* buffers()
@@ -288,6 +442,11 @@ public:
return 2;
}
+ std::size_t total_size() const
+ {
+ return total_buffer_size_;
+ }
+
bool all_empty() const
{
return total_buffer_size_ == 0;
@@ -295,19 +454,18 @@ public:
static bool all_empty(const boost::array<Elem, 2>& buffer_sequence)
{
- return boost::asio::buffer_size(buffer_sequence[0]) == 0
- && boost::asio::buffer_size(buffer_sequence[1]) == 0;
+ return buffer_sequence[0].size() == 0 && buffer_sequence[1].size() == 0;
}
static void validate(const boost::array<Elem, 2>& buffer_sequence)
{
- boost::asio::buffer_cast<const void*>(buffer_sequence[0]);
- boost::asio::buffer_cast<const void*>(buffer_sequence[1]);
+ buffer_sequence[0].data();
+ buffer_sequence[1].data();
}
static Buffer first(const boost::array<Elem, 2>& buffer_sequence)
{
- return Buffer(boost::asio::buffer_size(buffer_sequence[0]) != 0
+ return Buffer(buffer_sequence[0].size() != 0
? buffer_sequence[0] : buffer_sequence[1]);
}
@@ -328,8 +486,7 @@ public:
{
init_native_buffer(buffers_[0], Buffer(buffer_sequence[0]));
init_native_buffer(buffers_[1], Buffer(buffer_sequence[1]));
- total_buffer_size_ = boost::asio::buffer_size(buffer_sequence[0])
- + boost::asio::buffer_size(buffer_sequence[1]);
+ total_buffer_size_ = buffer_sequence[0].size() + buffer_sequence[1].size();
}
native_buffer_type* buffers()
@@ -342,6 +499,11 @@ public:
return 2;
}
+ std::size_t total_size() const
+ {
+ return total_buffer_size_;
+ }
+
bool all_empty() const
{
return total_buffer_size_ == 0;
@@ -349,19 +511,18 @@ public:
static bool all_empty(const std::array<Elem, 2>& buffer_sequence)
{
- return boost::asio::buffer_size(buffer_sequence[0]) == 0
- && boost::asio::buffer_size(buffer_sequence[1]) == 0;
+ return buffer_sequence[0].size() == 0 && buffer_sequence[1].size() == 0;
}
static void validate(const std::array<Elem, 2>& buffer_sequence)
{
- boost::asio::buffer_cast<const void*>(buffer_sequence[0]);
- boost::asio::buffer_cast<const void*>(buffer_sequence[1]);
+ buffer_sequence[0].data();
+ buffer_sequence[1].data();
}
static Buffer first(const std::array<Elem, 2>& buffer_sequence)
{
- return Buffer(boost::asio::buffer_size(buffer_sequence[0]) != 0
+ return Buffer(buffer_sequence[0].size() != 0
? buffer_sequence[0] : buffer_sequence[1]);
}
diff --git a/boost/asio/detail/call_stack.hpp b/boost/asio/detail/call_stack.hpp
index 5253e3b153..52de6ef00d 100644
--- a/boost/asio/detail/call_stack.hpp
+++ b/boost/asio/detail/call_stack.hpp
@@ -26,7 +26,7 @@ namespace asio {
namespace detail {
// Helper class to determine whether or not the current thread is inside an
-// invocation of io_service::run() for a specified io_service object.
+// invocation of io_context::run() for a specified io_context object.
template <typename Key, typename Value = unsigned char>
class call_stack
{
diff --git a/boost/asio/detail/chrono.hpp b/boost/asio/detail/chrono.hpp
new file mode 100644
index 0000000000..923e7697b2
--- /dev/null
+++ b/boost/asio/detail/chrono.hpp
@@ -0,0 +1,68 @@
+//
+// detail/chrono.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_CHRONO_HPP
+#define BOOST_ASIO_DETAIL_CHRONO_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_STD_CHRONO)
+# include <chrono>
+#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
+# include <boost/chrono/system_clocks.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_CHRONO)
+
+namespace boost {
+namespace asio {
+namespace chrono {
+
+#if defined(BOOST_ASIO_HAS_STD_CHRONO)
+using std::chrono::duration;
+using std::chrono::time_point;
+using std::chrono::duration_cast;
+using std::chrono::nanoseconds;
+using std::chrono::microseconds;
+using std::chrono::milliseconds;
+using std::chrono::seconds;
+using std::chrono::minutes;
+using std::chrono::hours;
+using std::chrono::time_point_cast;
+#if defined(BOOST_ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)
+typedef std::chrono::monotonic_clock steady_clock;
+#else // defined(BOOST_ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)
+using std::chrono::steady_clock;
+#endif // defined(BOOST_ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)
+using std::chrono::system_clock;
+using std::chrono::high_resolution_clock;
+#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
+using boost::chrono::duration;
+using boost::chrono::time_point;
+using boost::chrono::duration_cast;
+using boost::chrono::nanoseconds;
+using boost::chrono::microseconds;
+using boost::chrono::milliseconds;
+using boost::chrono::seconds;
+using boost::chrono::minutes;
+using boost::chrono::hours;
+using boost::chrono::time_point_cast;
+using boost::chrono::system_clock;
+using boost::chrono::steady_clock;
+using boost::chrono::high_resolution_clock;
+#endif // defined(BOOST_ASIO_HAS_BOOST_CHRONO)
+
+} // namespace chrono
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_CHRONO_HPP
diff --git a/boost/asio/detail/completion_handler.hpp b/boost/asio/detail/completion_handler.hpp
index 6333dce569..d18d372eeb 100644
--- a/boost/asio/detail/completion_handler.hpp
+++ b/boost/asio/detail/completion_handler.hpp
@@ -15,11 +15,11 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/config.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
-#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/handler_work.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -38,17 +38,19 @@ public:
: operation(&completion_handler::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(h))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
completion_handler* h(static_cast<completion_handler*>(base));
ptr p = { boost::asio::detail::addressof(h->handler_), h, h };
+ handler_work<Handler> w(h->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((h));
+ BOOST_ASIO_HANDLER_COMPLETION((*h));
// 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
@@ -65,7 +67,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN(());
- boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ w.complete(handler, handler);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/concurrency_hint.hpp b/boost/asio/detail/concurrency_hint.hpp
new file mode 100644
index 0000000000..0a13205499
--- /dev/null
+++ b/boost/asio/detail/concurrency_hint.hpp
@@ -0,0 +1,94 @@
+//
+// detail/concurrency_hint.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_CONCURRENCY_HINT_HPP
+#define BOOST_ASIO_DETAIL_CONCURRENCY_HINT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+
+// The concurrency hint ID and mask are used to identify when a "well-known"
+// concurrency hint value has been passed to the io_context.
+#define BOOST_ASIO_CONCURRENCY_HINT_ID 0xA5100000u
+#define BOOST_ASIO_CONCURRENCY_HINT_ID_MASK 0xFFFF0000u
+
+// If set, this bit indicates that the scheduler should perform locking.
+#define BOOST_ASIO_CONCURRENCY_HINT_LOCKING_SCHEDULER 0x1u
+
+// If set, this bit indicates that the reactor should perform locking when
+// managing descriptor registrations.
+#define BOOST_ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_REGISTRATION 0x2u
+
+// If set, this bit indicates that the reactor should perform locking for I/O.
+#define BOOST_ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_IO 0x4u
+
+// Helper macro to determine if we have a special concurrency hint.
+#define BOOST_ASIO_CONCURRENCY_HINT_IS_SPECIAL(hint) \
+ ((static_cast<unsigned>(hint) \
+ & BOOST_ASIO_CONCURRENCY_HINT_ID_MASK) \
+ == BOOST_ASIO_CONCURRENCY_HINT_ID)
+
+// Helper macro to determine if locking is enabled for a given facility.
+#define BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(facility, hint) \
+ (((static_cast<unsigned>(hint) \
+ & (BOOST_ASIO_CONCURRENCY_HINT_ID_MASK \
+ | BOOST_ASIO_CONCURRENCY_HINT_LOCKING_ ## facility)) \
+ ^ BOOST_ASIO_CONCURRENCY_HINT_ID) != 0)
+
+// This special concurrency hint disables locking in both the scheduler and
+// reactor I/O. This hint has the following restrictions:
+//
+// - Care must be taken to ensure that all operations on the io_context and any
+// of its associated I/O objects (such as sockets and timers) occur in only
+// one thread at a time.
+//
+// - Asynchronous resolve operations fail with operation_not_supported.
+//
+// - If a signal_set is used with the io_context, signal_set objects cannot be
+// used with any other io_context in the program.
+#define BOOST_ASIO_CONCURRENCY_HINT_UNSAFE \
+ static_cast<int>(BOOST_ASIO_CONCURRENCY_HINT_ID)
+
+// This special concurrency hint disables locking in the reactor I/O. This hint
+// has the following restrictions:
+//
+// - Care must be taken to ensure that run functions on the io_context, and all
+// operations on the io_context's associated I/O objects (such as sockets and
+// timers), occur in only one thread at a time.
+#define BOOST_ASIO_CONCURRENCY_HINT_UNSAFE_IO \
+ static_cast<int>(BOOST_ASIO_CONCURRENCY_HINT_ID \
+ | BOOST_ASIO_CONCURRENCY_HINT_LOCKING_SCHEDULER \
+ | BOOST_ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_REGISTRATION)
+
+// The special concurrency hint provides full thread safety.
+#define BOOST_ASIO_CONCURRENCY_HINT_SAFE \
+ static_cast<int>(BOOST_ASIO_CONCURRENCY_HINT_ID \
+ | BOOST_ASIO_CONCURRENCY_HINT_LOCKING_SCHEDULER \
+ | BOOST_ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_REGISTRATION \
+ | BOOST_ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_IO)
+
+// This #define may be overridden at compile time to specify a program-wide
+// default concurrency hint, used by the zero-argument io_context constructor.
+#if !defined(BOOST_ASIO_CONCURRENCY_HINT_DEFAULT)
+# define BOOST_ASIO_CONCURRENCY_HINT_DEFAULT -1
+#endif // !defined(BOOST_ASIO_CONCURRENCY_HINT_DEFAULT)
+
+// This #define may be overridden at compile time to specify a program-wide
+// concurrency hint, used by the one-argument io_context constructor when
+// passed a value of 1.
+#if !defined(BOOST_ASIO_CONCURRENCY_HINT_1)
+# define BOOST_ASIO_CONCURRENCY_HINT_1 1
+#endif // !defined(BOOST_ASIO_CONCURRENCY_HINT_DEFAULT)
+
+#endif // BOOST_ASIO_DETAIL_CONCURRENCY_HINT_HPP
diff --git a/boost/asio/detail/conditionally_enabled_event.hpp b/boost/asio/detail/conditionally_enabled_event.hpp
new file mode 100644
index 0000000000..c2be28587c
--- /dev/null
+++ b/boost/asio/detail/conditionally_enabled_event.hpp
@@ -0,0 +1,114 @@
+//
+// detail/conditionally_enabled_event.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_EVENT_HPP
+#define BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_EVENT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/conditionally_enabled_mutex.hpp>
+#include <boost/asio/detail/event.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/null_event.hpp>
+#include <boost/asio/detail/scoped_lock.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Mutex adapter used to conditionally enable or disable locking.
+class conditionally_enabled_event
+ : private noncopyable
+{
+public:
+ // Constructor.
+ conditionally_enabled_event()
+ {
+ }
+
+ // Destructor.
+ ~conditionally_enabled_event()
+ {
+ }
+
+ // Signal the event. (Retained for backward compatibility.)
+ void signal(conditionally_enabled_mutex::scoped_lock& lock)
+ {
+ if (lock.mutex_.enabled_)
+ event_.signal(lock);
+ }
+
+ // Signal all waiters.
+ void signal_all(conditionally_enabled_mutex::scoped_lock& lock)
+ {
+ if (lock.mutex_.enabled_)
+ event_.signal_all(lock);
+ }
+
+ // Unlock the mutex and signal one waiter.
+ void unlock_and_signal_one(
+ conditionally_enabled_mutex::scoped_lock& lock)
+ {
+ if (lock.mutex_.enabled_)
+ event_.unlock_and_signal_one(lock);
+ }
+
+ // If there's a waiter, unlock the mutex and signal it.
+ bool maybe_unlock_and_signal_one(
+ conditionally_enabled_mutex::scoped_lock& lock)
+ {
+ if (lock.mutex_.enabled_)
+ return event_.maybe_unlock_and_signal_one(lock);
+ else
+ return false;
+ }
+
+ // Reset the event.
+ void clear(conditionally_enabled_mutex::scoped_lock& lock)
+ {
+ if (lock.mutex_.enabled_)
+ event_.clear(lock);
+ }
+
+ // Wait for the event to become signalled.
+ void wait(conditionally_enabled_mutex::scoped_lock& lock)
+ {
+ if (lock.mutex_.enabled_)
+ event_.wait(lock);
+ else
+ null_event().wait(lock);
+ }
+
+ // Timed wait for the event to become signalled.
+ bool wait_for_usec(
+ conditionally_enabled_mutex::scoped_lock& lock, long usec)
+ {
+ if (lock.mutex_.enabled_)
+ return event_.wait_for_usec(lock, usec);
+ else
+ return null_event().wait_for_usec(lock, usec);
+ }
+
+private:
+ boost::asio::detail::event event_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_EVENT_HPP
diff --git a/boost/asio/detail/conditionally_enabled_mutex.hpp b/boost/asio/detail/conditionally_enabled_mutex.hpp
new file mode 100644
index 0000000000..c7762b6889
--- /dev/null
+++ b/boost/asio/detail/conditionally_enabled_mutex.hpp
@@ -0,0 +1,151 @@
+//
+// detail/conditionally_enabled_mutex.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
+#define BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/scoped_lock.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Mutex adapter used to conditionally enable or disable locking.
+class conditionally_enabled_mutex
+ : private noncopyable
+{
+public:
+ // Helper class to lock and unlock a mutex automatically.
+ class scoped_lock
+ : private noncopyable
+ {
+ public:
+ // Tag type used to distinguish constructors.
+ enum adopt_lock_t { adopt_lock };
+
+ // Constructor adopts a lock that is already held.
+ scoped_lock(conditionally_enabled_mutex& m, adopt_lock_t)
+ : mutex_(m),
+ locked_(m.enabled_)
+ {
+ }
+
+ // Constructor acquires the lock.
+ explicit scoped_lock(conditionally_enabled_mutex& m)
+ : mutex_(m)
+ {
+ if (m.enabled_)
+ {
+ mutex_.mutex_.lock();
+ locked_ = true;
+ }
+ else
+ locked_ = false;
+ }
+
+ // Destructor releases the lock.
+ ~scoped_lock()
+ {
+ if (locked_)
+ mutex_.mutex_.unlock();
+ }
+
+ // Explicitly acquire the lock.
+ void lock()
+ {
+ if (mutex_.enabled_ && !locked_)
+ {
+ mutex_.mutex_.lock();
+ locked_ = true;
+ }
+ }
+
+ // Explicitly release the lock.
+ void unlock()
+ {
+ if (locked_)
+ {
+ mutex_.unlock();
+ locked_ = false;
+ }
+ }
+
+ // Test whether the lock is held.
+ bool locked() const
+ {
+ return locked_;
+ }
+
+ // Get the underlying mutex.
+ boost::asio::detail::mutex& mutex()
+ {
+ return mutex_.mutex_;
+ }
+
+ private:
+ friend class conditionally_enabled_event;
+ conditionally_enabled_mutex& mutex_;
+ bool locked_;
+ };
+
+ // Constructor.
+ explicit conditionally_enabled_mutex(bool enabled)
+ : enabled_(enabled)
+ {
+ }
+
+ // Destructor.
+ ~conditionally_enabled_mutex()
+ {
+ }
+
+ // Determine whether locking is enabled.
+ bool enabled() const
+ {
+ return enabled_;
+ }
+
+ // Lock the mutex.
+ void lock()
+ {
+ if (enabled_)
+ mutex_.lock();
+ }
+
+ // Unlock the mutex.
+ void unlock()
+ {
+ if (enabled_)
+ mutex_.unlock();
+ }
+
+private:
+ friend class scoped_lock;
+ friend class conditionally_enabled_event;
+ boost::asio::detail::mutex mutex_;
+ const bool enabled_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
diff --git a/boost/asio/detail/config.hpp b/boost/asio/detail/config.hpp
index afe400e5b7..b3272a666f 100644
--- a/boost/asio/detail/config.hpp
+++ b/boost/asio/detail/config.hpp
@@ -83,6 +83,11 @@
# endif // (__cplusplus >= 201103)
#endif // defined(__clang__)
+// Android platform detection.
+#if defined(__ANDROID__)
+# include <android/api-level.h>
+#endif // defined(__ANDROID__)
+
// Support move construction and assignment on compilers known to allow it.
#if !defined(BOOST_ASIO_HAS_MOVE)
# if !defined(BOOST_ASIO_DISABLE_MOVE)
@@ -111,6 +116,7 @@
// references and perfect forwarding.
#if defined(BOOST_ASIO_HAS_MOVE) && !defined(BOOST_ASIO_MOVE_CAST)
# define BOOST_ASIO_MOVE_ARG(type) type&&
+# define BOOST_ASIO_MOVE_ARG2(type1, type2) type1, type2&&
# define BOOST_ASIO_MOVE_CAST(type) static_cast<type&&>
# define BOOST_ASIO_MOVE_CAST2(type1, type2) static_cast<type1, type2&&>
#endif // defined(BOOST_ASIO_HAS_MOVE) && !defined(BOOST_ASIO_MOVE_CAST)
@@ -163,6 +169,30 @@
# endif // !defined(BOOST_ASIO_DISABLE_VARIADIC_TEMPLATES)
#endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+// Support deleted functions on compilers known to allow it.
+#if !defined(BOOST_ASIO_DELETED)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_DELETED = delete
+# endif // 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 BOOST_ASIO_DELETED = delete
+# endif // __has_feature(__cxx_deleted_functions__)
+# endif // defined(__clang__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1900)
+# define BOOST_ASIO_DELETED = delete
+# endif // (_MSC_VER >= 1900)
+# endif // defined(BOOST_ASIO_MSVC)
+# if !defined(BOOST_ASIO_DELETED)
+# define BOOST_ASIO_DELETED
+# endif // !defined(BOOST_ASIO_DELETED)
+#endif // !defined(BOOST_ASIO_DELETED)
+
// Support constexpr on compilers known to allow it.
#if !defined(BOOST_ASIO_HAS_CONSTEXPR)
# if !defined(BOOST_ASIO_DISABLE_CONSTEXPR)
@@ -193,6 +223,85 @@
# endif // defined(BOOST_ASIO_HAS_CONSTEXPR)
#endif // !defined(BOOST_ASIO_CONSTEXPR)
+// Support noexcept on compilers known to allow it.
+#if !defined(BOOST_ASIO_NOEXCEPT)
+# if !defined(BOOST_ASIO_DISABLE_NOEXCEPT)
+# if (BOOST_VERSION >= 105300)
+# define BOOST_ASIO_NOEXCEPT BOOST_NOEXCEPT
+# define BOOST_ASIO_NOEXCEPT_OR_NOTHROW BOOST_NOEXCEPT_OR_NOTHROW
+# elif defined(__clang__)
+# if __has_feature(__cxx_noexcept__)
+# define BOOST_ASIO_NOEXCEPT noexcept(true)
+# define BOOST_ASIO_NOEXCEPT_OR_NOTHROW noexcept(true)
+# endif // __has_feature(__cxx_noexcept__)
+# elif defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_NOEXCEPT noexcept(true)
+# define BOOST_ASIO_NOEXCEPT_OR_NOTHROW noexcept(true)
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# elif defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1900)
+# define BOOST_ASIO_NOEXCEPT noexcept(true)
+# define BOOST_ASIO_NOEXCEPT_OR_NOTHROW noexcept(true)
+# endif // (_MSC_VER >= 1900)
+# endif // defined(BOOST_ASIO_MSVC)
+# endif // !defined(BOOST_ASIO_DISABLE_NOEXCEPT)
+# if !defined(BOOST_ASIO_NOEXCEPT)
+# define BOOST_ASIO_NOEXCEPT
+# endif // !defined(BOOST_ASIO_NOEXCEPT)
+# if !defined(BOOST_ASIO_NOEXCEPT_OR_NOTHROW)
+# define BOOST_ASIO_NOEXCEPT_OR_NOTHROW throw()
+# endif // !defined(BOOST_ASIO_NOEXCEPT_OR_NOTHROW)
+#endif // !defined(BOOST_ASIO_NOEXCEPT)
+
+// Support automatic type deduction on compilers known to support it.
+#if !defined(BOOST_ASIO_HAS_DECLTYPE)
+# if !defined(BOOST_ASIO_DISABLE_DECLTYPE)
+# if defined(__clang__)
+# if __has_feature(__cxx_decltype__)
+# define BOOST_ASIO_HAS_DECLTYPE 1
+# endif // __has_feature(__cxx_decltype__)
+# endif // defined(__clang__)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_HAS_DECLTYPE 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1700)
+# define BOOST_ASIO_HAS_DECLTYPE 1
+# endif // (_MSC_VER >= 1700)
+# endif // defined(BOOST_ASIO_MSVC)
+# endif // !defined(BOOST_ASIO_DISABLE_DECLTYPE)
+#endif // !defined(BOOST_ASIO_HAS_DECLTYPE)
+
+// Support alias templates on compilers known to allow it.
+#if !defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
+# if !defined(BOOST_ASIO_DISABLE_ALIAS_TEMPLATES)
+# if defined(__clang__)
+# if __has_feature(__cxx_alias_templates__)
+# define BOOST_ASIO_HAS_ALIAS_TEMPLATES 1
+# endif // __has_feature(__cxx_alias_templates__)
+# endif // defined(__clang__)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_HAS_ALIAS_TEMPLATES 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1900)
+# define BOOST_ASIO_HAS_ALIAS_TEMPLATES 1
+# endif // (_MSC_VER >= 1900)
+# endif // defined(BOOST_ASIO_MSVC)
+# endif // !defined(BOOST_ASIO_DISABLE_ALIAS_TEMPLATES)
+#endif // !defined(BOOST_ASIO_HAS_ALIAS_TEMPLATES)
+
// Standard library support for system errors.
# if !defined(BOOST_ASIO_DISABLE_STD_SYSTEM_ERROR)
# if defined(__clang__)
@@ -294,6 +403,31 @@
# endif // !defined(BOOST_ASIO_DISABLE_STD_SHARED_PTR)
#endif // !defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
+// Standard library support for allocator_arg_t.
+#if !defined(BOOST_ASIO_HAS_STD_ALLOCATOR_ARG)
+# if !defined(BOOST_ASIO_DISABLE_STD_ALLOCATOR_ARG)
+# if defined(__clang__)
+# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX)
+# define BOOST_ASIO_HAS_STD_ALLOCATOR_ARG 1
+# elif (__cplusplus >= 201103)
+# define BOOST_ASIO_HAS_STD_ALLOCATOR_ARG 1
+# endif // (__cplusplus >= 201103)
+# endif // defined(__clang__)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_HAS_STD_ALLOCATOR_ARG 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1600)
+# define BOOST_ASIO_HAS_STD_ALLOCATOR_ARG 1
+# endif // (_MSC_VER >= 1600)
+# endif // defined(BOOST_ASIO_MSVC)
+# endif // !defined(BOOST_ASIO_DISABLE_STD_ALLOCATOR_ARG)
+#endif // !defined(BOOST_ASIO_HAS_STD_ALLOCATOR_ARG)
+
// Standard library support for atomic operations.
#if !defined(BOOST_ASIO_HAS_STD_ATOMIC)
# if !defined(BOOST_ASIO_DISABLE_STD_ATOMIC)
@@ -362,6 +496,15 @@
# endif // !defined(BOOST_ASIO_DISABLE_BOOST_CHRONO)
#endif // !defined(BOOST_ASIO_HAS_BOOST_CHRONO)
+// Some form of chrono library is available.
+#if !defined(BOOST_ASIO_HAS_CHRONO)
+# if defined(BOOST_ASIO_HAS_STD_CHRONO) \
+ || defined(BOOST_ASIO_HAS_BOOST_CHRONO)
+# define BOOST_ASIO_HAS_CHRONO 1
+# endif // defined(BOOST_ASIO_HAS_STD_CHRONO)
+ // || defined(BOOST_ASIO_HAS_BOOST_CHRONO)
+#endif // !defined(BOOST_ASIO_HAS_CHRONO)
+
// Boost support for the DateTime library.
#if !defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
# if !defined(BOOST_ASIO_DISABLE_BOOST_DATE_TIME)
@@ -446,6 +589,28 @@
# endif // !defined(BOOST_ASIO_DISABLE_STD_TYPE_TRAITS)
#endif // !defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS)
+// Standard library support for the nullptr_t type.
+#if !defined(BOOST_ASIO_HAS_NULLPTR)
+# if !defined(BOOST_ASIO_DISABLE_NULLPTR)
+# if defined(__clang__)
+# if __has_feature(__cxx_nullptr__)
+# define BOOST_ASIO_HAS_NULLPTR 1
+# endif // __has_feature(__cxx_rvalue_references__)
+# elif defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_HAS_NULLPTR 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1700)
+# define BOOST_ASIO_HAS_NULLPTR 1
+# endif // (_MSC_VER >= 1700)
+# endif // defined(BOOST_ASIO_MSVC)
+# endif // !defined(BOOST_ASIO_DISABLE_NULLPTR)
+#endif // !defined(BOOST_ASIO_HAS_NULLPTR)
+
// Standard library support for the C++11 allocator additions.
#if !defined(BOOST_ASIO_HAS_CXX11_ALLOCATORS)
# if !defined(BOOST_ASIO_DISABLE_CXX11_ALLOCATORS)
@@ -456,16 +621,16 @@
# define BOOST_ASIO_HAS_CXX11_ALLOCATORS 1
# endif // (__cplusplus >= 201103)
# elif defined(__GNUC__)
-# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
# if defined(__GXX_EXPERIMENTAL_CXX0X__)
# define BOOST_ASIO_HAS_CXX11_ALLOCATORS 1
# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
-# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
# endif // defined(__GNUC__)
# if defined(BOOST_ASIO_MSVC)
-# if (_MSC_VER >= 1700)
+# if (_MSC_VER >= 1800)
# define BOOST_ASIO_HAS_CXX11_ALLOCATORS 1
-# endif // (_MSC_VER >= 1700)
+# endif // (_MSC_VER >= 1800)
# endif // defined(BOOST_ASIO_MSVC)
# endif // !defined(BOOST_ASIO_DISABLE_CXX11_ALLOCATORS)
#endif // !defined(BOOST_ASIO_HAS_CXX11_ALLOCATORS)
@@ -549,6 +714,105 @@
# endif // !defined(BOOST_ASIO_DISABLE_STD_MUTEX_AND_CONDVAR)
#endif // !defined(BOOST_ASIO_HAS_STD_MUTEX_AND_CONDVAR)
+// Standard library support for the call_once function.
+#if !defined(BOOST_ASIO_HAS_STD_CALL_ONCE)
+# if !defined(BOOST_ASIO_DISABLE_STD_CALL_ONCE)
+# if defined(__clang__)
+# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX)
+# define BOOST_ASIO_HAS_STD_CALL_ONCE 1
+# elif (__cplusplus >= 201103)
+# if __has_include(<mutex>)
+# define BOOST_ASIO_HAS_STD_CALL_ONCE 1
+# endif // __has_include(<mutex>)
+# endif // (__cplusplus >= 201103)
+# endif // defined(__clang__)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_HAS_STD_CALL_ONCE 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1700)
+# define BOOST_ASIO_HAS_STD_CALL_ONCE 1
+# endif // (_MSC_VER >= 1700)
+# endif // defined(BOOST_ASIO_MSVC)
+# endif // !defined(BOOST_ASIO_DISABLE_STD_CALL_ONCE)
+#endif // !defined(BOOST_ASIO_HAS_STD_CALL_ONCE)
+
+// Standard library support for futures.
+#if !defined(BOOST_ASIO_HAS_STD_FUTURE)
+# if !defined(BOOST_ASIO_DISABLE_STD_FUTURE)
+# if defined(__clang__)
+# if defined(BOOST_ASIO_HAS_CLANG_LIBCXX)
+# define BOOST_ASIO_HAS_STD_FUTURE 1
+# elif (__cplusplus >= 201103)
+# if __has_include(<future>)
+# define BOOST_ASIO_HAS_STD_FUTURE 1
+# endif // __has_include(<mutex>)
+# endif // (__cplusplus >= 201103)
+# endif // defined(__clang__)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_HAS_STD_FUTURE 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1700)
+# define BOOST_ASIO_HAS_STD_FUTURE 1
+# endif // (_MSC_VER >= 1700)
+# endif // defined(BOOST_ASIO_MSVC)
+# endif // !defined(BOOST_ASIO_DISABLE_STD_FUTURE)
+#endif // !defined(BOOST_ASIO_HAS_STD_FUTURE)
+
+// Standard library support for experimental::string_view.
+#if !defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+# if !defined(BOOST_ASIO_DISABLE_STD_STRING_VIEW)
+# if defined(__clang__)
+# if (__cplusplus >= 201402)
+# if __has_include(<experimental/string_view>)
+# define BOOST_ASIO_HAS_STD_STRING_VIEW 1
+# define BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW 1
+# endif // __has_include(<experimental/string_view>)
+# endif // (__cplusplus >= 201402)
+# endif // defined(__clang__)
+# if defined(__GNUC__)
+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)
+# if (__cplusplus >= 201402)
+# define BOOST_ASIO_HAS_STD_STRING_VIEW 1
+# define BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW 1
+# endif // (__cplusplus >= 201402)
+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1910 && _HAS_CXX17)
+# define BOOST_ASIO_HAS_STD_STRING_VIEW
+# endif // (_MSC_VER >= 1910)
+# endif // defined(BOOST_ASIO_MSVC)
+# endif // !defined(BOOST_ASIO_DISABLE_STD_STRING_VIEW)
+#endif // !defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
+// Standard library support for iostream move construction and assignment.
+#if !defined(BOOST_ASIO_HAS_STD_IOSTREAM_MOVE)
+# if !defined(BOOST_ASIO_DISABLE_STD_IOSTREAM_MOVE)
+# if defined(__GNUC__)
+# if (__GNUC__ > 4)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__)
+# define BOOST_ASIO_HAS_STD_IOSTREAM_MOVE 1
+# endif // defined(__GXX_EXPERIMENTAL_CXX0X__)
+# endif // (__GNUC__ > 4)
+# endif // defined(__GNUC__)
+# if defined(BOOST_ASIO_MSVC)
+# if (_MSC_VER >= 1700)
+# define BOOST_ASIO_HAS_STD_IOSTREAM_MOVE 1
+# endif // (_MSC_VER >= 1700)
+# endif // defined(BOOST_ASIO_MSVC)
+# endif // !defined(BOOST_ASIO_DISABLE_STD_IOSTREAM_MOVE)
+#endif // !defined(BOOST_ASIO_HAS_STD_IOSTREAM_MOVE)
+
// Windows App target. Windows but with a limited API.
#if !defined(BOOST_ASIO_WINDOWS_APP)
# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0603)
@@ -884,11 +1148,18 @@
# if !defined(BOOST_ASIO_DISABLE_THREADS)
# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_THREADS)
# define BOOST_ASIO_HAS_THREADS 1
-# elif defined(_MSC_VER) && defined(_MT)
+# elif defined(__GNUC__) && !defined(__MINGW32__) \
+ && !defined(linux) && !defined(__linux) && !defined(__linux__)
# define BOOST_ASIO_HAS_THREADS 1
-# elif defined(__BORLANDC__) && defined(__MT__)
+# elif defined(_MT) || defined(__MT__)
# define BOOST_ASIO_HAS_THREADS 1
-# elif defined(_POSIX_THREADS)
+# elif defined(_REENTRANT)
+# define BOOST_ASIO_HAS_THREADS 1
+# elif defined(__APPLE__)
+# define BOOST_ASIO_HAS_THREADS 1
+# elif defined(_POSIX_THREADS) && (_POSIX_THREADS + 0 >= 0)
+# define BOOST_ASIO_HAS_THREADS 1
+# elif defined(_PTHREADS)
# define BOOST_ASIO_HAS_THREADS 1
# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_THREADS)
# endif // !defined(BOOST_ASIO_DISABLE_THREADS)
@@ -899,7 +1170,7 @@
# if defined(BOOST_ASIO_HAS_THREADS)
# if defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS)
# define BOOST_ASIO_HAS_PTHREADS 1
-# elif defined(_POSIX_THREADS)
+# elif defined(_POSIX_THREADS) && (_POSIX_THREADS + 0 >= 0)
# define BOOST_ASIO_HAS_PTHREADS 1
# endif // defined(BOOST_ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS)
# endif // defined(BOOST_ASIO_HAS_THREADS)
@@ -1030,6 +1301,42 @@
// || (defined(__MACH__) && defined(__APPLE__))
#endif // !defined(BOOST_ASIO_DISABLE_SSIZE_T)
+// Helper macros to manage the transition away from the old services-based API.
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# define BOOST_ASIO_SVC_TPARAM , typename Service
+# define BOOST_ASIO_SVC_TPARAM_DEF1(d1) , typename Service d1
+# define BOOST_ASIO_SVC_TPARAM_DEF2(d1, d2) , typename Service d1, d2
+# define BOOST_ASIO_SVC_TARG , Service
+# define BOOST_ASIO_SVC_T Service
+# define BOOST_ASIO_SVC_TPARAM1 , typename Service1
+# define BOOST_ASIO_SVC_TPARAM1_DEF1(d1) , typename Service1 d1
+# define BOOST_ASIO_SVC_TPARAM1_DEF2(d1, d2) , typename Service1 d1, d2
+# define BOOST_ASIO_SVC_TARG1 , Service1
+# define BOOST_ASIO_SVC_T1 Service1
+# define BOOST_ASIO_SVC_ACCESS public
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# define BOOST_ASIO_SVC_TPARAM
+# define BOOST_ASIO_SVC_TPARAM_DEF1(d1)
+# define BOOST_ASIO_SVC_TPARAM_DEF2(d1, d2)
+# define BOOST_ASIO_SVC_TARG
+// BOOST_ASIO_SVC_T is defined at each point of use.
+# define BOOST_ASIO_SVC_TPARAM1
+# define BOOST_ASIO_SVC_TPARAM1_DEF1(d1)
+# define BOOST_ASIO_SVC_TPARAM1_DEF2(d1, d2)
+# define BOOST_ASIO_SVC_TARG1
+// BOOST_ASIO_SVC_T1 is defined at each point of use.
+# define BOOST_ASIO_SVC_ACCESS protected
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+// Helper macros to manage transition away from error_code return values.
+#if defined(BOOST_ASIO_NO_DEPRECATED)
+# define BOOST_ASIO_SYNC_OP_VOID void
+# define BOOST_ASIO_SYNC_OP_VOID_RETURN(e) return
+#else // defined(BOOST_ASIO_NO_DEPRECATED)
+# define BOOST_ASIO_SYNC_OP_VOID boost::system::error_code
+# define BOOST_ASIO_SYNC_OP_VOID_RETURN(e) return e
+#endif // defined(BOOST_ASIO_NO_DEPRECATED)
+
// Newer gcc, clang need special treatment to suppress unused typedef warnings.
#if defined(__clang__)
# if defined(__apple_build_version__)
diff --git a/boost/asio/detail/consuming_buffers.hpp b/boost/asio/detail/consuming_buffers.hpp
index f0978b54d3..a429f974d6 100644
--- a/boost/asio/detail/consuming_buffers.hpp
+++ b/boost/asio/detail/consuming_buffers.hpp
@@ -17,8 +17,8 @@
#include <boost/asio/detail/config.hpp>
#include <cstddef>
-#include <iterator>
#include <boost/asio/buffer.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/limits.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -27,262 +27,384 @@ namespace boost {
namespace asio {
namespace detail {
-// A proxy iterator for a sub-range in a list of buffers.
-template <typename Buffer, typename Buffer_Iterator>
-class consuming_buffers_iterator
+// Helper template to determine the maximum number of prepared buffers.
+template <typename Buffers>
+struct prepared_buffers_max
{
-public:
- /// The type used for the distance between two iterators.
- typedef std::ptrdiff_t difference_type;
+ enum { value = buffer_sequence_adapter_base::max_buffers };
+};
+
+template <typename Elem, std::size_t N>
+struct prepared_buffers_max<boost::array<Elem, N> >
+{
+ enum { value = N };
+};
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+
+template <typename Elem, std::size_t N>
+struct prepared_buffers_max<std::array<Elem, N> >
+{
+ enum { value = N };
+};
- /// The type of the value pointed to by the iterator.
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+
+// A buffer sequence used to represent a subsequence of the buffers.
+template <typename Buffer, std::size_t MaxBuffers>
+struct prepared_buffers
+{
typedef Buffer value_type;
+ typedef const Buffer* const_iterator;
- /// The type of the result of applying operator->() to the iterator.
- typedef const Buffer* pointer;
+ enum { max_buffers = MaxBuffers < 16 ? MaxBuffers : 16 };
- /// The type of the result of applying operator*() to the iterator.
- typedef const Buffer& reference;
+ prepared_buffers() : count(0) {}
+ const_iterator begin() const { return elems; }
+ const_iterator end() const { return elems + count; }
+
+ Buffer elems[max_buffers];
+ std::size_t count;
+};
- /// The iterator category.
- typedef std::forward_iterator_tag iterator_category;
+// A proxy for a sub-range in a list of buffers.
+template <typename Buffer, typename Buffers, typename Buffer_Iterator>
+class consuming_buffers
+{
+public:
+ typedef prepared_buffers<Buffer, prepared_buffers_max<Buffers>::value>
+ prepared_buffers_type;
- // Default constructor creates an end iterator.
- consuming_buffers_iterator()
- : at_end_(true)
+ // Construct to represent the entire list of buffers.
+ explicit consuming_buffers(const Buffers& buffers)
+ : buffers_(buffers),
+ total_consumed_(0),
+ next_elem_(0),
+ next_elem_offset_(0)
{
+ using boost::asio::buffer_size;
+ total_size_ = buffer_size(buffers);
}
- // Construct with a buffer for the first entry and an iterator
- // range for the remaining entries.
- consuming_buffers_iterator(bool at_end, const Buffer& first,
- Buffer_Iterator begin_remainder, Buffer_Iterator end_remainder,
- std::size_t max_size)
- : at_end_(max_size > 0 ? at_end : true),
- first_(buffer(first, max_size)),
- begin_remainder_(begin_remainder),
- end_remainder_(end_remainder),
- offset_(0),
- max_size_(max_size)
+ // Determine if we are at the end of the buffers.
+ bool empty() const
{
+ return total_consumed_ >= total_size_;
}
- // Dereference an iterator.
- const Buffer& operator*() const
+ // Get the buffer for a single transfer, with a size.
+ prepared_buffers_type prepare(std::size_t max_size)
{
- return dereference();
+ prepared_buffers_type result;
+
+ Buffer_Iterator next = boost::asio::buffer_sequence_begin(buffers_);
+ Buffer_Iterator end = boost::asio::buffer_sequence_end(buffers_);
+
+ std::advance(next, next_elem_);
+ std::size_t elem_offset = next_elem_offset_;
+ while (next != end && max_size > 0 && result.count < result.max_buffers)
+ {
+ Buffer next_buf = Buffer(*next) + elem_offset;
+ result.elems[result.count] = boost::asio::buffer(next_buf, max_size);
+ max_size -= result.elems[result.count].size();
+ elem_offset = 0;
+ if (result.elems[result.count].size() > 0)
+ ++result.count;
+ ++next;
+ }
+
+ return result;
}
- // Dereference an iterator.
- const Buffer* operator->() const
+ // Consume the specified number of bytes from the buffers.
+ void consume(std::size_t size)
+ {
+ total_consumed_ += size;
+
+ Buffer_Iterator next = boost::asio::buffer_sequence_begin(buffers_);
+ Buffer_Iterator end = boost::asio::buffer_sequence_end(buffers_);
+
+ std::advance(next, next_elem_);
+ while (next != end && size > 0)
+ {
+ Buffer next_buf = Buffer(*next) + next_elem_offset_;
+ if (size < next_buf.size())
+ {
+ next_elem_offset_ += size;
+ size = 0;
+ }
+ else
+ {
+ size -= next_buf.size();
+ next_elem_offset_ = 0;
+ ++next_elem_;
+ ++next;
+ }
+ }
+ }
+
+ // Get the total number of bytes consumed from the buffers.
+ std::size_t total_consumed() const
+ {
+ return total_consumed_;
+ }
+
+private:
+ Buffers buffers_;
+ std::size_t total_size_;
+ std::size_t total_consumed_;
+ std::size_t next_elem_;
+ std::size_t next_elem_offset_;
+};
+
+// Base class of all consuming_buffers specialisations for single buffers.
+template <typename Buffer>
+class consuming_single_buffer
+{
+public:
+ // Construct to represent the entire list of buffers.
+ template <typename Buffer1>
+ explicit consuming_single_buffer(const Buffer1& buffer)
+ : buffer_(buffer),
+ total_consumed_(0)
{
- return &dereference();
}
- // Increment operator (prefix).
- consuming_buffers_iterator& operator++()
+ // Determine if we are at the end of the buffers.
+ bool empty() const
{
- increment();
- return *this;
+ return total_consumed_ >= buffer_.size();
}
- // Increment operator (postfix).
- consuming_buffers_iterator operator++(int)
+ // Get the buffer for a single transfer, with a size.
+ Buffer prepare(std::size_t max_size)
{
- consuming_buffers_iterator tmp(*this);
- ++*this;
- return tmp;
+ return boost::asio::buffer(buffer_ + total_consumed_, max_size);
}
- // Test two iterators for equality.
- friend bool operator==(const consuming_buffers_iterator& a,
- const consuming_buffers_iterator& b)
+ // Consume the specified number of bytes from the buffers.
+ void consume(std::size_t size)
{
- return a.equal(b);
+ total_consumed_ += size;
}
- // Test two iterators for inequality.
- friend bool operator!=(const consuming_buffers_iterator& a,
- const consuming_buffers_iterator& b)
+ // Get the total number of bytes consumed from the buffers.
+ std::size_t total_consumed() const
{
- return !a.equal(b);
+ return total_consumed_;
}
private:
- void increment()
+ Buffer buffer_;
+ std::size_t total_consumed_;
+};
+
+template <>
+class consuming_buffers<mutable_buffer, mutable_buffer, const mutable_buffer*>
+ : public consuming_single_buffer<BOOST_ASIO_MUTABLE_BUFFER>
+{
+public:
+ explicit consuming_buffers(const mutable_buffer& buffer)
+ : consuming_single_buffer<BOOST_ASIO_MUTABLE_BUFFER>(buffer)
{
- if (!at_end_)
- {
- if (begin_remainder_ == end_remainder_
- || offset_ + buffer_size(first_) >= max_size_)
- {
- at_end_ = true;
- }
- else
- {
- offset_ += buffer_size(first_);
- first_ = buffer(*begin_remainder_++, max_size_ - offset_);
- }
- }
}
+};
- bool equal(const consuming_buffers_iterator& other) const
+template <>
+class consuming_buffers<const_buffer, mutable_buffer, const mutable_buffer*>
+ : public consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>
+{
+public:
+ explicit consuming_buffers(const mutable_buffer& buffer)
+ : consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>(buffer)
{
- if (at_end_ && other.at_end_)
- return true;
- return !at_end_ && !other.at_end_
- && buffer_cast<const void*>(first_)
- == buffer_cast<const void*>(other.first_)
- && buffer_size(first_) == buffer_size(other.first_)
- && begin_remainder_ == other.begin_remainder_
- && end_remainder_ == other.end_remainder_;
}
+};
- const Buffer& dereference() const
+template <>
+class consuming_buffers<const_buffer, const_buffer, const const_buffer*>
+ : public consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>
+{
+public:
+ explicit consuming_buffers(const const_buffer& buffer)
+ : consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>(buffer)
{
- return first_;
}
+};
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
- bool at_end_;
- Buffer first_;
- Buffer_Iterator begin_remainder_;
- Buffer_Iterator end_remainder_;
- std::size_t offset_;
- std::size_t max_size_;
+template <>
+class consuming_buffers<mutable_buffer,
+ mutable_buffers_1, const mutable_buffer*>
+ : public consuming_single_buffer<BOOST_ASIO_MUTABLE_BUFFER>
+{
+public:
+ explicit consuming_buffers(const mutable_buffers_1& buffer)
+ : consuming_single_buffer<BOOST_ASIO_MUTABLE_BUFFER>(buffer)
+ {
+ }
};
-// A proxy for a sub-range in a list of buffers.
-template <typename Buffer, typename Buffers>
-class consuming_buffers
+template <>
+class consuming_buffers<const_buffer, mutable_buffers_1, const mutable_buffer*>
+ : public consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>
{
public:
- // The type for each element in the list of buffers.
- typedef Buffer value_type;
+ explicit consuming_buffers(const mutable_buffers_1& buffer)
+ : consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>(buffer)
+ {
+ }
+};
- // A forward-only iterator type that may be used to read elements.
- typedef consuming_buffers_iterator<Buffer, typename Buffers::const_iterator>
- const_iterator;
+template <>
+class consuming_buffers<const_buffer, const_buffers_1, const const_buffer*>
+ : public consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>
+{
+public:
+ explicit consuming_buffers(const const_buffers_1& buffer)
+ : consuming_single_buffer<BOOST_ASIO_CONST_BUFFER>(buffer)
+ {
+ }
+};
+
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+template <typename Buffer, typename Elem>
+class consuming_buffers<Buffer, boost::array<Elem, 2>,
+ typename boost::array<Elem, 2>::const_iterator>
+{
+public:
// Construct to represent the entire list of buffers.
- consuming_buffers(const Buffers& buffers)
+ explicit consuming_buffers(const boost::array<Elem, 2>& buffers)
: buffers_(buffers),
- at_end_(buffers_.begin() == buffers_.end()),
- begin_remainder_(buffers_.begin()),
- max_size_((std::numeric_limits<std::size_t>::max)())
+ total_consumed_(0)
{
- if (!at_end_)
- {
- first_ = *buffers_.begin();
- ++begin_remainder_;
- }
}
- // Copy constructor.
- consuming_buffers(const consuming_buffers& other)
- : buffers_(other.buffers_),
- at_end_(other.at_end_),
- first_(other.first_),
- begin_remainder_(buffers_.begin()),
- max_size_(other.max_size_)
+ // Determine if we are at the end of the buffers.
+ bool empty() const
+ {
+ return total_consumed_ >=
+ Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
+ }
+
+ // Get the buffer for a single transfer, with a size.
+ boost::array<Buffer, 2> prepare(std::size_t max_size)
+ {
+ boost::array<Buffer, 2> result = {{
+ Buffer(buffers_[0]), Buffer(buffers_[1]) }};
+ std::size_t buffer0_size = result[0].size();
+ result[0] = boost::asio::buffer(result[0] + total_consumed_, max_size);
+ result[1] = boost::asio::buffer(
+ result[1] + (total_consumed_ < buffer0_size
+ ? 0 : total_consumed_ - buffer0_size),
+ max_size - result[0].size());
+ return result;
+ }
+
+ // Consume the specified number of bytes from the buffers.
+ void consume(std::size_t size)
{
- typename Buffers::const_iterator first = other.buffers_.begin();
- typename Buffers::const_iterator second = other.begin_remainder_;
- std::advance(begin_remainder_, std::distance(first, second));
+ total_consumed_ += size;
}
- // Assignment operator.
- consuming_buffers& operator=(const consuming_buffers& other)
+ // Get the total number of bytes consumed from the buffers.
+ std::size_t total_consumed() const
{
- buffers_ = other.buffers_;
- at_end_ = other.at_end_;
- first_ = other.first_;
- begin_remainder_ = buffers_.begin();
- typename Buffers::const_iterator first = other.buffers_.begin();
- typename Buffers::const_iterator second = other.begin_remainder_;
- std::advance(begin_remainder_, std::distance(first, second));
- max_size_ = other.max_size_;
- return *this;
+ return total_consumed_;
}
- // Get a forward-only iterator to the first element.
- const_iterator begin() const
+private:
+ boost::array<Elem, 2> buffers_;
+ std::size_t total_consumed_;
+};
+
+#if defined(BOOST_ASIO_HAS_STD_ARRAY)
+
+template <typename Buffer, typename Elem>
+class consuming_buffers<Buffer, std::array<Elem, 2>,
+ typename std::array<Elem, 2>::const_iterator>
+{
+public:
+ // Construct to represent the entire list of buffers.
+ explicit consuming_buffers(const std::array<Elem, 2>& buffers)
+ : buffers_(buffers),
+ total_consumed_(0)
{
- return const_iterator(at_end_, first_,
- begin_remainder_, buffers_.end(), max_size_);
}
- // Get a forward-only iterator for one past the last element.
- const_iterator end() const
+ // Determine if we are at the end of the buffers.
+ bool empty() const
{
- return const_iterator();
+ return total_consumed_ >=
+ Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();
}
- // Set the maximum size for a single transfer.
- void prepare(std::size_t max_size)
+ // Get the buffer for a single transfer, with a size.
+ std::array<Buffer, 2> prepare(std::size_t max_size)
{
- max_size_ = max_size;
+ std::array<Buffer, 2> result = {{
+ Buffer(buffers_[0]), Buffer(buffers_[1]) }};
+ std::size_t buffer0_size = result[0].size();
+ result[0] = boost::asio::buffer(result[0] + total_consumed_, max_size);
+ result[1] = boost::asio::buffer(
+ result[1] + (total_consumed_ < buffer0_size
+ ? 0 : total_consumed_ - buffer0_size),
+ max_size - result[0].size());
+ return result;
}
// Consume the specified number of bytes from the buffers.
void consume(std::size_t size)
{
- // Remove buffers from the start until the specified size is reached.
- while (size > 0 && !at_end_)
- {
- if (buffer_size(first_) <= size)
- {
- size -= buffer_size(first_);
- if (begin_remainder_ == buffers_.end())
- at_end_ = true;
- else
- first_ = *begin_remainder_++;
- }
- else
- {
- first_ = first_ + size;
- size = 0;
- }
- }
+ total_consumed_ += size;
+ }
- // Remove any more empty buffers at the start.
- while (!at_end_ && buffer_size(first_) == 0)
- {
- if (begin_remainder_ == buffers_.end())
- at_end_ = true;
- else
- first_ = *begin_remainder_++;
- }
+ // Get the total number of bytes consumed from the buffers.
+ std::size_t total_consumed() const
+ {
+ return total_consumed_;
}
private:
- Buffers buffers_;
- bool at_end_;
- Buffer first_;
- typename Buffers::const_iterator begin_remainder_;
- std::size_t max_size_;
+ std::array<Elem, 2> buffers_;
+ std::size_t total_consumed_;
};
+#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
+
// Specialisation for null_buffers to ensure that the null_buffers type is
// always passed through to the underlying read or write operation.
template <typename Buffer>
-class consuming_buffers<Buffer, boost::asio::null_buffers>
+class consuming_buffers<Buffer, null_buffers, const mutable_buffer*>
: public boost::asio::null_buffers
{
public:
- consuming_buffers(const boost::asio::null_buffers&)
+ consuming_buffers(const null_buffers&)
{
// No-op.
}
- void prepare(std::size_t)
+ bool empty()
{
- // No-op.
+ return false;
+ }
+
+ null_buffers prepare(std::size_t)
+ {
+ return null_buffers();
}
void consume(std::size_t)
{
// No-op.
}
+
+ std::size_t total_consume() const
+ {
+ return 0;
+ }
};
} // namespace detail
diff --git a/boost/asio/detail/cstddef.hpp b/boost/asio/detail/cstddef.hpp
new file mode 100644
index 0000000000..a6dacc1de4
--- /dev/null
+++ b/boost/asio/detail/cstddef.hpp
@@ -0,0 +1,33 @@
+//
+// detail/cstddef.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_CSTDDEF_HPP
+#define BOOST_ASIO_DETAIL_CSTDDEF_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+
+namespace boost {
+namespace asio {
+
+#if defined(BOOST_ASIO_HAS_NULLPTR)
+using std::nullptr_t;
+#else // defined(BOOST_ASIO_HAS_NULLPTR)
+struct nullptr_t {};
+#endif // defined(BOOST_ASIO_HAS_NULLPTR)
+
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_CSTDDEF_HPP
diff --git a/boost/asio/detail/cstdint.hpp b/boost/asio/detail/cstdint.hpp
index a1be0dced0..61627c7ed3 100644
--- a/boost/asio/detail/cstdint.hpp
+++ b/boost/asio/detail/cstdint.hpp
@@ -28,18 +28,32 @@ namespace asio {
#if defined(BOOST_ASIO_HAS_CSTDINT)
using std::int16_t;
+using std::int_least16_t;
using std::uint16_t;
+using std::uint_least16_t;
using std::int32_t;
+using std::int_least32_t;
using std::uint32_t;
+using std::uint_least32_t;
using std::int64_t;
+using std::int_least64_t;
using std::uint64_t;
+using std::uint_least64_t;
+using std::uintmax_t;
#else // defined(BOOST_ASIO_HAS_CSTDINT)
using boost::int16_t;
+using boost::int_least16_t;
using boost::uint16_t;
+using boost::uint_least16_t;
using boost::int32_t;
+using boost::int_least32_t;
using boost::uint32_t;
+using boost::uint_least32_t;
using boost::int64_t;
+using boost::int_least64_t;
using boost::uint64_t;
+using boost::uint_least64_t;
+using boost::uintmax_t;
#endif // defined(BOOST_ASIO_HAS_CSTDINT)
} // namespace asio
diff --git a/boost/asio/detail/deadline_timer_service.hpp b/boost/asio/detail/deadline_timer_service.hpp
index bbd5358425..bc17eb288c 100644
--- a/boost/asio/detail/deadline_timer_service.hpp
+++ b/boost/asio/detail/deadline_timer_service.hpp
@@ -18,14 +18,15 @@
#include <boost/asio/detail/config.hpp>
#include <cstddef>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/timer_queue.hpp>
+#include <boost/asio/detail/timer_queue_ptime.hpp>
#include <boost/asio/detail/timer_scheduler.hpp>
#include <boost/asio/detail/wait_handler.hpp>
#include <boost/asio/detail/wait_op.hpp>
@@ -43,6 +44,7 @@ namespace detail {
template <typename Time_Traits>
class deadline_timer_service
+ : public service_base<deadline_timer_service<Time_Traits> >
{
public:
// The time type.
@@ -62,8 +64,9 @@ public:
};
// Constructor.
- deadline_timer_service(boost::asio::io_service& io_service)
- : scheduler_(boost::asio::use_service<timer_scheduler>(io_service))
+ deadline_timer_service(boost::asio::io_context& io_context)
+ : service_base<deadline_timer_service<Time_Traits> >(io_context),
+ scheduler_(boost::asio::use_service<timer_scheduler>(io_context))
{
scheduler_.init_task();
scheduler_.add_timer_queue(timer_queue_);
@@ -76,7 +79,7 @@ public:
}
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
}
@@ -94,6 +97,38 @@ public:
cancel(impl, ec);
}
+ // Move-construct a new serial port implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ scheduler_.move_timer(timer_queue_, impl.timer_data, other_impl.timer_data);
+
+ impl.expiry = other_impl.expiry;
+ other_impl.expiry = time_type();
+
+ impl.might_have_pending_waits = other_impl.might_have_pending_waits;
+ other_impl.might_have_pending_waits = false;
+ }
+
+ // Move-assign from another serial port implementation.
+ void move_assign(implementation_type& impl,
+ deadline_timer_service& other_service,
+ implementation_type& other_impl)
+ {
+ if (this != &other_service)
+ if (impl.might_have_pending_waits)
+ scheduler_.cancel_timer(timer_queue_, impl.timer_data);
+
+ other_service.scheduler_.move_timer(other_service.timer_queue_,
+ impl.timer_data, other_impl.timer_data);
+
+ impl.expiry = other_impl.expiry;
+ other_impl.expiry = time_type();
+
+ impl.might_have_pending_waits = other_impl.might_have_pending_waits;
+ other_impl.might_have_pending_waits = false;
+ }
+
// Cancel any asynchronous wait operations associated with the timer.
std::size_t cancel(implementation_type& impl, boost::system::error_code& ec)
{
@@ -103,7 +138,8 @@ public:
return 0;
}
- BOOST_ASIO_HANDLER_OPERATION(("deadline_timer", &impl, "cancel"));
+ BOOST_ASIO_HANDLER_OPERATION((scheduler_.context(),
+ "deadline_timer", &impl, 0, "cancel"));
std::size_t count = scheduler_.cancel_timer(timer_queue_, impl.timer_data);
impl.might_have_pending_waits = false;
@@ -121,7 +157,8 @@ public:
return 0;
}
- BOOST_ASIO_HANDLER_OPERATION(("deadline_timer", &impl, "cancel_one"));
+ BOOST_ASIO_HANDLER_OPERATION((scheduler_.context(),
+ "deadline_timer", &impl, 0, "cancel_one"));
std::size_t count = scheduler_.cancel_timer(
timer_queue_, impl.timer_data, 1);
@@ -132,11 +169,23 @@ public:
}
// Get the expiry time for the timer as an absolute time.
+ time_type expiry(const implementation_type& impl) const
+ {
+ return impl.expiry;
+ }
+
+ // Get the expiry time for the timer as an absolute time.
time_type expires_at(const implementation_type& impl) const
{
return impl.expiry;
}
+ // Get the expiry time for the timer relative to now.
+ duration_type expires_from_now(const implementation_type& impl) const
+ {
+ return Time_Traits::subtract(this->expiry(impl), Time_Traits::now());
+ }
+
// Set the expiry time for the timer as an absolute time.
std::size_t expires_at(implementation_type& impl,
const time_type& expiry_time, boost::system::error_code& ec)
@@ -147,10 +196,12 @@ public:
return count;
}
- // Get the expiry time for the timer relative to now.
- duration_type expires_from_now(const implementation_type& impl) const
+ // Set the expiry time for the timer relative to now.
+ std::size_t expires_after(implementation_type& impl,
+ const duration_type& expiry_time, boost::system::error_code& ec)
{
- return Time_Traits::subtract(expires_at(impl), Time_Traits::now());
+ return expires_at(impl,
+ Time_Traits::add(Time_Traits::now(), expiry_time), ec);
}
// Set the expiry time for the timer relative to now.
@@ -181,13 +232,13 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef wait_handler<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
impl.might_have_pending_waits = true;
- BOOST_ASIO_HANDLER_CREATION((p.p, "deadline_timer", &impl, "async_wait"));
+ BOOST_ASIO_HANDLER_CREATION((scheduler_.context(),
+ *p.p, "deadline_timer", &impl, 0, "async_wait"));
scheduler_.schedule_timer(timer_queue_, impl.expiry, impl.timer_data, p.p);
p.v = p.p = 0;
diff --git a/boost/asio/detail/descriptor_ops.hpp b/boost/asio/detail/descriptor_ops.hpp
index 62100392da..5c1ce20d9c 100644
--- a/boost/asio/detail/descriptor_ops.hpp
+++ b/boost/asio/detail/descriptor_ops.hpp
@@ -22,6 +22,7 @@
&& !defined(__CYGWIN__)
#include <cstddef>
+#include <boost/asio/error.hpp>
#include <boost/system/error_code.hpp>
#include <boost/asio/detail/socket_types.hpp>
@@ -101,6 +102,9 @@ BOOST_ASIO_DECL int poll_read(int d,
BOOST_ASIO_DECL int poll_write(int d,
state_type state, boost::system::error_code& ec);
+BOOST_ASIO_DECL int poll_error(int d,
+ state_type state, boost::system::error_code& ec);
+
} // namespace descriptor_ops
} // namespace detail
} // namespace asio
diff --git a/boost/asio/detail/descriptor_read_op.hpp b/boost/asio/detail/descriptor_read_op.hpp
index ddbdf7d3e5..1ca2d236fe 100644
--- a/boost/asio/detail/descriptor_read_op.hpp
+++ b/boost/asio/detail/descriptor_read_op.hpp
@@ -19,11 +19,12 @@
#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/descriptor_ops.hpp>
#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/handler_work.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -44,15 +45,21 @@ public:
{
}
- static bool do_perform(reactor_op* base)
+ static status do_perform(reactor_op* base)
{
descriptor_read_op_base* o(static_cast<descriptor_read_op_base*>(base));
buffer_sequence_adapter<boost::asio::mutable_buffer,
MutableBufferSequence> bufs(o->buffers_);
- return descriptor_ops::non_blocking_read(o->descriptor_,
- bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_);
+ status result = descriptor_ops::non_blocking_read(o->descriptor_,
+ bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_)
+ ? done : not_done;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_read",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
}
private:
@@ -73,17 +80,19 @@ public:
descriptor, buffers, &descriptor_read_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
descriptor_read_op* o(static_cast<descriptor_read_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -101,7 +110,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/descriptor_write_op.hpp b/boost/asio/detail/descriptor_write_op.hpp
index f635feb122..0063491742 100644
--- a/boost/asio/detail/descriptor_write_op.hpp
+++ b/boost/asio/detail/descriptor_write_op.hpp
@@ -19,11 +19,12 @@
#if !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/descriptor_ops.hpp>
#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/handler_work.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -44,15 +45,21 @@ public:
{
}
- static bool do_perform(reactor_op* base)
+ static status do_perform(reactor_op* base)
{
descriptor_write_op_base* o(static_cast<descriptor_write_op_base*>(base));
buffer_sequence_adapter<boost::asio::const_buffer,
ConstBufferSequence> bufs(o->buffers_);
- return descriptor_ops::non_blocking_write(o->descriptor_,
- bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_);
+ status result = descriptor_ops::non_blocking_write(o->descriptor_,
+ bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_)
+ ? done : not_done;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_write",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
}
private:
@@ -73,17 +80,19 @@ public:
descriptor, buffers, &descriptor_write_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
descriptor_write_op* o(static_cast<descriptor_write_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -101,7 +110,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/dev_poll_reactor.hpp b/boost/asio/detail/dev_poll_reactor.hpp
index 17f57d5221..805f44b6ee 100644
--- a/boost/asio/detail/dev_poll_reactor.hpp
+++ b/boost/asio/detail/dev_poll_reactor.hpp
@@ -33,7 +33,7 @@
#include <boost/asio/detail/timer_queue_base.hpp>
#include <boost/asio/detail/timer_queue_set.hpp>
#include <boost/asio/detail/wait_op.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/execution_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -42,7 +42,7 @@ namespace asio {
namespace detail {
class dev_poll_reactor
- : public boost::asio::detail::service_base<dev_poll_reactor>
+ : public execution_context_service_base<dev_poll_reactor>
{
public:
enum op_types { read_op = 0, write_op = 1,
@@ -54,17 +54,17 @@ public:
};
// Constructor.
- BOOST_ASIO_DECL dev_poll_reactor(boost::asio::io_service& io_service);
+ BOOST_ASIO_DECL dev_poll_reactor(boost::asio::execution_context& ctx);
// Destructor.
BOOST_ASIO_DECL ~dev_poll_reactor();
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Recreate internal descriptors following a fork.
- BOOST_ASIO_DECL void fork_service(
- boost::asio::io_service::fork_event fork_ev);
+ BOOST_ASIO_DECL void notify_fork(
+ boost::asio::execution_context::fork_event fork_ev);
// Initialise the task.
BOOST_ASIO_DECL void init_task();
@@ -87,7 +87,7 @@ public:
// Post a reactor operation for immediate completion.
void post_immediate_completion(reactor_op* op, bool is_continuation)
{
- io_service_.post_immediate_completion(op, is_continuation);
+ scheduler_.post_immediate_completion(op, is_continuation);
}
// Start a new operation. The reactor operation will be performed when the
@@ -139,8 +139,14 @@ public:
typename timer_queue<Time_Traits>::per_timer_data& timer,
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
+ // 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);
+
// Run /dev/poll once until interrupted or events are ready to be dispatched.
- BOOST_ASIO_DECL void run(bool block, op_queue<operation>& ops);
+ BOOST_ASIO_DECL void run(long usec, op_queue<operation>& ops);
// Interrupt the select loop.
BOOST_ASIO_DECL void interrupt();
@@ -159,7 +165,7 @@ private:
// Get the timeout value for the /dev/poll DP_POLL operation. The timeout
// value is returned as a number of milliseconds. A return value of -1
// indicates that the poll should block indefinitely.
- BOOST_ASIO_DECL int get_timeout();
+ BOOST_ASIO_DECL int get_timeout(int msec);
// Cancel all operations associated with the given descriptor. The do_cancel
// function of the handler objects will be invoked. This function does not
@@ -170,8 +176,8 @@ private:
// Add a pending event entry for the given descriptor.
BOOST_ASIO_DECL ::pollfd& add_pending_event_change(int descriptor);
- // The io_service implementation used to post completions.
- io_service_impl& io_service_;
+ // The scheduler implementation used to post completions.
+ scheduler& scheduler_;
// Mutex to protect access to internal data.
boost::asio::detail::mutex mutex_;
diff --git a/boost/asio/detail/epoll_reactor.hpp b/boost/asio/detail/epoll_reactor.hpp
index 34ed0370f5..e1acb48da7 100644
--- a/boost/asio/detail/epoll_reactor.hpp
+++ b/boost/asio/detail/epoll_reactor.hpp
@@ -19,10 +19,9 @@
#if defined(BOOST_ASIO_HAS_EPOLL)
-#include <boost/asio/io_service.hpp>
#include <boost/asio/detail/atomic_count.hpp>
+#include <boost/asio/detail/conditionally_enabled_mutex.hpp>
#include <boost/asio/detail/limits.hpp>
-#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/object_pool.hpp>
#include <boost/asio/detail/op_queue.hpp>
#include <boost/asio/detail/reactor_op.hpp>
@@ -31,6 +30,7 @@
#include <boost/asio/detail/timer_queue_base.hpp>
#include <boost/asio/detail/timer_queue_set.hpp>
#include <boost/asio/detail/wait_op.hpp>
+#include <boost/asio/execution_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -39,8 +39,12 @@ namespace asio {
namespace detail {
class epoll_reactor
- : public boost::asio::detail::service_base<epoll_reactor>
+ : public execution_context_service_base<epoll_reactor>
{
+private:
+ // The mutex type used by this reactor.
+ typedef conditionally_enabled_mutex mutex;
+
public:
enum op_types { read_op = 0, write_op = 1,
connect_op = 1, except_op = 2, max_ops = 3 };
@@ -59,14 +63,15 @@ public:
int descriptor_;
uint32_t registered_events_;
op_queue<reactor_op> op_queue_[max_ops];
+ bool try_speculative_[max_ops];
bool shutdown_;
- BOOST_ASIO_DECL descriptor_state();
+ BOOST_ASIO_DECL descriptor_state(bool locking);
void set_ready_events(uint32_t events) { task_result_ = events; }
void add_ready_events(uint32_t events) { task_result_ |= events; }
BOOST_ASIO_DECL operation* perform_io(uint32_t events);
BOOST_ASIO_DECL static void do_complete(
- io_service_impl* owner, operation* base,
+ void* owner, operation* base,
const boost::system::error_code& ec, std::size_t bytes_transferred);
};
@@ -74,17 +79,17 @@ public:
typedef descriptor_state* per_descriptor_data;
// Constructor.
- BOOST_ASIO_DECL epoll_reactor(boost::asio::io_service& io_service);
+ BOOST_ASIO_DECL epoll_reactor(boost::asio::execution_context& ctx);
// Destructor.
BOOST_ASIO_DECL ~epoll_reactor();
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Recreate internal descriptors following a fork.
- BOOST_ASIO_DECL void fork_service(
- boost::asio::io_service::fork_event fork_ev);
+ BOOST_ASIO_DECL void notify_fork(
+ boost::asio::execution_context::fork_event fork_ev);
// Initialise the task.
BOOST_ASIO_DECL void init_task();
@@ -108,7 +113,7 @@ public:
// Post a reactor operation for immediate completion.
void post_immediate_completion(reactor_op* op, bool is_continuation)
{
- io_service_.post_immediate_completion(op, is_continuation);
+ scheduler_.post_immediate_completion(op, is_continuation);
}
// Start a new operation. The reactor operation will be performed when the
@@ -162,8 +167,14 @@ public:
typename timer_queue<Time_Traits>::per_timer_data& timer,
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
+ // 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);
+
// Run epoll once until interrupted or events are ready to be dispatched.
- BOOST_ASIO_DECL void run(bool block, op_queue<operation>& ops);
+ BOOST_ASIO_DECL void run(long usec, op_queue<operation>& ops);
// Interrupt the select loop.
BOOST_ASIO_DECL void interrupt();
@@ -197,7 +208,7 @@ private:
// Get the timeout value for the epoll_wait call. The timeout value is
// returned as a number of milliseconds. A return value of -1 indicates
// that epoll_wait should block indefinitely.
- BOOST_ASIO_DECL int get_timeout();
+ BOOST_ASIO_DECL int get_timeout(int msec);
#if defined(BOOST_ASIO_HAS_TIMERFD)
// Get the timeout value for the timer descriptor. The return value is the
@@ -205,8 +216,8 @@ private:
BOOST_ASIO_DECL int get_timeout(itimerspec& ts);
#endif // defined(BOOST_ASIO_HAS_TIMERFD)
- // The io_service implementation used to post completions.
- io_service_impl& io_service_;
+ // The scheduler implementation used to post completions.
+ scheduler& scheduler_;
// Mutex to protect access to internal data.
mutex mutex_;
diff --git a/boost/asio/detail/executor_op.hpp b/boost/asio/detail/executor_op.hpp
new file mode 100644
index 0000000000..f3364f5155
--- /dev/null
+++ b/boost/asio/detail/executor_op.hpp
@@ -0,0 +1,86 @@
+//
+// detail/executor_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_EXECUTOR_OP_HPP
+#define BOOST_ASIO_DETAIL_EXECUTOR_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/scheduler_operation.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Handler, typename Alloc,
+ typename Operation = scheduler_operation>
+class executor_op : public Operation
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(executor_op);
+
+ template <typename H>
+ executor_op(BOOST_ASIO_MOVE_ARG(H) h, const Alloc& allocator)
+ : Operation(&executor_op::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(H)(h)),
+ allocator_(allocator)
+ {
+ }
+
+ static void do_complete(void* owner, Operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ executor_op* o(static_cast<executor_op*>(base));
+ Alloc allocator(o->allocator_);
+ ptr p = { detail::addressof(allocator), o, o };
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // 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.
+ Handler handler(BOOST_ASIO_MOVE_CAST(Handler)(o->handler_));
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN(());
+ boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+ Alloc allocator_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_EXECUTOR_OP_HPP
diff --git a/boost/asio/detail/function.hpp b/boost/asio/detail/functional.hpp
index db26144c5f..a7d6064e4a 100644
--- a/boost/asio/detail/function.hpp
+++ b/boost/asio/detail/functional.hpp
@@ -1,6 +1,6 @@
//
-// detail/function.hpp
-// ~~~~~~~~~~~~~~~~~~~
+// detail/functional.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
@@ -8,8 +8,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_ASIO_DETAIL_FUNCTION_HPP
-#define BOOST_ASIO_DETAIL_FUNCTION_HPP
+#ifndef BOOST_ASIO_DETAIL_FUNCTIONAL_HPP
+#define BOOST_ASIO_DETAIL_FUNCTIONAL_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
@@ -17,11 +17,11 @@
#include <boost/asio/detail/config.hpp>
-#if defined(BOOST_ASIO_HAS_STD_FUNCTION)
-# include <functional>
-#else // defined(BOOST_ASIO_HAS_STD_FUNCTION)
+#include <functional>
+
+#if !defined(BOOST_ASIO_HAS_STD_FUNCTION)
# include <boost/function.hpp>
-#endif // defined(BOOST_ASIO_HAS_STD_FUNCTION)
+#endif // !defined(BOOST_ASIO_HAS_STD_FUNCTION)
namespace boost {
namespace asio {
@@ -37,4 +37,4 @@ using boost::function;
} // namespace asio
} // namespace boost
-#endif // BOOST_ASIO_DETAIL_FUNCTION_HPP
+#endif // BOOST_ASIO_DETAIL_FUNCTIONAL_HPP
diff --git a/boost/asio/detail/gcc_arm_fenced_block.hpp b/boost/asio/detail/gcc_arm_fenced_block.hpp
index b4805c35cd..51a8ca7c55 100644
--- a/boost/asio/detail/gcc_arm_fenced_block.hpp
+++ b/boost/asio/detail/gcc_arm_fenced_block.hpp
@@ -19,6 +19,8 @@
#if defined(__GNUC__) && defined(__arm__)
+#include <boost/asio/detail/noncopyable.hpp>
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
diff --git a/boost/asio/detail/gcc_hppa_fenced_block.hpp b/boost/asio/detail/gcc_hppa_fenced_block.hpp
index b9aa9e2ca4..95f47ac8eb 100644
--- a/boost/asio/detail/gcc_hppa_fenced_block.hpp
+++ b/boost/asio/detail/gcc_hppa_fenced_block.hpp
@@ -19,6 +19,8 @@
#if defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))
+#include <boost/asio/detail/noncopyable.hpp>
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
diff --git a/boost/asio/detail/gcc_sync_fenced_block.hpp b/boost/asio/detail/gcc_sync_fenced_block.hpp
index e8e6c54643..b9026b1206 100644
--- a/boost/asio/detail/gcc_sync_fenced_block.hpp
+++ b/boost/asio/detail/gcc_sync_fenced_block.hpp
@@ -22,6 +22,8 @@
&& !defined(__INTEL_COMPILER) && !defined(__ICL) \
&& !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)
+#include <boost/asio/detail/noncopyable.hpp>
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
diff --git a/boost/asio/detail/gcc_x86_fenced_block.hpp b/boost/asio/detail/gcc_x86_fenced_block.hpp
index fe0ce8a316..be355a115a 100644
--- a/boost/asio/detail/gcc_x86_fenced_block.hpp
+++ b/boost/asio/detail/gcc_x86_fenced_block.hpp
@@ -19,6 +19,8 @@
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+#include <boost/asio/detail/noncopyable.hpp>
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
diff --git a/boost/asio/detail/global.hpp b/boost/asio/detail/global.hpp
new file mode 100644
index 0000000000..581478909f
--- /dev/null
+++ b/boost/asio/detail/global.hpp
@@ -0,0 +1,54 @@
+//
+// detail/global.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_GLOBAL_HPP
+#define BOOST_ASIO_DETAIL_GLOBAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_HAS_THREADS)
+# include <boost/asio/detail/null_global.hpp>
+#elif defined(BOOST_ASIO_WINDOWS)
+# include <boost/asio/detail/win_global.hpp>
+#elif defined(BOOST_ASIO_HAS_PTHREADS)
+# include <boost/asio/detail/posix_global.hpp>
+#elif defined(BOOST_ASIO_HAS_STD_CALL_ONCE)
+# include <boost/asio/detail/std_global.hpp>
+#else
+# error Only Windows, POSIX and std::call_once are supported!
+#endif
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+inline T& global()
+{
+#if !defined(BOOST_ASIO_HAS_THREADS)
+ return null_global<T>();
+#elif defined(BOOST_ASIO_WINDOWS)
+ return win_global<T>();
+#elif defined(BOOST_ASIO_HAS_PTHREADS)
+ return posix_global<T>();
+#elif defined(BOOST_ASIO_HAS_STD_CALL_ONCE)
+ return std_global<T>();
+#endif
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_GLOBAL_HPP
diff --git a/boost/asio/detail/handler_alloc_helpers.hpp b/boost/asio/detail/handler_alloc_helpers.hpp
index a03cb41976..ee2e80c81d 100644
--- a/boost/asio/detail/handler_alloc_helpers.hpp
+++ b/boost/asio/detail/handler_alloc_helpers.hpp
@@ -16,8 +16,10 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/recycling_allocator.hpp>
+#include <boost/asio/associated_allocator.hpp>
#include <boost/asio/handler_alloc_hook.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -51,16 +53,165 @@ inline void deallocate(void* p, std::size_t s, Handler& h)
} // namespace boost_asio_handler_alloc_helpers
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Handler, typename T>
+class hook_allocator
+{
+public:
+ typedef T value_type;
+
+ template <typename U>
+ struct rebind
+ {
+ typedef hook_allocator<Handler, U> other;
+ };
+
+ explicit hook_allocator(Handler& h)
+ : handler_(h)
+ {
+ }
+
+ template <typename U>
+ hook_allocator(const hook_allocator<Handler, U>& a)
+ : handler_(a.handler_)
+ {
+ }
+
+ T* allocate(std::size_t n)
+ {
+ return static_cast<T*>(
+ boost_asio_handler_alloc_helpers::allocate(sizeof(T) * n, handler_));
+ }
+
+ void deallocate(T* p, std::size_t n)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(p, sizeof(T) * n, handler_);
+ }
+
+//private:
+ Handler& handler_;
+};
+
+template <typename Handler>
+class hook_allocator<Handler, void>
+{
+public:
+ typedef void value_type;
+
+ template <typename U>
+ struct rebind
+ {
+ typedef hook_allocator<Handler, U> other;
+ };
+
+ explicit hook_allocator(Handler& h)
+ : handler_(h)
+ {
+ }
+
+ template <typename U>
+ hook_allocator(const hook_allocator<Handler, U>& a)
+ : handler_(a.handler_)
+ {
+ }
+
+//private:
+ Handler& handler_;
+};
+
+template <typename Handler, typename Allocator>
+struct get_hook_allocator
+{
+ typedef Allocator type;
+
+ static type get(Handler&, const Allocator& a)
+ {
+ return a;
+ }
+};
+
+template <typename Handler, typename T>
+struct get_hook_allocator<Handler, std::allocator<T> >
+{
+ typedef hook_allocator<Handler, T> type;
+
+ static type get(Handler& handler, const std::allocator<T>&)
+ {
+ return type(handler);
+ }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
#define BOOST_ASIO_DEFINE_HANDLER_PTR(op) \
struct ptr \
{ \
Handler* h; \
+ op* v; \
+ op* p; \
+ ~ptr() \
+ { \
+ reset(); \
+ } \
+ static op* allocate(Handler& handler) \
+ { \
+ typedef typename ::boost::asio::associated_allocator< \
+ Handler>::type associated_allocator_type; \
+ typedef typename ::boost::asio::detail::get_hook_allocator< \
+ Handler, associated_allocator_type>::type hook_allocator_type; \
+ BOOST_ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \
+ ::boost::asio::detail::get_hook_allocator< \
+ Handler, associated_allocator_type>::get( \
+ handler, ::boost::asio::get_associated_allocator(handler))); \
+ return a.allocate(1); \
+ } \
+ void reset() \
+ { \
+ if (p) \
+ { \
+ p->~op(); \
+ p = 0; \
+ } \
+ if (v) \
+ { \
+ typedef typename ::boost::asio::associated_allocator< \
+ Handler>::type associated_allocator_type; \
+ typedef typename ::boost::asio::detail::get_hook_allocator< \
+ Handler, associated_allocator_type>::type hook_allocator_type; \
+ BOOST_ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \
+ ::boost::asio::detail::get_hook_allocator< \
+ Handler, associated_allocator_type>::get( \
+ *h, ::boost::asio::get_associated_allocator(*h))); \
+ a.deallocate(static_cast<op*>(v), 1); \
+ v = 0; \
+ } \
+ } \
+ } \
+ /**/
+
+#define BOOST_ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op) \
+ struct ptr \
+ { \
+ const Alloc* a; \
void* v; \
op* p; \
~ptr() \
{ \
reset(); \
} \
+ static op* allocate(const Alloc& a) \
+ { \
+ typedef typename ::boost::asio::detail::get_recycling_allocator< \
+ Alloc>::type recycling_allocator_type; \
+ BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
+ ::boost::asio::detail::get_recycling_allocator<Alloc>::get(a)); \
+ return a1.allocate(1); \
+ } \
void reset() \
{ \
if (p) \
@@ -70,7 +221,11 @@ inline void deallocate(void* p, std::size_t s, Handler& h)
} \
if (v) \
{ \
- boost_asio_handler_alloc_helpers::deallocate(v, sizeof(op), *h); \
+ typedef typename ::boost::asio::detail::get_recycling_allocator< \
+ Alloc>::type recycling_allocator_type; \
+ BOOST_ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \
+ ::boost::asio::detail::get_recycling_allocator<Alloc>::get(*a)); \
+ a1.deallocate(static_cast<op*>(v), 1); \
v = 0; \
} \
} \
diff --git a/boost/asio/detail/handler_cont_helpers.hpp b/boost/asio/detail/handler_cont_helpers.hpp
index 9a361a9ca4..a47ecf2d4a 100644
--- a/boost/asio/detail/handler_cont_helpers.hpp
+++ b/boost/asio/detail/handler_cont_helpers.hpp
@@ -16,7 +16,7 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/handler_continuation_hook.hpp>
#include <boost/asio/detail/push_options.hpp>
diff --git a/boost/asio/detail/handler_invoke_helpers.hpp b/boost/asio/detail/handler_invoke_helpers.hpp
index 43f74f3272..290ecb194f 100644
--- a/boost/asio/detail/handler_invoke_helpers.hpp
+++ b/boost/asio/detail/handler_invoke_helpers.hpp
@@ -16,7 +16,7 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/handler_invoke_hook.hpp>
#include <boost/asio/detail/push_options.hpp>
diff --git a/boost/asio/detail/handler_tracking.hpp b/boost/asio/detail/handler_tracking.hpp
index fd69bdd5b6..92e8a469f1 100644
--- a/boost/asio/detail/handler_tracking.hpp
+++ b/boost/asio/detail/handler_tracking.hpp
@@ -17,7 +17,17 @@
#include <boost/asio/detail/config.hpp>
-#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+namespace boost {
+namespace asio {
+
+class execution_context;
+
+} // namespace asio
+} // namespace boost
+
+#if defined(BOOST_ASIO_CUSTOM_HANDLER_TRACKING)
+# include BOOST_ASIO_CUSTOM_HANDLER_TRACKING
+#elif defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
# include <boost/system/error_code.hpp>
# include <boost/asio/detail/cstdint.hpp>
# include <boost/asio/detail/static_mutex.hpp>
@@ -30,7 +40,30 @@ namespace boost {
namespace asio {
namespace detail {
-#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+#if defined(BOOST_ASIO_CUSTOM_HANDLER_TRACKING)
+
+// The user-specified header must define the following macros:
+// - BOOST_ASIO_INHERIT_TRACKED_HANDLER
+// - BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER
+// - BOOST_ASIO_HANDLER_TRACKING_INIT
+// - BOOST_ASIO_HANDLER_CREATION(args)
+// - BOOST_ASIO_HANDLER_COMPLETION(args)
+// - BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args)
+// - BOOST_ASIO_HANDLER_INVOCATION_END
+// - BOOST_ASIO_HANDLER_OPERATION(args)
+// - BOOST_ASIO_HANDLER_REACTOR_REGISTRATION(args)
+// - BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION(args)
+// - BOOST_ASIO_HANDLER_REACTOR_READ_EVENT
+// - BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT
+// - BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT
+// - BOOST_ASIO_HANDLER_REACTOR_EVENTS(args)
+// - BOOST_ASIO_HANDLER_REACTOR_OPERATION(args)
+
+# if !defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+# define BOOST_ASIO_ENABLE_HANDLER_TRACKING 1
+# endif /// !defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+
+#elif defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
class handler_tracking
{
@@ -58,14 +91,16 @@ public:
BOOST_ASIO_DECL static void init();
// Record the creation of a tracked handler.
- BOOST_ASIO_DECL static void creation(tracked_handler* h,
- const char* object_type, void* object, const char* op_name);
+ BOOST_ASIO_DECL static void creation(
+ execution_context& context, tracked_handler& h,
+ const char* object_type, void* object,
+ uintmax_t native_handle, const char* op_name);
class completion
{
public:
// Constructor records that handler is to be invoked with no arguments.
- BOOST_ASIO_DECL explicit completion(tracked_handler* h);
+ BOOST_ASIO_DECL explicit completion(const tracked_handler& h);
// Destructor records only when an exception is thrown from the handler, or
// if the memory is being freed without the handler having been invoked.
@@ -99,9 +134,32 @@ public:
completion* next_;
};
- // Record an operation that affects pending handlers.
- BOOST_ASIO_DECL static void operation(const char* object_type,
- void* object, const char* op_name);
+ // Record an operation that is not directly associated with a handler.
+ BOOST_ASIO_DECL static void operation(execution_context& context,
+ const char* object_type, void* object,
+ uintmax_t native_handle, const char* op_name);
+
+ // Record that a descriptor has been registered with the reactor.
+ BOOST_ASIO_DECL static void reactor_registration(execution_context& context,
+ uintmax_t native_handle, uintmax_t registration);
+
+ // Record that a descriptor has been deregistered from the reactor.
+ BOOST_ASIO_DECL static void reactor_deregistration(execution_context& context,
+ uintmax_t native_handle, uintmax_t registration);
+
+ // Record a reactor-based operation that is associated with a handler.
+ BOOST_ASIO_DECL static void reactor_events(execution_context& context,
+ uintmax_t registration, unsigned events);
+
+ // Record a reactor-based operation that is associated with a handler.
+ BOOST_ASIO_DECL static void reactor_operation(
+ const tracked_handler& h, const char* op_name,
+ const boost::system::error_code& ec);
+
+ // Record a reactor-based operation that is associated with a handler.
+ BOOST_ASIO_DECL static void reactor_operation(
+ const tracked_handler& h, const char* op_name,
+ const boost::system::error_code& ec, std::size_t bytes_transferred);
// Write a line of output.
BOOST_ASIO_DECL static void write_line(const char* format, ...);
@@ -135,6 +193,22 @@ private:
# define BOOST_ASIO_HANDLER_OPERATION(args) \
boost::asio::detail::handler_tracking::operation args
+# define BOOST_ASIO_HANDLER_REACTOR_REGISTRATION(args) \
+ boost::asio::detail::handler_tracking::reactor_registration args
+
+# define BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION(args) \
+ boost::asio::detail::handler_tracking::reactor_deregistration args
+
+# define BOOST_ASIO_HANDLER_REACTOR_READ_EVENT 1
+# define BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT 2
+# define BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT 4
+
+# define BOOST_ASIO_HANDLER_REACTOR_EVENTS(args) \
+ boost::asio::detail::handler_tracking::reactor_events args
+
+# define BOOST_ASIO_HANDLER_REACTOR_OPERATION(args) \
+ boost::asio::detail::handler_tracking::reactor_operation args
+
#else // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
# define BOOST_ASIO_INHERIT_TRACKED_HANDLER
@@ -145,6 +219,13 @@ private:
# define BOOST_ASIO_HANDLER_INVOCATION_BEGIN(args) (void)0
# define BOOST_ASIO_HANDLER_INVOCATION_END (void)0
# define BOOST_ASIO_HANDLER_OPERATION(args) (void)0
+# define BOOST_ASIO_HANDLER_REACTOR_REGISTRATION(args) (void)0
+# define BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION(args) (void)0
+# define BOOST_ASIO_HANDLER_REACTOR_READ_EVENT 0
+# define BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT 0
+# define BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT 0
+# define BOOST_ASIO_HANDLER_REACTOR_EVENTS(args) (void)0
+# define BOOST_ASIO_HANDLER_REACTOR_OPERATION(args) (void)0
#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
diff --git a/boost/asio/detail/handler_type_requirements.hpp b/boost/asio/detail/handler_type_requirements.hpp
index bc2fbce0ce..65b5e62dac 100644
--- a/boost/asio/detail/handler_type_requirements.hpp
+++ b/boost/asio/detail/handler_type_requirements.hpp
@@ -50,7 +50,7 @@
#endif // !defined(BOOST_ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)
#if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
-# include <boost/asio/handler_type.hpp>
+# include <boost/asio/async_result.hpp>
#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)
namespace boost {
@@ -62,19 +62,19 @@ namespace detail {
# if defined(BOOST_ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)
template <typename Handler>
-auto zero_arg_handler_test(Handler h, void*)
+auto zero_arg_copyable_handler_test(Handler h, void*)
-> decltype(
sizeof(Handler(static_cast<const Handler&>(h))),
((h)()),
char(0));
template <typename Handler>
-char (&zero_arg_handler_test(Handler, ...))[2];
+char (&zero_arg_copyable_handler_test(Handler, ...))[2];
template <typename Handler, typename Arg1>
auto one_arg_handler_test(Handler h, Arg1* a1)
-> decltype(
- sizeof(Handler(static_cast<const Handler&>(h))),
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
((h)(*a1)),
char(0));
@@ -84,13 +84,23 @@ char (&one_arg_handler_test(Handler h, ...))[2];
template <typename Handler, typename Arg1, typename Arg2>
auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)
-> decltype(
- sizeof(Handler(static_cast<const Handler&>(h))),
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
((h)(*a1, *a2)),
char(0));
template <typename Handler>
char (&two_arg_handler_test(Handler, ...))[2];
+template <typename Handler, typename Arg1, typename Arg2>
+auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2)
+ -> decltype(
+ sizeof(Handler(BOOST_ASIO_MOVE_CAST(Handler)(h))),
+ ((h)(*a1, BOOST_ASIO_MOVE_CAST(Arg2)(*a2))),
+ char(0));
+
+template <typename Handler>
+char (&two_arg_move_handler_test(Handler, ...))[2];
+
# define BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \
static_assert(expr, msg);
@@ -104,6 +114,13 @@ template <typename T> T& lvref();
template <typename T> T& lvref(T);
template <typename T> const T& clvref();
template <typename T> const T& clvref(T);
+#if defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> T rvref();
+template <typename T> T rvref(T);
+#else // defined(BOOST_ASIO_HAS_MOVE)
+template <typename T> const T& rvref();
+template <typename T> const T& rvref(T);
+#endif // defined(BOOST_ASIO_HAS_MOVE)
template <typename T> char argbyv(T);
template <int>
@@ -118,7 +135,7 @@ struct handler_type_requirements
void()) asio_true_handler_type; \
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
- sizeof(boost::asio::detail::zero_arg_handler_test( \
+ sizeof(boost::asio::detail::zero_arg_copyable_handler_test( \
boost::asio::detail::clvref< \
asio_true_handler_type>(), 0)) == 1, \
"CompletionHandler type requirements not met") \
@@ -142,7 +159,7 @@ struct handler_type_requirements
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
sizeof(boost::asio::detail::two_arg_handler_test( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>(), \
static_cast<const boost::system::error_code*>(0), \
static_cast<const std::size_t*>(0))) == 1, \
@@ -151,7 +168,7 @@ struct handler_type_requirements
typedef boost::asio::detail::handler_type_requirements< \
sizeof( \
boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>())) + \
sizeof( \
boost::asio::detail::lvref< \
@@ -160,7 +177,6 @@ struct handler_type_requirements
boost::asio::detail::lvref<const std::size_t>()), \
char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-
#define BOOST_ASIO_WRITE_HANDLER_CHECK( \
handler_type, handler) \
\
@@ -170,7 +186,7 @@ struct handler_type_requirements
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
sizeof(boost::asio::detail::two_arg_handler_test( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>(), \
static_cast<const boost::system::error_code*>(0), \
static_cast<const std::size_t*>(0))) == 1, \
@@ -179,7 +195,7 @@ struct handler_type_requirements
typedef boost::asio::detail::handler_type_requirements< \
sizeof( \
boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>())) + \
sizeof( \
boost::asio::detail::lvref< \
@@ -197,7 +213,7 @@ struct handler_type_requirements
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
sizeof(boost::asio::detail::one_arg_handler_test( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>(), \
static_cast<const boost::system::error_code*>(0))) == 1, \
"AcceptHandler type requirements not met") \
@@ -205,7 +221,7 @@ struct handler_type_requirements
typedef boost::asio::detail::handler_type_requirements< \
sizeof( \
boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>())) + \
sizeof( \
boost::asio::detail::lvref< \
@@ -213,6 +229,33 @@ struct handler_type_requirements
boost::asio::detail::lvref<const boost::system::error_code>()), \
char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler, socket_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, socket_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_move_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<socket_type*>(0))) == 1, \
+ "MoveAcceptHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::rvref<socket_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
handler_type, handler) \
\
@@ -222,7 +265,7 @@ struct handler_type_requirements
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
sizeof(boost::asio::detail::one_arg_handler_test( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>(), \
static_cast<const boost::system::error_code*>(0))) == 1, \
"ConnectHandler type requirements not met") \
@@ -230,7 +273,7 @@ struct handler_type_requirements
typedef boost::asio::detail::handler_type_requirements< \
sizeof( \
boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>())) + \
sizeof( \
boost::asio::detail::lvref< \
@@ -238,7 +281,34 @@ struct handler_type_requirements
boost::asio::detail::lvref<const boost::system::error_code>()), \
char(0))> BOOST_ASIO_UNUSED_TYPEDEF
-#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
+#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, endpoint_type) \
+ \
+ typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
+ void(boost::system::error_code, endpoint_type)) \
+ asio_true_handler_type; \
+ \
+ BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
+ sizeof(boost::asio::detail::two_arg_handler_test( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>(), \
+ static_cast<const boost::system::error_code*>(0), \
+ static_cast<const endpoint_type*>(0))) == 1, \
+ "RangeConnectHandler type requirements not met") \
+ \
+ typedef boost::asio::detail::handler_type_requirements< \
+ sizeof( \
+ boost::asio::detail::argbyv( \
+ boost::asio::detail::rvref< \
+ asio_true_handler_type>())) + \
+ sizeof( \
+ boost::asio::detail::lvref< \
+ asio_true_handler_type>()( \
+ boost::asio::detail::lvref<const boost::system::error_code>(), \
+ boost::asio::detail::lvref<const endpoint_type>()), \
+ char(0))> BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \
handler_type, handler, iter_type) \
\
typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
@@ -247,16 +317,16 @@ struct handler_type_requirements
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
sizeof(boost::asio::detail::two_arg_handler_test( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>(), \
static_cast<const boost::system::error_code*>(0), \
static_cast<const iter_type*>(0))) == 1, \
- "ComposedConnectHandler type requirements not met") \
+ "IteratorConnectHandler type requirements not met") \
\
typedef boost::asio::detail::handler_type_requirements< \
sizeof( \
boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>())) + \
sizeof( \
boost::asio::detail::lvref< \
@@ -266,30 +336,30 @@ struct handler_type_requirements
char(0))> BOOST_ASIO_UNUSED_TYPEDEF
#define BOOST_ASIO_RESOLVE_HANDLER_CHECK( \
- handler_type, handler, iter_type) \
+ handler_type, handler, range_type) \
\
typedef BOOST_ASIO_HANDLER_TYPE(handler_type, \
- void(boost::system::error_code, iter_type)) \
+ void(boost::system::error_code, range_type)) \
asio_true_handler_type; \
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
sizeof(boost::asio::detail::two_arg_handler_test( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>(), \
static_cast<const boost::system::error_code*>(0), \
- static_cast<const iter_type*>(0))) == 1, \
+ static_cast<const range_type*>(0))) == 1, \
"ResolveHandler type requirements not met") \
\
typedef boost::asio::detail::handler_type_requirements< \
sizeof( \
boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>())) + \
sizeof( \
boost::asio::detail::lvref< \
asio_true_handler_type>()( \
boost::asio::detail::lvref<const boost::system::error_code>(), \
- boost::asio::detail::lvref<const iter_type>()), \
+ boost::asio::detail::lvref<const range_type>()), \
char(0))> BOOST_ASIO_UNUSED_TYPEDEF
#define BOOST_ASIO_WAIT_HANDLER_CHECK( \
@@ -301,7 +371,7 @@ struct handler_type_requirements
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
sizeof(boost::asio::detail::one_arg_handler_test( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>(), \
static_cast<const boost::system::error_code*>(0))) == 1, \
"WaitHandler type requirements not met") \
@@ -309,7 +379,7 @@ struct handler_type_requirements
typedef boost::asio::detail::handler_type_requirements< \
sizeof( \
boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>())) + \
sizeof( \
boost::asio::detail::lvref< \
@@ -326,7 +396,7 @@ struct handler_type_requirements
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
sizeof(boost::asio::detail::two_arg_handler_test( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>(), \
static_cast<const boost::system::error_code*>(0), \
static_cast<const int*>(0))) == 1, \
@@ -335,7 +405,7 @@ struct handler_type_requirements
typedef boost::asio::detail::handler_type_requirements< \
sizeof( \
boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>())) + \
sizeof( \
boost::asio::detail::lvref< \
@@ -353,7 +423,7 @@ struct handler_type_requirements
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
sizeof(boost::asio::detail::one_arg_handler_test( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>(), \
static_cast<const boost::system::error_code*>(0))) == 1, \
"HandshakeHandler type requirements not met") \
@@ -361,7 +431,7 @@ struct handler_type_requirements
typedef boost::asio::detail::handler_type_requirements< \
sizeof( \
boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>())) + \
sizeof( \
boost::asio::detail::lvref< \
@@ -378,7 +448,7 @@ struct handler_type_requirements
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
sizeof(boost::asio::detail::two_arg_handler_test( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>(), \
static_cast<const boost::system::error_code*>(0), \
static_cast<const std::size_t*>(0))) == 1, \
@@ -387,7 +457,7 @@ struct handler_type_requirements
typedef boost::asio::detail::handler_type_requirements< \
sizeof( \
boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>())) + \
sizeof( \
boost::asio::detail::lvref< \
@@ -405,7 +475,7 @@ struct handler_type_requirements
\
BOOST_ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \
sizeof(boost::asio::detail::one_arg_handler_test( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>(), \
static_cast<const boost::system::error_code*>(0))) == 1, \
"ShutdownHandler type requirements not met") \
@@ -413,7 +483,7 @@ struct handler_type_requirements
typedef boost::asio::detail::handler_type_requirements< \
sizeof( \
boost::asio::detail::argbyv( \
- boost::asio::detail::clvref< \
+ boost::asio::detail::rvref< \
asio_true_handler_type>())) + \
sizeof( \
boost::asio::detail::lvref< \
@@ -439,11 +509,19 @@ struct handler_type_requirements
handler_type, handler) \
typedef int BOOST_ASIO_UNUSED_TYPEDEF
+#define BOOST_ASIO_MOVE_ACCEPT_HANDLER_CHECK( \
+ handler_type, handler, socket_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
#define BOOST_ASIO_CONNECT_HANDLER_CHECK( \
handler_type, handler) \
typedef int BOOST_ASIO_UNUSED_TYPEDEF
-#define BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK( \
+#define BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK( \
+ handler_type, handler, iter_type) \
+ typedef int BOOST_ASIO_UNUSED_TYPEDEF
+
+#define BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \
handler_type, handler, iter_type) \
typedef int BOOST_ASIO_UNUSED_TYPEDEF
diff --git a/boost/asio/detail/handler_work.hpp b/boost/asio/detail/handler_work.hpp
new file mode 100644
index 0000000000..62fbe68e46
--- /dev/null
+++ b/boost/asio/detail/handler_work.hpp
@@ -0,0 +1,97 @@
+//
+// detail/handler_work.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_HANDLER_WORK_HPP
+#define BOOST_ASIO_DETAIL_HANDLER_WORK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// A helper class template to allow completion handlers to be dispatched
+// through either the new executors framework or the old invocaton hook. The
+// primary template uses the new executors framework.
+template <typename Handler, typename Executor
+ = typename associated_executor<Handler>::type>
+class handler_work
+{
+public:
+ explicit handler_work(Handler& handler) BOOST_ASIO_NOEXCEPT
+ : executor_(associated_executor<Handler>::get(handler))
+ {
+ }
+
+ static void start(Handler& handler) BOOST_ASIO_NOEXCEPT
+ {
+ Executor ex(associated_executor<Handler>::get(handler));
+ ex.on_work_started();
+ }
+
+ ~handler_work()
+ {
+ executor_.on_work_finished();
+ }
+
+ template <typename Function>
+ void complete(Function& function, Handler& handler)
+ {
+ executor_.dispatch(BOOST_ASIO_MOVE_CAST(Function)(function),
+ associated_allocator<Handler>::get(handler));
+ }
+
+private:
+ // Disallow copying and assignment.
+ handler_work(const handler_work&);
+ handler_work& operator=(const handler_work&);
+
+ typename associated_executor<Handler>::type executor_;
+};
+
+// This specialisation dispatches a handler through the old invocation hook.
+// The specialisation is not strictly required for correctness, as the
+// system_executor will dispatch through the hook anyway. However, by doing
+// this we avoid an extra copy of the handler.
+template <typename Handler>
+class handler_work<Handler, system_executor>
+{
+public:
+ explicit handler_work(Handler&) BOOST_ASIO_NOEXCEPT {}
+ static void start(Handler&) BOOST_ASIO_NOEXCEPT {}
+ ~handler_work() {}
+
+ template <typename Function>
+ void complete(Function& function, Handler& handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(function, handler);
+ }
+
+private:
+ // Disallow copying and assignment.
+ handler_work(const handler_work&);
+ handler_work& operator=(const handler_work&);
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_HANDLER_WORK_HPP
diff --git a/boost/asio/detail/impl/buffer_sequence_adapter.ipp b/boost/asio/detail/impl/buffer_sequence_adapter.ipp
index f471863e1a..c2114ba1cf 100644
--- a/boost/asio/detail/impl/buffer_sequence_adapter.ipp
+++ b/boost/asio/detail/impl/buffer_sequence_adapter.ipp
@@ -40,16 +40,16 @@ class winrt_buffer_impl :
public:
explicit winrt_buffer_impl(const boost::asio::const_buffer& b)
{
- bytes_ = const_cast<byte*>(boost::asio::buffer_cast<const byte*>(b));
- length_ = boost::asio::buffer_size(b);
- capacity_ = boost::asio::buffer_size(b);
+ bytes_ = const_cast<byte*>(static_cast<const byte*>(b.data()));
+ length_ = b.size();
+ capacity_ = b.size();
}
explicit winrt_buffer_impl(const boost::asio::mutable_buffer& b)
{
- bytes_ = const_cast<byte*>(boost::asio::buffer_cast<const byte*>(b));
+ bytes_ = static_cast<byte*>(b.data());
length_ = 0;
- capacity_ = boost::asio::buffer_size(b);
+ capacity_ = b.size();
}
~winrt_buffer_impl()
diff --git a/boost/asio/detail/impl/descriptor_ops.ipp b/boost/asio/detail/impl/descriptor_ops.ipp
index 00f6b4796e..cdf5022306 100644
--- a/boost/asio/detail/impl/descriptor_ops.ipp
+++ b/boost/asio/detail/impl/descriptor_ops.ipp
@@ -439,6 +439,29 @@ int poll_write(int d, state_type state, boost::system::error_code& ec)
return result;
}
+int poll_error(int d, state_type state, boost::system::error_code& ec)
+{
+ if (d == -1)
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return -1;
+ }
+
+ pollfd fds;
+ fds.fd = d;
+ fds.events = POLLPRI | POLLERR | POLLHUP;
+ fds.revents = 0;
+ int timeout = (state & user_set_non_blocking) ? 0 : -1;
+ errno = 0;
+ int result = error_wrapper(::poll(&fds, 1, timeout), ec);
+ if (result == 0)
+ ec = (state & user_set_non_blocking)
+ ? boost::asio::error::would_block : boost::system::error_code();
+ else if (result > 0)
+ ec = boost::system::error_code();
+ return result;
+}
+
} // namespace descriptor_ops
} // namespace detail
} // namespace asio
diff --git a/boost/asio/detail/impl/dev_poll_reactor.hpp b/boost/asio/detail/impl/dev_poll_reactor.hpp
index 623346edd5..c01450ffea 100644
--- a/boost/asio/detail/impl/dev_poll_reactor.hpp
+++ b/boost/asio/detail/impl/dev_poll_reactor.hpp
@@ -46,12 +46,12 @@ void dev_poll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
if (shutdown_)
{
- io_service_.post_immediate_completion(op, false);
+ scheduler_.post_immediate_completion(op, false);
return;
}
bool earliest = queue.enqueue_timer(time, timer, op);
- io_service_.work_started();
+ scheduler_.work_started();
if (earliest)
interrupter_.interrupt();
}
@@ -65,10 +65,23 @@ std::size_t dev_poll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
op_queue<operation> ops;
std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
lock.unlock();
- io_service_.post_deferred_completions(ops);
+ scheduler_.post_deferred_completions(ops);
return n;
}
+template <typename Time_Traits>
+void dev_poll_reactor::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)
+{
+ boost::asio::detail::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
} // namespace boost
diff --git a/boost/asio/detail/impl/dev_poll_reactor.ipp b/boost/asio/detail/impl/dev_poll_reactor.ipp
index 7efb05ed02..5186d30473 100644
--- a/boost/asio/detail/impl/dev_poll_reactor.ipp
+++ b/boost/asio/detail/impl/dev_poll_reactor.ipp
@@ -30,9 +30,9 @@ namespace boost {
namespace asio {
namespace detail {
-dev_poll_reactor::dev_poll_reactor(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<dev_poll_reactor>(io_service),
- io_service_(use_service<io_service_impl>(io_service)),
+dev_poll_reactor::dev_poll_reactor(boost::asio::execution_context& ctx)
+ : boost::asio::detail::execution_context_service_base<dev_poll_reactor>(ctx),
+ scheduler_(use_service<scheduler>(ctx)),
mutex_(),
dev_poll_fd_(do_dev_poll_create()),
interrupter_(),
@@ -48,11 +48,11 @@ dev_poll_reactor::dev_poll_reactor(boost::asio::io_service& io_service)
dev_poll_reactor::~dev_poll_reactor()
{
- shutdown_service();
+ shutdown();
::close(dev_poll_fd_);
}
-void dev_poll_reactor::shutdown_service()
+void dev_poll_reactor::shutdown()
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
shutdown_ = true;
@@ -65,12 +65,13 @@ void dev_poll_reactor::shutdown_service()
timer_queues_.get_all_timers(ops);
- io_service_.abandon_operations(ops);
+ scheduler_.abandon_operations(ops);
}
-void dev_poll_reactor::fork_service(boost::asio::io_service::fork_event fork_ev)
+void dev_poll_reactor::notify_fork(
+ boost::asio::execution_context::fork_event fork_ev)
{
- if (fork_ev == boost::asio::io_service::fork_child)
+ if (fork_ev == boost::asio::execution_context::fork_child)
{
detail::mutex::scoped_lock lock(mutex_);
@@ -113,7 +114,7 @@ void dev_poll_reactor::fork_service(boost::asio::io_service::fork_event fork_ev)
void dev_poll_reactor::init_task()
{
- io_service_.init_task();
+ scheduler_.init_task();
}
int dev_poll_reactor::register_descriptor(socket_type, per_descriptor_data&)
@@ -168,7 +169,7 @@ void dev_poll_reactor::start_op(int op_type, socket_type descriptor,
if (op->perform())
{
lock.unlock();
- io_service_.post_immediate_completion(op, is_continuation);
+ scheduler_.post_immediate_completion(op, is_continuation);
return;
}
}
@@ -176,7 +177,7 @@ void dev_poll_reactor::start_op(int op_type, socket_type descriptor,
}
bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
- io_service_.work_started();
+ scheduler_.work_started();
if (first)
{
::pollfd& ev = add_pending_event_change(descriptor);
@@ -240,13 +241,13 @@ void dev_poll_reactor::cleanup_descriptor_data(
{
}
-void dev_poll_reactor::run(bool block, op_queue<operation>& ops)
+void dev_poll_reactor::run(long usec, op_queue<operation>& ops)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
// We can return immediately if there's no work to do and the reactor is
// not supposed to block.
- if (!block && op_queue_[read_op].empty() && op_queue_[write_op].empty()
+ if (usec == 0 && op_queue_[read_op].empty() && op_queue_[write_op].empty()
&& op_queue_[except_op].empty() && timer_queues_.all_empty())
return;
@@ -272,7 +273,15 @@ void dev_poll_reactor::run(bool block, op_queue<operation>& ops)
pending_event_change_index_.clear();
}
- int timeout = block ? get_timeout() : 0;
+ // Calculate timeout.
+ int timeout;
+ if (usec == 0)
+ timeout = 0;
+ else
+ {
+ timeout = (usec < 0) ? -1 : ((usec - 1) / 1000 + 1);
+ timeout = get_timeout(timeout);
+ }
lock.unlock();
// Block on the /dev/poll descriptor.
@@ -386,11 +395,13 @@ void dev_poll_reactor::do_remove_timer_queue(timer_queue_base& queue)
timer_queues_.erase(&queue);
}
-int dev_poll_reactor::get_timeout()
+int dev_poll_reactor::get_timeout(int msec)
{
// By default we will wait no longer than 5 minutes. This will ensure that
// any changes to the system clock are detected after no longer than this.
- return timer_queues_.wait_duration_msec(5 * 60 * 1000);
+ const int max_msec = 5 * 60 * 1000;
+ return timer_queues_.wait_duration_msec(
+ (msec < 0 || max_msec < msec) ? max_msec : msec);
}
void dev_poll_reactor::cancel_ops_unlocked(socket_type descriptor,
@@ -401,7 +412,7 @@ void dev_poll_reactor::cancel_ops_unlocked(socket_type descriptor,
for (int i = 0; i < max_ops; ++i)
need_interrupt = op_queue_[i].cancel_operations(
descriptor, ops, ec) || need_interrupt;
- io_service_.post_deferred_completions(ops);
+ scheduler_.post_deferred_completions(ops);
if (need_interrupt)
interrupter_.interrupt();
}
diff --git a/boost/asio/detail/impl/epoll_reactor.hpp b/boost/asio/detail/impl/epoll_reactor.hpp
index ea5c6bfc69..537b0fc7da 100644
--- a/boost/asio/detail/impl/epoll_reactor.hpp
+++ b/boost/asio/detail/impl/epoll_reactor.hpp
@@ -44,12 +44,12 @@ void epoll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
if (shutdown_)
{
- io_service_.post_immediate_completion(op, false);
+ scheduler_.post_immediate_completion(op, false);
return;
}
bool earliest = queue.enqueue_timer(time, timer, op);
- io_service_.work_started();
+ scheduler_.work_started();
if (earliest)
update_timeout();
}
@@ -63,10 +63,23 @@ std::size_t epoll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
op_queue<operation> ops;
std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
lock.unlock();
- io_service_.post_deferred_completions(ops);
+ scheduler_.post_deferred_completions(ops);
return n;
}
+template <typename Time_Traits>
+void epoll_reactor::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
} // namespace boost
diff --git a/boost/asio/detail/impl/epoll_reactor.ipp b/boost/asio/detail/impl/epoll_reactor.ipp
index 3d3d244e0a..a9c2602fbe 100644
--- a/boost/asio/detail/impl/epoll_reactor.ipp
+++ b/boost/asio/detail/impl/epoll_reactor.ipp
@@ -35,14 +35,16 @@ namespace boost {
namespace asio {
namespace detail {
-epoll_reactor::epoll_reactor(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<epoll_reactor>(io_service),
- io_service_(use_service<io_service_impl>(io_service)),
- mutex_(),
+epoll_reactor::epoll_reactor(boost::asio::execution_context& ctx)
+ : execution_context_service_base<epoll_reactor>(ctx),
+ scheduler_(use_service<scheduler>(ctx)),
+ mutex_(BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
+ REACTOR_REGISTRATION, scheduler_.concurrency_hint())),
interrupter_(),
epoll_fd_(do_epoll_create()),
timer_fd_(do_timerfd_create()),
- shutdown_(false)
+ shutdown_(false),
+ registered_descriptors_mutex_(mutex_.enabled())
{
// Add the interrupter's descriptor to epoll.
epoll_event ev = { 0, { 0 } };
@@ -68,7 +70,7 @@ epoll_reactor::~epoll_reactor()
close(timer_fd_);
}
-void epoll_reactor::shutdown_service()
+void epoll_reactor::shutdown()
{
mutex::scoped_lock lock(mutex_);
shutdown_ = true;
@@ -86,12 +88,13 @@ void epoll_reactor::shutdown_service()
timer_queues_.get_all_timers(ops);
- io_service_.abandon_operations(ops);
+ scheduler_.abandon_operations(ops);
}
-void epoll_reactor::fork_service(boost::asio::io_service::fork_event fork_ev)
+void epoll_reactor::notify_fork(
+ boost::asio::execution_context::fork_event fork_ev)
{
- if (fork_ev == boost::asio::io_service::fork_child)
+ if (fork_ev == boost::asio::execution_context::fork_child)
{
if (epoll_fd_ != -1)
::close(epoll_fd_);
@@ -142,7 +145,7 @@ void epoll_reactor::fork_service(boost::asio::io_service::fork_event fork_ev)
void epoll_reactor::init_task()
{
- io_service_.init_task();
+ scheduler_.init_task();
}
int epoll_reactor::register_descriptor(socket_type descriptor,
@@ -150,12 +153,18 @@ int epoll_reactor::register_descriptor(socket_type descriptor,
{
descriptor_data = allocate_descriptor_state();
+ BOOST_ASIO_HANDLER_REACTOR_REGISTRATION((
+ context(), static_cast<uintmax_t>(descriptor),
+ reinterpret_cast<uintmax_t>(descriptor_data)));
+
{
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
descriptor_data->reactor_ = this;
descriptor_data->descriptor_ = descriptor;
descriptor_data->shutdown_ = false;
+ for (int i = 0; i < max_ops; ++i)
+ descriptor_data->try_speculative_[i] = true;
}
epoll_event ev = { 0, { 0 } };
@@ -186,6 +195,10 @@ int epoll_reactor::register_internal_descriptor(
{
descriptor_data = allocate_descriptor_state();
+ BOOST_ASIO_HANDLER_REACTOR_REGISTRATION((
+ context(), static_cast<uintmax_t>(descriptor),
+ reinterpret_cast<uintmax_t>(descriptor_data)));
+
{
mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);
@@ -193,6 +206,8 @@ int epoll_reactor::register_internal_descriptor(
descriptor_data->descriptor_ = descriptor;
descriptor_data->shutdown_ = false;
descriptor_data->op_queue_[op_type].push(op);
+ for (int i = 0; i < max_ops; ++i)
+ descriptor_data->try_speculative_[i] = true;
}
epoll_event ev = { 0, { 0 } };
@@ -239,17 +254,23 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
&& (op_type != read_op
|| descriptor_data->op_queue_[except_op].empty()))
{
- if (op->perform())
+ if (descriptor_data->try_speculative_[op_type])
{
- descriptor_lock.unlock();
- io_service_.post_immediate_completion(op, is_continuation);
- return;
+ if (reactor_op::status status = op->perform())
+ {
+ if (status == reactor_op::done_and_exhausted)
+ if (descriptor_data->registered_events_ != 0)
+ descriptor_data->try_speculative_[op_type] = false;
+ descriptor_lock.unlock();
+ scheduler_.post_immediate_completion(op, is_continuation);
+ return;
+ }
}
if (descriptor_data->registered_events_ == 0)
{
op->ec_ = boost::asio::error::operation_not_supported;
- io_service_.post_immediate_completion(op, is_continuation);
+ scheduler_.post_immediate_completion(op, is_continuation);
return;
}
@@ -268,7 +289,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
{
op->ec_ = boost::system::error_code(errno,
boost::asio::error::get_system_category());
- io_service_.post_immediate_completion(op, is_continuation);
+ scheduler_.post_immediate_completion(op, is_continuation);
return;
}
}
@@ -277,7 +298,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
else if (descriptor_data->registered_events_ == 0)
{
op->ec_ = boost::asio::error::operation_not_supported;
- io_service_.post_immediate_completion(op, is_continuation);
+ scheduler_.post_immediate_completion(op, is_continuation);
return;
}
else
@@ -295,7 +316,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor,
}
descriptor_data->op_queue_[op_type].push(op);
- io_service_.work_started();
+ scheduler_.work_started();
}
void epoll_reactor::cancel_ops(socket_type,
@@ -319,7 +340,7 @@ void epoll_reactor::cancel_ops(socket_type,
descriptor_lock.unlock();
- io_service_.post_deferred_completions(ops);
+ scheduler_.post_deferred_completions(ops);
}
void epoll_reactor::deregister_descriptor(socket_type descriptor,
@@ -359,7 +380,11 @@ void epoll_reactor::deregister_descriptor(socket_type descriptor,
descriptor_lock.unlock();
- io_service_.post_deferred_completions(ops);
+ BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION((
+ context(), static_cast<uintmax_t>(descriptor),
+ reinterpret_cast<uintmax_t>(descriptor_data)));
+
+ scheduler_.post_deferred_completions(ops);
// Leave descriptor_data set so that it will be freed by the subsequent
// call to cleanup_descriptor_data.
@@ -394,6 +419,10 @@ void epoll_reactor::deregister_internal_descriptor(socket_type descriptor,
descriptor_lock.unlock();
+ BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION((
+ context(), static_cast<uintmax_t>(descriptor),
+ reinterpret_cast<uintmax_t>(descriptor_data)));
+
// Leave descriptor_data set so that it will be freed by the subsequent
// call to cleanup_descriptor_data.
}
@@ -415,28 +444,62 @@ void epoll_reactor::cleanup_descriptor_data(
}
}
-void epoll_reactor::run(bool block, op_queue<operation>& ops)
+void epoll_reactor::run(long usec, op_queue<operation>& ops)
{
- // This code relies on the fact that the task_io_service queues the reactor
- // task behind all descriptor operations generated by this function. This
- // means, that by the time we reach this point, any previously returned
- // descriptor operations have already been dequeued. Therefore it is now safe
- // for us to reuse and return them for the task_io_service to queue again.
+ // This code relies on the fact that the scheduler queues the reactor task
+ // behind all descriptor operations generated by this function. This means,
+ // that by the time we reach this point, any previously returned descriptor
+ // operations have already been dequeued. Therefore it is now safe for us to
+ // reuse and return them for the scheduler to queue again.
- // Calculate a timeout only if timerfd is not used.
+ // Calculate timeout. Check the timer queues only if timerfd is not in use.
int timeout;
- if (timer_fd_ != -1)
- timeout = block ? -1 : 0;
+ if (usec == 0)
+ timeout = 0;
else
{
- mutex::scoped_lock lock(mutex_);
- timeout = block ? get_timeout() : 0;
+ timeout = (usec < 0) ? -1 : ((usec - 1) / 1000 + 1);
+ if (timer_fd_ == -1)
+ {
+ mutex::scoped_lock lock(mutex_);
+ timeout = get_timeout(timeout);
+ }
}
// Block on the epoll descriptor.
epoll_event events[128];
int num_events = epoll_wait(epoll_fd_, events, 128, timeout);
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+ // Trace the waiting events.
+ for (int i = 0; i < num_events; ++i)
+ {
+ void* ptr = events[i].data.ptr;
+ if (ptr == &interrupter_)
+ {
+ // Ignore.
+ }
+# if defined(BOOST_ASIO_HAS_TIMERFD)
+ else if (ptr == &timer_fd_)
+ {
+ // Ignore.
+ }
+# endif // defined(BOOST_ASIO_HAS_TIMERFD)
+ else
+ {
+ unsigned event_mask = 0;
+ if ((events[i].events & EPOLLIN) != 0)
+ event_mask |= BOOST_ASIO_HANDLER_REACTOR_READ_EVENT;
+ if ((events[i].events & EPOLLOUT))
+ event_mask |= BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT;
+ if ((events[i].events & (EPOLLERR | EPOLLHUP)) != 0)
+ event_mask |= BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT;
+ BOOST_ASIO_HANDLER_REACTOR_EVENTS((context(),
+ reinterpret_cast<uintmax_t>(ptr), event_mask));
+ }
+ }
+#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+
#if defined(BOOST_ASIO_HAS_TIMERFD)
bool check_timers = (timer_fd_ == -1);
#else // defined(BOOST_ASIO_HAS_TIMERFD)
@@ -470,7 +533,7 @@ void epoll_reactor::run(bool block, op_queue<operation>& ops)
else
{
// The descriptor operation doesn't count as work in and of itself, so we
- // don't call work_started() here. This still allows the io_service to
+ // don't call work_started() here. This still allows the scheduler to
// stop if the only remaining operations are descriptor operations.
descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);
if (!ops.is_enqueued(descriptor_data))
@@ -562,7 +625,8 @@ int epoll_reactor::do_timerfd_create()
epoll_reactor::descriptor_state* epoll_reactor::allocate_descriptor_state()
{
mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
- return registered_descriptors_.alloc();
+ return registered_descriptors_.alloc(BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
+ REACTOR_IO, scheduler_.concurrency_hint()));
}
void epoll_reactor::free_descriptor_state(epoll_reactor::descriptor_state* s)
@@ -598,11 +662,13 @@ void epoll_reactor::update_timeout()
interrupt();
}
-int epoll_reactor::get_timeout()
+int epoll_reactor::get_timeout(int msec)
{
// By default we will wait no longer than 5 minutes. This will ensure that
// any changes to the system clock are detected after no longer than this.
- return timer_queues_.wait_duration_msec(5 * 60 * 1000);
+ const int max_msec = 5 * 60 * 1000;
+ return timer_queues_.wait_duration_msec(
+ (msec < 0 || max_msec < msec) ? max_msec : msec);
}
#if defined(BOOST_ASIO_HAS_TIMERFD)
@@ -632,19 +698,18 @@ struct epoll_reactor::perform_io_cleanup_on_block_exit
{
// Post the remaining completed operations for invocation.
if (!ops_.empty())
- reactor_->io_service_.post_deferred_completions(ops_);
+ reactor_->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 task_io_service will call work_finished() once we
- // return.
+ // 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 task_io_service will make once
- // this operation returns.
- reactor_->io_service_.work_started();
+ // for the work_finished() call that the scheduler will make once this
+ // operation returns.
+ reactor_->scheduler_.compensating_work_started();
}
}
@@ -653,8 +718,9 @@ struct epoll_reactor::perform_io_cleanup_on_block_exit
operation* first_op_;
};
-epoll_reactor::descriptor_state::descriptor_state()
- : operation(&epoll_reactor::descriptor_state::do_complete)
+epoll_reactor::descriptor_state::descriptor_state(bool locking)
+ : operation(&epoll_reactor::descriptor_state::do_complete),
+ mutex_(locking)
{
}
@@ -671,12 +737,18 @@ operation* epoll_reactor::descriptor_state::perform_io(uint32_t events)
{
if (events & (flag[j] | EPOLLERR | EPOLLHUP))
{
+ try_speculative_[j] = true;
while (reactor_op* op = op_queue_[j].front())
{
- if (op->perform())
+ if (reactor_op::status status = op->perform())
{
op_queue_[j].pop();
io_cleanup.ops_.push(op);
+ if (status == reactor_op::done_and_exhausted)
+ {
+ try_speculative_[j] = false;
+ break;
+ }
}
else
break;
@@ -692,7 +764,7 @@ operation* epoll_reactor::descriptor_state::perform_io(uint32_t events)
}
void epoll_reactor::descriptor_state::do_complete(
- io_service_impl* owner, operation* base,
+ void* owner, operation* base,
const boost::system::error_code& ec, std::size_t bytes_transferred)
{
if (owner)
@@ -701,7 +773,7 @@ void epoll_reactor::descriptor_state::do_complete(
uint32_t events = static_cast<uint32_t>(bytes_transferred);
if (operation* op = descriptor_data->perform_io(events))
{
- op->complete(*owner, ec, 0);
+ op->complete(owner, ec, 0);
}
}
}
diff --git a/boost/asio/detail/impl/handler_tracking.ipp b/boost/asio/detail/impl/handler_tracking.ipp
index 259b5ab62b..aa6b9b2917 100644
--- a/boost/asio/detail/impl/handler_tracking.ipp
+++ b/boost/asio/detail/impl/handler_tracking.ipp
@@ -17,7 +17,11 @@
#include <boost/asio/detail/config.hpp>
-#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+#if defined(BOOST_ASIO_CUSTOM_HANDLER_TRACKING)
+
+// The handler tracking implementation is provided by the user-specified header.
+
+#elif defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
#include <cstdarg>
#include <cstdio>
@@ -25,17 +29,15 @@
#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
# include <boost/asio/time_traits.hpp>
-#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
-# if defined(BOOST_ASIO_HAS_STD_CHRONO)
-# include <chrono>
-# elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
-# include <boost/chrono/system_clocks.hpp>
-# endif
+#elif defined(BOOST_ASIO_HAS_CHRONO)
+# include <boost/asio/detail/chrono.hpp>
# include <boost/asio/detail/chrono_time_traits.hpp>
# include <boost/asio/wait_traits.hpp>
#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
-#if !defined(BOOST_ASIO_WINDOWS)
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/socket_types.hpp>
+#elif !defined(BOOST_ASIO_WINDOWS)
# include <unistd.h>
#endif // !defined(BOOST_ASIO_WINDOWS)
@@ -56,16 +58,11 @@ struct handler_tracking_timestamp
boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));
boost::posix_time::time_duration now =
boost::posix_time::microsec_clock::universal_time() - epoch;
-#elif defined(BOOST_ASIO_HAS_STD_CHRONO)
- typedef chrono_time_traits<std::chrono::system_clock,
- boost::asio::wait_traits<std::chrono::system_clock> > traits_helper;
- traits_helper::posix_time_duration now(
- std::chrono::system_clock::now().time_since_epoch());
-#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
- typedef chrono_time_traits<boost::chrono::system_clock,
- boost::asio::wait_traits<boost::chrono::system_clock> > traits_helper;
+#elif defined(BOOST_ASIO_HAS_CHRONO)
+ typedef chrono_time_traits<chrono::system_clock,
+ boost::asio::wait_traits<chrono::system_clock> > traits_helper;
traits_helper::posix_time_duration now(
- boost::chrono::system_clock::now().time_since_epoch());
+ chrono::system_clock::now().time_since_epoch());
#endif
seconds = static_cast<uint64_t>(now.total_seconds());
microseconds = static_cast<uint64_t>(now.total_microseconds() % 1000000);
@@ -96,13 +93,15 @@ void handler_tracking::init()
state->current_completion_ = new tss_ptr<completion>;
}
-void handler_tracking::creation(handler_tracking::tracked_handler* h,
- const char* object_type, void* object, const char* op_name)
+void handler_tracking::creation(execution_context&,
+ handler_tracking::tracked_handler& h,
+ const char* object_type, void* object,
+ uintmax_t /*native_handle*/, const char* op_name)
{
static tracking_state* state = get_state();
static_mutex::scoped_lock lock(state->mutex_);
- h->id_ = state->next_id_++;
+ h.id_ = state->next_id_++;
lock.unlock();
handler_tracking_timestamp timestamp;
@@ -118,11 +117,12 @@ void handler_tracking::creation(handler_tracking::tracked_handler* h,
"@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n",
#endif // defined(BOOST_ASIO_WINDOWS)
timestamp.seconds, timestamp.microseconds,
- current_id, h->id_, object_type, object, op_name);
+ current_id, h.id_, object_type, object, op_name);
}
-handler_tracking::completion::completion(handler_tracking::tracked_handler* h)
- : id_(h->id_),
+handler_tracking::completion::completion(
+ const handler_tracking::tracked_handler& h)
+ : id_(h.id_),
invoked_(false),
next_(*get_state()->current_completion_)
{
@@ -250,8 +250,9 @@ void handler_tracking::completion::invocation_end()
}
}
-void handler_tracking::operation(const char* object_type,
- void* object, const char* op_name)
+void handler_tracking::operation(execution_context&,
+ const char* object_type, void* object,
+ uintmax_t /*native_handle*/, const char* op_name)
{
static tracking_state* state = get_state();
@@ -271,6 +272,54 @@ void handler_tracking::operation(const char* object_type,
current_id, object_type, object, op_name);
}
+void handler_tracking::reactor_registration(execution_context& /*context*/,
+ uintmax_t /*native_handle*/, uintmax_t /*registration*/)
+{
+}
+
+void handler_tracking::reactor_deregistration(execution_context& /*context*/,
+ uintmax_t /*native_handle*/, uintmax_t /*registration*/)
+{
+}
+
+void handler_tracking::reactor_events(execution_context& /*context*/,
+ uintmax_t /*native_handle*/, unsigned /*events*/)
+{
+}
+
+void handler_tracking::reactor_operation(
+ const tracked_handler& h, const char* op_name,
+ const boost::system::error_code& ec)
+{
+ handler_tracking_timestamp timestamp;
+
+ write_line(
+#if defined(BOOST_ASIO_WINDOWS)
+ "@asio|%I64u.%06I64u|.%I64u|%s,ec=%.20s:%d\n",
+#else // defined(BOOST_ASIO_WINDOWS)
+ "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d\n",
+#endif // defined(BOOST_ASIO_WINDOWS)
+ timestamp.seconds, timestamp.microseconds,
+ h.id_, op_name, ec.category().name(), ec.value());
+}
+
+void handler_tracking::reactor_operation(
+ const tracked_handler& h, const char* op_name,
+ const boost::system::error_code& ec, std::size_t bytes_transferred)
+{
+ handler_tracking_timestamp timestamp;
+
+ write_line(
+#if defined(BOOST_ASIO_WINDOWS)
+ "@asio|%I64u.%06I64u|.%I64u|%s,ec=%.20s:%d,bytes_transferred=%I64u\n",
+#else // defined(BOOST_ASIO_WINDOWS)
+ "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d,bytes_transferred=%llu\n",
+#endif // defined(BOOST_ASIO_WINDOWS)
+ timestamp.seconds, timestamp.microseconds,
+ h.id_, op_name, ec.category().name(), ec.value(),
+ static_cast<uint64_t>(bytes_transferred));
+}
+
void handler_tracking::write_line(const char* format, ...)
{
using namespace std; // For sprintf (or equivalent).
@@ -287,7 +336,11 @@ void handler_tracking::write_line(const char* format, ...)
va_end(args);
-#if defined(BOOST_ASIO_WINDOWS)
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ wchar_t wline[256] = L"";
+ mbstowcs_s(0, wline, sizeof(wline) / sizeof(wchar_t), line, length);
+ ::OutputDebugStringW(wline);
+#elif defined(BOOST_ASIO_WINDOWS)
HANDLE stderr_handle = ::GetStdHandle(STD_ERROR_HANDLE);
DWORD bytes_written = 0;
::WriteFile(stderr_handle, line, length, &bytes_written, 0);
diff --git a/boost/asio/detail/impl/kqueue_reactor.hpp b/boost/asio/detail/impl/kqueue_reactor.hpp
index 93cbca26a2..83bfa95765 100644
--- a/boost/asio/detail/impl/kqueue_reactor.hpp
+++ b/boost/asio/detail/impl/kqueue_reactor.hpp
@@ -44,16 +44,16 @@ void kqueue_reactor::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)
{
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ mutex::scoped_lock lock(mutex_);
if (shutdown_)
{
- io_service_.post_immediate_completion(op, false);
+ scheduler_.post_immediate_completion(op, false);
return;
}
bool earliest = queue.enqueue_timer(time, timer, op);
- io_service_.work_started();
+ scheduler_.work_started();
if (earliest)
interrupt();
}
@@ -63,14 +63,27 @@ std::size_t kqueue_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
typename timer_queue<Time_Traits>::per_timer_data& timer,
std::size_t max_cancelled)
{
- boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ mutex::scoped_lock lock(mutex_);
op_queue<operation> ops;
std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
lock.unlock();
- io_service_.post_deferred_completions(ops);
+ scheduler_.post_deferred_completions(ops);
return n;
}
+template <typename Time_Traits>
+void kqueue_reactor::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
} // namespace boost
diff --git a/boost/asio/detail/impl/kqueue_reactor.ipp b/boost/asio/detail/impl/kqueue_reactor.ipp
index 8057606ce6..c492646a0b 100644
--- a/boost/asio/detail/impl/kqueue_reactor.ipp
+++ b/boost/asio/detail/impl/kqueue_reactor.ipp
@@ -21,6 +21,7 @@
#if defined(BOOST_ASIO_HAS_KQUEUE)
#include <boost/asio/detail/kqueue_reactor.hpp>
+#include <boost/asio/detail/scheduler.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
@@ -39,13 +40,15 @@ namespace boost {
namespace asio {
namespace detail {
-kqueue_reactor::kqueue_reactor(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<kqueue_reactor>(io_service),
- io_service_(use_service<io_service_impl>(io_service)),
- mutex_(),
+kqueue_reactor::kqueue_reactor(boost::asio::execution_context& ctx)
+ : execution_context_service_base<kqueue_reactor>(ctx),
+ scheduler_(use_service<scheduler>(ctx)),
+ mutex_(BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
+ REACTOR_REGISTRATION, scheduler_.concurrency_hint())),
kqueue_fd_(do_kqueue_create()),
interrupter_(),
- shutdown_(false)
+ shutdown_(false),
+ registered_descriptors_mutex_(mutex_.enabled())
{
struct kevent events[1];
BOOST_ASIO_KQUEUE_EV_SET(&events[0], interrupter_.read_descriptor(),
@@ -63,7 +66,7 @@ kqueue_reactor::~kqueue_reactor()
close(kqueue_fd_);
}
-void kqueue_reactor::shutdown_service()
+void kqueue_reactor::shutdown()
{
mutex::scoped_lock lock(mutex_);
shutdown_ = true;
@@ -81,12 +84,13 @@ void kqueue_reactor::shutdown_service()
timer_queues_.get_all_timers(ops);
- io_service_.abandon_operations(ops);
+ scheduler_.abandon_operations(ops);
}
-void kqueue_reactor::fork_service(boost::asio::io_service::fork_event fork_ev)
+void kqueue_reactor::notify_fork(
+ boost::asio::execution_context::fork_event fork_ev)
{
- if (fork_ev == boost::asio::io_service::fork_child)
+ if (fork_ev == boost::asio::execution_context::fork_child)
{
// The kqueue descriptor is automatically closed in the child.
kqueue_fd_ = -1;
@@ -128,7 +132,7 @@ void kqueue_reactor::fork_service(boost::asio::io_service::fork_event fork_ev)
void kqueue_reactor::init_task()
{
- io_service_.init_task();
+ scheduler_.init_task();
}
int kqueue_reactor::register_descriptor(socket_type descriptor,
@@ -136,6 +140,10 @@ int kqueue_reactor::register_descriptor(socket_type descriptor,
{
descriptor_data = allocate_descriptor_state();
+ BOOST_ASIO_HANDLER_REACTOR_REGISTRATION((
+ context(), static_cast<uintmax_t>(descriptor),
+ reinterpret_cast<uintmax_t>(descriptor_data)));
+
mutex::scoped_lock lock(descriptor_data->mutex_);
descriptor_data->descriptor_ = descriptor;
@@ -151,6 +159,10 @@ int kqueue_reactor::register_internal_descriptor(
{
descriptor_data = allocate_descriptor_state();
+ BOOST_ASIO_HANDLER_REACTOR_REGISTRATION((
+ context(), static_cast<uintmax_t>(descriptor),
+ reinterpret_cast<uintmax_t>(descriptor_data)));
+
mutex::scoped_lock lock(descriptor_data->mutex_);
descriptor_data->descriptor_ = descriptor;
@@ -205,7 +217,7 @@ void kqueue_reactor::start_op(int op_type, socket_type descriptor,
if (op->perform())
{
descriptor_lock.unlock();
- io_service_.post_immediate_completion(op, is_continuation);
+ scheduler_.post_immediate_completion(op, is_continuation);
return;
}
@@ -224,7 +236,7 @@ void kqueue_reactor::start_op(int op_type, socket_type descriptor,
{
op->ec_ = boost::system::error_code(errno,
boost::asio::error::get_system_category());
- io_service_.post_immediate_completion(op, is_continuation);
+ scheduler_.post_immediate_completion(op, is_continuation);
return;
}
}
@@ -244,7 +256,7 @@ void kqueue_reactor::start_op(int op_type, socket_type descriptor,
}
descriptor_data->op_queue_[op_type].push(op);
- io_service_.work_started();
+ scheduler_.work_started();
}
void kqueue_reactor::cancel_ops(socket_type,
@@ -268,7 +280,7 @@ void kqueue_reactor::cancel_ops(socket_type,
descriptor_lock.unlock();
- io_service_.post_deferred_completions(ops);
+ scheduler_.post_deferred_completions(ops);
}
void kqueue_reactor::deregister_descriptor(socket_type descriptor,
@@ -312,7 +324,11 @@ void kqueue_reactor::deregister_descriptor(socket_type descriptor,
descriptor_lock.unlock();
- io_service_.post_deferred_completions(ops);
+ BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION((
+ context(), static_cast<uintmax_t>(descriptor),
+ reinterpret_cast<uintmax_t>(descriptor_data)));
+
+ scheduler_.post_deferred_completions(ops);
// Leave descriptor_data set so that it will be freed by the subsequent
// call to cleanup_descriptor_data.
@@ -351,6 +367,10 @@ void kqueue_reactor::deregister_internal_descriptor(socket_type descriptor,
descriptor_lock.unlock();
+ BOOST_ASIO_HANDLER_REACTOR_DEREGISTRATION((
+ context(), static_cast<uintmax_t>(descriptor),
+ reinterpret_cast<uintmax_t>(descriptor_data)));
+
// Leave descriptor_data set so that it will be freed by the subsequent
// call to cleanup_descriptor_data.
}
@@ -372,13 +392,13 @@ void kqueue_reactor::cleanup_descriptor_data(
}
}
-void kqueue_reactor::run(bool block, op_queue<operation>& ops)
+void kqueue_reactor::run(long usec, op_queue<operation>& ops)
{
mutex::scoped_lock lock(mutex_);
// Determine how long to block while waiting for events.
timespec timeout_buf = { 0, 0 };
- timespec* timeout = block ? get_timeout(timeout_buf) : &timeout_buf;
+ timespec* timeout = usec ? get_timeout(usec, timeout_buf) : &timeout_buf;
lock.unlock();
@@ -386,6 +406,31 @@ void kqueue_reactor::run(bool block, op_queue<operation>& ops)
struct kevent events[128];
int num_events = kevent(kqueue_fd_, 0, 0, events, 128, timeout);
+#if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+ // Trace the waiting events.
+ for (int i = 0; i < num_events; ++i)
+ {
+ void* ptr = reinterpret_cast<void*>(events[i].udata);
+ if (ptr != &interrupter_)
+ {
+ unsigned event_mask = 0;
+ switch (events[i].filter)
+ {
+ case EVFILT_READ:
+ event_mask |= BOOST_ASIO_HANDLER_REACTOR_READ_EVENT;
+ break;
+ case EVFILT_WRITE:
+ event_mask |= BOOST_ASIO_HANDLER_REACTOR_WRITE_EVENT;
+ break;
+ }
+ if ((events[i].flags & (EV_ERROR | EV_OOBAND)) != 0)
+ event_mask |= BOOST_ASIO_HANDLER_REACTOR_ERROR_EVENT;
+ BOOST_ASIO_HANDLER_REACTOR_EVENTS((context(),
+ reinterpret_cast<uintmax_t>(ptr), event_mask));
+ }
+ }
+#endif // defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
+
// Dispatch the waiting events.
for (int i = 0; i < num_events; ++i)
{
@@ -476,7 +521,8 @@ int kqueue_reactor::do_kqueue_create()
kqueue_reactor::descriptor_state* kqueue_reactor::allocate_descriptor_state()
{
mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);
- return registered_descriptors_.alloc();
+ return registered_descriptors_.alloc(BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
+ REACTOR_IO, scheduler_.concurrency_hint()));
}
void kqueue_reactor::free_descriptor_state(kqueue_reactor::descriptor_state* s)
@@ -497,11 +543,13 @@ void kqueue_reactor::do_remove_timer_queue(timer_queue_base& queue)
timer_queues_.erase(&queue);
}
-timespec* kqueue_reactor::get_timeout(timespec& ts)
+timespec* kqueue_reactor::get_timeout(long usec, timespec& ts)
{
// By default we will wait no longer than 5 minutes. This will ensure that
// any changes to the system clock are detected after no longer than this.
- long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+ const long max_usec = 5 * 60 * 1000 * 1000;
+ usec = timer_queues_.wait_duration_usec(
+ (usec < 0 || max_usec < usec) ? max_usec : usec);
ts.tv_sec = usec / 1000000;
ts.tv_nsec = (usec % 1000000) * 1000;
return &ts;
diff --git a/boost/asio/detail/impl/null_event.ipp b/boost/asio/detail/impl/null_event.ipp
new file mode 100644
index 0000000000..fb9f2e2ed2
--- /dev/null
+++ b/boost/asio/detail/impl/null_event.ipp
@@ -0,0 +1,76 @@
+//
+// detail/impl/null_event.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_IMPL_NULL_EVENT_IPP
+#define BOOST_ASIO_DETAIL_IMPL_NULL_EVENT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <thread>
+#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+# include <boost/asio/detail/socket_types.hpp>
+#else
+# include <unistd.h>
+# if defined(__hpux)
+# include <sys/time.h>
+# endif
+# if !defined(__hpux) || defined(__SELECT)
+# include <sys/select.h>
+# endif
+#endif
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+void null_event::do_wait()
+{
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ std::this_thread::sleep_until((std::chrono::steady_clock::time_point::max)());
+#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ ::Sleep(INFINITE);
+#else
+ ::pause();
+#endif
+}
+
+void null_event::do_wait_for_usec(long usec)
+{
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ std::this_thread::sleep_for(std::chrono::microseconds(usec));
+#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ ::Sleep(usec / 1000);
+#elif defined(__hpux) && defined(__SELECT)
+ timespec ts;
+ ts.tv_sec = usec / 1000000;
+ ts.tv_nsec = (usec % 1000000) * 1000;
+ ::pselect(0, 0, 0, 0, &ts, 0);
+#else
+ timeval tv;
+ tv.tv_sec = usec / 1000000;
+ tv.tv_usec = usec % 1000000;
+ ::select(0, 0, 0, 0, &tv);
+#endif
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_IMPL_NULL_EVENT_IPP
diff --git a/boost/asio/detail/impl/posix_event.ipp b/boost/asio/detail/impl/posix_event.ipp
index 3b465ca3cd..4ff246f301 100644
--- a/boost/asio/detail/impl/posix_event.ipp
+++ b/boost/asio/detail/impl/posix_event.ipp
@@ -32,7 +32,19 @@ namespace detail {
posix_event::posix_event()
: state_(0)
{
+#if (defined(__MACH__) && defined(__APPLE__)) \
+ || (defined(__ANDROID__) && (__ANDROID_API__ < 21))
int error = ::pthread_cond_init(&cond_, 0);
+#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);
+ if (error == 0)
+ error = ::pthread_cond_init(&cond_, &attr);
+#endif // (defined(__MACH__) && defined(__APPLE__))
+ // || (defined(__ANDROID__) && (__ANDROID_API__ < 21))
+
boost::system::error_code ec(error,
boost::asio::error::get_system_category());
boost::asio::detail::throw_error(ec, "event");
diff --git a/boost/asio/detail/impl/posix_thread.ipp b/boost/asio/detail/impl/posix_thread.ipp
index 66cb18da33..66a6792a4a 100644
--- a/boost/asio/detail/impl/posix_thread.ipp
+++ b/boost/asio/detail/impl/posix_thread.ipp
@@ -44,6 +44,16 @@ void posix_thread::join()
}
}
+std::size_t posix_thread::hardware_concurrency()
+{
+#if defined(_SC_NPROCESSORS_ONLN)
+ long result = sysconf(_SC_NPROCESSORS_ONLN);
+ if (result > 0)
+ return result;
+#endif // defined(_SC_NPROCESSORS_ONLN)
+ return 0;
+}
+
void posix_thread::start_thread(func_base* arg)
{
int error = ::pthread_create(&thread_, 0,
diff --git a/boost/asio/detail/impl/reactive_descriptor_service.ipp b/boost/asio/detail/impl/reactive_descriptor_service.ipp
index a0300c47d0..ffb623839f 100644
--- a/boost/asio/detail/impl/reactive_descriptor_service.ipp
+++ b/boost/asio/detail/impl/reactive_descriptor_service.ipp
@@ -31,13 +31,14 @@ namespace asio {
namespace detail {
reactive_descriptor_service::reactive_descriptor_service(
- boost::asio::io_service& io_service)
- : reactor_(boost::asio::use_service<reactor>(io_service))
+ boost::asio::io_context& io_context)
+ : service_base<reactive_descriptor_service>(io_context),
+ reactor_(boost::asio::use_service<reactor>(io_context))
{
reactor_.init_task();
}
-void reactive_descriptor_service::shutdown_service()
+void reactive_descriptor_service::shutdown()
{
}
@@ -84,7 +85,8 @@ void reactive_descriptor_service::destroy(
{
if (is_open(impl))
{
- BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "close"));
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "descriptor", &impl, impl.descriptor_, "close"));
reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_,
(impl.state_ & descriptor_ops::possible_dup) == 0);
@@ -126,7 +128,8 @@ boost::system::error_code reactive_descriptor_service::close(
{
if (is_open(impl))
{
- BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "close"));
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "descriptor", &impl, impl.descriptor_, "close"));
reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_,
(impl.state_ & descriptor_ops::possible_dup) == 0);
@@ -159,7 +162,8 @@ reactive_descriptor_service::release(
if (is_open(impl))
{
- BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "release"));
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "descriptor", &impl, impl.descriptor_, "release"));
reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, false);
reactor_.cleanup_descriptor_data(impl.reactor_data_);
@@ -179,7 +183,8 @@ boost::system::error_code reactive_descriptor_service::cancel(
return ec;
}
- BOOST_ASIO_HANDLER_OPERATION(("descriptor", &impl, "cancel"));
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "descriptor", &impl, impl.descriptor_, "cancel"));
reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_);
ec = boost::system::error_code();
diff --git a/boost/asio/detail/impl/reactive_serial_port_service.ipp b/boost/asio/detail/impl/reactive_serial_port_service.ipp
index ffa8857ab6..ffd2a2b558 100644
--- a/boost/asio/detail/impl/reactive_serial_port_service.ipp
+++ b/boost/asio/detail/impl/reactive_serial_port_service.ipp
@@ -31,14 +31,15 @@ namespace asio {
namespace detail {
reactive_serial_port_service::reactive_serial_port_service(
- boost::asio::io_service& io_service)
- : descriptor_service_(io_service)
+ boost::asio::io_context& io_context)
+ : service_base<reactive_serial_port_service>(io_context),
+ descriptor_service_(io_context)
{
}
-void reactive_serial_port_service::shutdown_service()
+void reactive_serial_port_service::shutdown()
{
- descriptor_service_.shutdown_service();
+ descriptor_service_.shutdown();
}
boost::system::error_code reactive_serial_port_service::open(
@@ -73,7 +74,7 @@ boost::system::error_code reactive_serial_port_service::open(
s = descriptor_ops::error_wrapper(::tcgetattr(fd, &ios), ec);
if (s >= 0)
{
-#if defined(_BSD_SOURCE)
+#if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
::cfmakeraw(&ios);
#else
ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK
diff --git a/boost/asio/detail/impl/reactive_socket_service_base.ipp b/boost/asio/detail/impl/reactive_socket_service_base.ipp
index 3594ae0528..23dbbb583c 100644
--- a/boost/asio/detail/impl/reactive_socket_service_base.ipp
+++ b/boost/asio/detail/impl/reactive_socket_service_base.ipp
@@ -29,13 +29,14 @@ namespace asio {
namespace detail {
reactive_socket_service_base::reactive_socket_service_base(
- boost::asio::io_service& io_service)
- : reactor_(use_service<reactor>(io_service))
+ boost::asio::io_context& io_context)
+ : io_context_(io_context),
+ reactor_(use_service<reactor>(io_context))
{
reactor_.init_task();
}
-void reactive_socket_service_base::shutdown_service()
+void reactive_socket_service_base::base_shutdown()
{
}
@@ -82,7 +83,8 @@ void reactive_socket_service_base::destroy(
{
if (impl.socket_ != invalid_socket)
{
- BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "close"));
reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
(impl.state_ & socket_ops::possible_dup) == 0);
@@ -100,7 +102,8 @@ boost::system::error_code reactive_socket_service_base::close(
{
if (is_open(impl))
{
- BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "close"));
reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,
(impl.state_ & socket_ops::possible_dup) == 0);
@@ -127,6 +130,27 @@ boost::system::error_code reactive_socket_service_base::close(
return ec;
}
+socket_type reactive_socket_service_base::release(
+ reactive_socket_service_base::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return invalid_socket;
+ }
+
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "release"));
+
+ reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false);
+ reactor_.cleanup_descriptor_data(impl.reactor_data_);
+ socket_type sock = impl.socket_;
+ construct(impl);
+ ec = boost::system::error_code();
+ return sock;
+}
+
boost::system::error_code reactive_socket_service_base::cancel(
reactive_socket_service_base::base_implementation_type& impl,
boost::system::error_code& ec)
@@ -137,7 +161,8 @@ boost::system::error_code reactive_socket_service_base::cancel(
return ec;
}
- BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "cancel"));
+ BOOST_ASIO_HANDLER_OPERATION((reactor_.context(),
+ "socket", &impl, impl.socket_, "cancel"));
reactor_.cancel_ops(impl.socket_, impl.reactor_data_);
ec = boost::system::error_code();
diff --git a/boost/asio/detail/impl/resolver_service_base.ipp b/boost/asio/detail/impl/resolver_service_base.ipp
index 4ef66cde15..1dbbd20c3f 100644
--- a/boost/asio/detail/impl/resolver_service_base.ipp
+++ b/boost/asio/detail/impl/resolver_service_base.ipp
@@ -24,62 +24,62 @@ namespace boost {
namespace asio {
namespace detail {
-class resolver_service_base::work_io_service_runner
+class resolver_service_base::work_io_context_runner
{
public:
- work_io_service_runner(boost::asio::io_service& io_service)
- : io_service_(io_service) {}
- void operator()() { io_service_.run(); }
+ work_io_context_runner(boost::asio::io_context& io_context)
+ : io_context_(io_context) {}
+ void operator()() { io_context_.run(); }
private:
- boost::asio::io_service& io_service_;
+ boost::asio::io_context& io_context_;
};
resolver_service_base::resolver_service_base(
- boost::asio::io_service& io_service)
- : io_service_impl_(boost::asio::use_service<io_service_impl>(io_service)),
- work_io_service_(new boost::asio::io_service),
- work_io_service_impl_(boost::asio::use_service<
- io_service_impl>(*work_io_service_)),
- work_(new boost::asio::io_service::work(*work_io_service_)),
+ boost::asio::io_context& io_context)
+ : io_context_impl_(boost::asio::use_service<io_context_impl>(io_context)),
+ work_io_context_(new boost::asio::io_context(-1)),
+ work_io_context_impl_(boost::asio::use_service<
+ io_context_impl>(*work_io_context_)),
+ work_(boost::asio::make_work_guard(*work_io_context_)),
work_thread_(0)
{
}
resolver_service_base::~resolver_service_base()
{
- shutdown_service();
+ base_shutdown();
}
-void resolver_service_base::shutdown_service()
+void resolver_service_base::base_shutdown()
{
work_.reset();
- if (work_io_service_.get())
+ if (work_io_context_.get())
{
- work_io_service_->stop();
+ work_io_context_->stop();
if (work_thread_.get())
{
work_thread_->join();
work_thread_.reset();
}
- work_io_service_.reset();
+ work_io_context_.reset();
}
}
-void resolver_service_base::fork_service(
- boost::asio::io_service::fork_event fork_ev)
+void resolver_service_base::base_notify_fork(
+ boost::asio::io_context::fork_event fork_ev)
{
if (work_thread_.get())
{
- if (fork_ev == boost::asio::io_service::fork_prepare)
+ if (fork_ev == boost::asio::io_context::fork_prepare)
{
- work_io_service_->stop();
+ work_io_context_->stop();
work_thread_->join();
}
else
{
- work_io_service_->reset();
+ work_io_context_->restart();
work_thread_.reset(new boost::asio::detail::thread(
- work_io_service_runner(*work_io_service_)));
+ work_io_context_runner(*work_io_context_)));
}
}
}
@@ -93,24 +93,48 @@ void resolver_service_base::construct(
void resolver_service_base::destroy(
resolver_service_base::implementation_type& impl)
{
- BOOST_ASIO_HANDLER_OPERATION(("resolver", &impl, "cancel"));
+ BOOST_ASIO_HANDLER_OPERATION((io_context_impl_.context(),
+ "resolver", &impl, 0, "cancel"));
impl.reset();
}
+void resolver_service_base::move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+{
+ impl = BOOST_ASIO_MOVE_CAST(implementation_type)(other_impl);
+}
+
+void resolver_service_base::move_assign(implementation_type& impl,
+ resolver_service_base&, implementation_type& other_impl)
+{
+ destroy(impl);
+ impl = BOOST_ASIO_MOVE_CAST(implementation_type)(other_impl);
+}
+
void resolver_service_base::cancel(
resolver_service_base::implementation_type& impl)
{
- BOOST_ASIO_HANDLER_OPERATION(("resolver", &impl, "cancel"));
+ BOOST_ASIO_HANDLER_OPERATION((io_context_impl_.context(),
+ "resolver", &impl, 0, "cancel"));
impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());
}
-void resolver_service_base::start_resolve_op(operation* op)
+void resolver_service_base::start_resolve_op(resolve_op* op)
{
- start_work_thread();
- io_service_impl_.work_started();
- work_io_service_impl_.post_immediate_completion(op, false);
+ if (BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,
+ io_context_impl_.concurrency_hint()))
+ {
+ start_work_thread();
+ io_context_impl_.work_started();
+ work_io_context_impl_.post_immediate_completion(op, false);
+ }
+ else
+ {
+ op->ec_ = boost::asio::error::operation_not_supported;
+ io_context_impl_.post_immediate_completion(op, false);
+ }
}
void resolver_service_base::start_work_thread()
@@ -119,7 +143,7 @@ void resolver_service_base::start_work_thread()
if (!work_thread_.get())
{
work_thread_.reset(new boost::asio::detail::thread(
- work_io_service_runner(*work_io_service_)));
+ work_io_context_runner(*work_io_context_)));
}
}
diff --git a/boost/asio/detail/impl/task_io_service.ipp b/boost/asio/detail/impl/scheduler.ipp
index bc83fd4757..7af3907016 100644
--- a/boost/asio/detail/impl/task_io_service.ipp
+++ b/boost/asio/detail/impl/scheduler.ipp
@@ -1,6 +1,6 @@
//
-// detail/impl/task_io_service.ipp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/impl/scheduler.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
@@ -8,8 +8,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP
-#define BOOST_ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP
+#ifndef BOOST_ASIO_DETAIL_IMPL_SCHEDULER_IPP
+#define BOOST_ASIO_DETAIL_IMPL_SCHEDULER_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
@@ -17,13 +17,12 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_HAS_IOCP)
-
+#include <boost/asio/detail/concurrency_hint.hpp>
#include <boost/asio/detail/event.hpp>
#include <boost/asio/detail/limits.hpp>
#include <boost/asio/detail/reactor.hpp>
-#include <boost/asio/detail/task_io_service.hpp>
-#include <boost/asio/detail/task_io_service_thread_info.hpp>
+#include <boost/asio/detail/scheduler.hpp>
+#include <boost/asio/detail/scheduler_thread_info.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -31,14 +30,14 @@ namespace boost {
namespace asio {
namespace detail {
-struct task_io_service::task_cleanup
+struct scheduler::task_cleanup
{
~task_cleanup()
{
if (this_thread_->private_outstanding_work > 0)
{
boost::asio::detail::increment(
- task_io_service_->outstanding_work_,
+ scheduler_->outstanding_work_,
this_thread_->private_outstanding_work);
}
this_thread_->private_outstanding_work = 0;
@@ -46,29 +45,29 @@ struct task_io_service::task_cleanup
// Enqueue the completed operations and reinsert the task at the end of
// the operation queue.
lock_->lock();
- task_io_service_->task_interrupted_ = true;
- task_io_service_->op_queue_.push(this_thread_->private_op_queue);
- task_io_service_->op_queue_.push(&task_io_service_->task_operation_);
+ scheduler_->task_interrupted_ = true;
+ scheduler_->op_queue_.push(this_thread_->private_op_queue);
+ scheduler_->op_queue_.push(&scheduler_->task_operation_);
}
- task_io_service* task_io_service_;
+ scheduler* scheduler_;
mutex::scoped_lock* lock_;
thread_info* this_thread_;
};
-struct task_io_service::work_cleanup
+struct scheduler::work_cleanup
{
~work_cleanup()
{
if (this_thread_->private_outstanding_work > 1)
{
boost::asio::detail::increment(
- task_io_service_->outstanding_work_,
+ scheduler_->outstanding_work_,
this_thread_->private_outstanding_work - 1);
}
else if (this_thread_->private_outstanding_work < 1)
{
- task_io_service_->work_finished();
+ scheduler_->work_finished();
}
this_thread_->private_outstanding_work = 0;
@@ -76,31 +75,37 @@ struct task_io_service::work_cleanup
if (!this_thread_->private_op_queue.empty())
{
lock_->lock();
- task_io_service_->op_queue_.push(this_thread_->private_op_queue);
+ scheduler_->op_queue_.push(this_thread_->private_op_queue);
}
#endif // defined(BOOST_ASIO_HAS_THREADS)
}
- task_io_service* task_io_service_;
+ scheduler* scheduler_;
mutex::scoped_lock* lock_;
thread_info* this_thread_;
};
-task_io_service::task_io_service(
- boost::asio::io_service& io_service, std::size_t concurrency_hint)
- : boost::asio::detail::service_base<task_io_service>(io_service),
- one_thread_(concurrency_hint == 1),
- mutex_(),
+scheduler::scheduler(
+ boost::asio::execution_context& ctx, int concurrency_hint)
+ : boost::asio::detail::execution_context_service_base<scheduler>(ctx),
+ one_thread_(concurrency_hint == 1
+ || !BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
+ SCHEDULER, concurrency_hint)
+ || !BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
+ REACTOR_IO, concurrency_hint)),
+ mutex_(BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
+ SCHEDULER, concurrency_hint)),
task_(0),
task_interrupted_(true),
outstanding_work_(0),
stopped_(false),
- shutdown_(false)
+ shutdown_(false),
+ concurrency_hint_(concurrency_hint)
{
BOOST_ASIO_HANDLER_TRACKING_INIT;
}
-void task_io_service::shutdown_service()
+void scheduler::shutdown()
{
mutex::scoped_lock lock(mutex_);
shutdown_ = true;
@@ -119,18 +124,18 @@ void task_io_service::shutdown_service()
task_ = 0;
}
-void task_io_service::init_task()
+void scheduler::init_task()
{
mutex::scoped_lock lock(mutex_);
if (!shutdown_ && !task_)
{
- task_ = &use_service<reactor>(this->get_io_service());
+ task_ = &use_service<reactor>(this->context());
op_queue_.push(&task_operation_);
wake_one_thread_and_unlock(lock);
}
}
-std::size_t task_io_service::run(boost::system::error_code& ec)
+std::size_t scheduler::run(boost::system::error_code& ec)
{
ec = boost::system::error_code();
if (outstanding_work_ == 0)
@@ -152,7 +157,7 @@ std::size_t task_io_service::run(boost::system::error_code& ec)
return n;
}
-std::size_t task_io_service::run_one(boost::system::error_code& ec)
+std::size_t scheduler::run_one(boost::system::error_code& ec)
{
ec = boost::system::error_code();
if (outstanding_work_ == 0)
@@ -170,7 +175,25 @@ std::size_t task_io_service::run_one(boost::system::error_code& ec)
return do_run_one(lock, this_thread, ec);
}
-std::size_t task_io_service::poll(boost::system::error_code& ec)
+std::size_t scheduler::wait_one(long usec, boost::system::error_code& ec)
+{
+ ec = boost::system::error_code();
+ if (outstanding_work_ == 0)
+ {
+ stop();
+ return 0;
+ }
+
+ thread_info this_thread;
+ this_thread.private_outstanding_work = 0;
+ thread_call_stack::context ctx(this, this_thread);
+
+ mutex::scoped_lock lock(mutex_);
+
+ return do_wait_one(lock, this_thread, usec, ec);
+}
+
+std::size_t scheduler::poll(boost::system::error_code& ec)
{
ec = boost::system::error_code();
if (outstanding_work_ == 0)
@@ -190,8 +213,8 @@ std::size_t task_io_service::poll(boost::system::error_code& ec)
// that are already on a thread-private queue need to be put on to the main
// queue now.
if (one_thread_)
- if (thread_info* outer_thread_info = ctx.next_by_key())
- op_queue_.push(outer_thread_info->private_op_queue);
+ if (thread_info* outer_info = static_cast<thread_info*>(ctx.next_by_key()))
+ op_queue_.push(outer_info->private_op_queue);
#endif // defined(BOOST_ASIO_HAS_THREADS)
std::size_t n = 0;
@@ -201,7 +224,7 @@ std::size_t task_io_service::poll(boost::system::error_code& ec)
return n;
}
-std::size_t task_io_service::poll_one(boost::system::error_code& ec)
+std::size_t scheduler::poll_one(boost::system::error_code& ec)
{
ec = boost::system::error_code();
if (outstanding_work_ == 0)
@@ -221,41 +244,47 @@ std::size_t task_io_service::poll_one(boost::system::error_code& ec)
// that are already on a thread-private queue need to be put on to the main
// queue now.
if (one_thread_)
- if (thread_info* outer_thread_info = ctx.next_by_key())
- op_queue_.push(outer_thread_info->private_op_queue);
+ if (thread_info* outer_info = static_cast<thread_info*>(ctx.next_by_key()))
+ op_queue_.push(outer_info->private_op_queue);
#endif // defined(BOOST_ASIO_HAS_THREADS)
return do_poll_one(lock, this_thread, ec);
}
-void task_io_service::stop()
+void scheduler::stop()
{
mutex::scoped_lock lock(mutex_);
stop_all_threads(lock);
}
-bool task_io_service::stopped() const
+bool scheduler::stopped() const
{
mutex::scoped_lock lock(mutex_);
return stopped_;
}
-void task_io_service::reset()
+void scheduler::restart()
{
mutex::scoped_lock lock(mutex_);
stopped_ = false;
}
-void task_io_service::post_immediate_completion(
- task_io_service::operation* op, bool is_continuation)
+void scheduler::compensating_work_started()
+{
+ thread_info_base* this_thread = thread_call_stack::contains(this);
+ ++static_cast<thread_info*>(this_thread)->private_outstanding_work;
+}
+
+void scheduler::post_immediate_completion(
+ scheduler::operation* op, bool is_continuation)
{
#if defined(BOOST_ASIO_HAS_THREADS)
if (one_thread_ || is_continuation)
{
- if (thread_info* this_thread = thread_call_stack::contains(this))
+ if (thread_info_base* this_thread = thread_call_stack::contains(this))
{
- ++this_thread->private_outstanding_work;
- this_thread->private_op_queue.push(op);
+ ++static_cast<thread_info*>(this_thread)->private_outstanding_work;
+ static_cast<thread_info*>(this_thread)->private_op_queue.push(op);
return;
}
}
@@ -269,14 +298,14 @@ void task_io_service::post_immediate_completion(
wake_one_thread_and_unlock(lock);
}
-void task_io_service::post_deferred_completion(task_io_service::operation* op)
+void scheduler::post_deferred_completion(scheduler::operation* op)
{
#if defined(BOOST_ASIO_HAS_THREADS)
if (one_thread_)
{
- if (thread_info* this_thread = thread_call_stack::contains(this))
+ if (thread_info_base* this_thread = thread_call_stack::contains(this))
{
- this_thread->private_op_queue.push(op);
+ static_cast<thread_info*>(this_thread)->private_op_queue.push(op);
return;
}
}
@@ -287,17 +316,17 @@ void task_io_service::post_deferred_completion(task_io_service::operation* op)
wake_one_thread_and_unlock(lock);
}
-void task_io_service::post_deferred_completions(
- op_queue<task_io_service::operation>& ops)
+void scheduler::post_deferred_completions(
+ op_queue<scheduler::operation>& ops)
{
if (!ops.empty())
{
#if defined(BOOST_ASIO_HAS_THREADS)
if (one_thread_)
{
- if (thread_info* this_thread = thread_call_stack::contains(this))
+ if (thread_info_base* this_thread = thread_call_stack::contains(this))
{
- this_thread->private_op_queue.push(ops);
+ static_cast<thread_info*>(this_thread)->private_op_queue.push(ops);
return;
}
}
@@ -309,8 +338,8 @@ void task_io_service::post_deferred_completions(
}
}
-void task_io_service::do_dispatch(
- task_io_service::operation* op)
+void scheduler::do_dispatch(
+ scheduler::operation* op)
{
work_started();
mutex::scoped_lock lock(mutex_);
@@ -318,15 +347,15 @@ void task_io_service::do_dispatch(
wake_one_thread_and_unlock(lock);
}
-void task_io_service::abandon_operations(
- op_queue<task_io_service::operation>& ops)
+void scheduler::abandon_operations(
+ op_queue<scheduler::operation>& ops)
{
- op_queue<task_io_service::operation> ops2;
+ op_queue<scheduler::operation> ops2;
ops2.push(ops);
}
-std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
- task_io_service::thread_info& this_thread,
+std::size_t scheduler::do_run_one(mutex::scoped_lock& lock,
+ scheduler::thread_info& this_thread,
const boost::system::error_code& ec)
{
while (!stopped_)
@@ -353,7 +382,7 @@ std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
// Run the task. May throw an exception. Only block if the operation
// queue is empty and we're not polling, otherwise we want to return
// as soon as possible.
- task_->run(!more_handlers, this_thread.private_op_queue);
+ task_->run(more_handlers ? 0 : -1, this_thread.private_op_queue);
}
else
{
@@ -369,7 +398,7 @@ std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
(void)on_exit;
// Complete the operation. May throw an exception. Deletes the object.
- o->complete(*this, ec, task_result);
+ o->complete(this, ec, task_result);
return 1;
}
@@ -384,8 +413,78 @@ std::size_t task_io_service::do_run_one(mutex::scoped_lock& lock,
return 0;
}
-std::size_t task_io_service::do_poll_one(mutex::scoped_lock& lock,
- task_io_service::thread_info& this_thread,
+std::size_t scheduler::do_wait_one(mutex::scoped_lock& lock,
+ scheduler::thread_info& this_thread, long usec,
+ const boost::system::error_code& ec)
+{
+ if (stopped_)
+ return 0;
+
+ operation* o = op_queue_.front();
+ if (o == 0)
+ {
+ wakeup_event_.clear(lock);
+ wakeup_event_.wait_for_usec(lock, usec);
+ usec = 0; // Wait at most once.
+ o = op_queue_.front();
+ }
+
+ if (o == &task_operation_)
+ {
+ op_queue_.pop();
+ bool more_handlers = (!op_queue_.empty());
+
+ task_interrupted_ = more_handlers;
+
+ if (more_handlers && !one_thread_)
+ wakeup_event_.unlock_and_signal_one(lock);
+ else
+ lock.unlock();
+
+ {
+ task_cleanup on_exit = { this, &lock, &this_thread };
+ (void)on_exit;
+
+ // Run the task. May throw an exception. Only block if the operation
+ // queue is empty and we're not polling, otherwise we want to return
+ // as soon as possible.
+ task_->run(more_handlers ? 0 : usec, this_thread.private_op_queue);
+ }
+
+ o = op_queue_.front();
+ if (o == &task_operation_)
+ {
+ if (!one_thread_)
+ wakeup_event_.maybe_unlock_and_signal_one(lock);
+ return 0;
+ }
+ }
+
+ if (o == 0)
+ return 0;
+
+ op_queue_.pop();
+ bool more_handlers = (!op_queue_.empty());
+
+ std::size_t task_result = o->task_result_;
+
+ if (more_handlers && !one_thread_)
+ wake_one_thread_and_unlock(lock);
+ else
+ lock.unlock();
+
+ // Ensure the count of outstanding work is decremented on block exit.
+ work_cleanup on_exit = { this, &lock, &this_thread };
+ (void)on_exit;
+
+ // Complete the operation. May throw an exception. Deletes the object.
+ o->complete(this, ec, task_result);
+
+ return 1;
+}
+
+std::size_t scheduler::do_poll_one(mutex::scoped_lock& lock,
+ scheduler::thread_info& this_thread,
const boost::system::error_code& ec)
{
if (stopped_)
@@ -404,7 +503,7 @@ std::size_t task_io_service::do_poll_one(mutex::scoped_lock& lock,
// Run the task. May throw an exception. Only block if the operation
// queue is empty and we're not polling, otherwise we want to return
// as soon as possible.
- task_->run(false, this_thread.private_op_queue);
+ task_->run(0, this_thread.private_op_queue);
}
o = op_queue_.front();
@@ -433,12 +532,12 @@ std::size_t task_io_service::do_poll_one(mutex::scoped_lock& lock,
(void)on_exit;
// Complete the operation. May throw an exception. Deletes the object.
- o->complete(*this, ec, task_result);
+ o->complete(this, ec, task_result);
return 1;
}
-void task_io_service::stop_all_threads(
+void scheduler::stop_all_threads(
mutex::scoped_lock& lock)
{
stopped_ = true;
@@ -451,7 +550,7 @@ void task_io_service::stop_all_threads(
}
}
-void task_io_service::wake_one_thread_and_unlock(
+void scheduler::wake_one_thread_and_unlock(
mutex::scoped_lock& lock)
{
if (!wakeup_event_.maybe_unlock_and_signal_one(lock))
@@ -471,6 +570,4 @@ void task_io_service::wake_one_thread_and_unlock(
#include <boost/asio/detail/pop_options.hpp>
-#endif // !defined(BOOST_ASIO_HAS_IOCP)
-
-#endif // BOOST_ASIO_DETAIL_IMPL_TASK_IO_SERVICE_IPP
+#endif // BOOST_ASIO_DETAIL_IMPL_SCHEDULER_IPP
diff --git a/boost/asio/detail/impl/select_reactor.hpp b/boost/asio/detail/impl/select_reactor.hpp
index d3f28f5e61..207a045f6c 100644
--- a/boost/asio/detail/impl/select_reactor.hpp
+++ b/boost/asio/detail/impl/select_reactor.hpp
@@ -51,12 +51,12 @@ void select_reactor::schedule_timer(timer_queue<Time_Traits>& queue,
if (shutdown_)
{
- io_service_.post_immediate_completion(op, false);
+ scheduler_.post_immediate_completion(op, false);
return;
}
bool earliest = queue.enqueue_timer(time, timer, op);
- io_service_.work_started();
+ scheduler_.work_started();
if (earliest)
interrupter_.interrupt();
}
@@ -70,10 +70,23 @@ std::size_t select_reactor::cancel_timer(timer_queue<Time_Traits>& queue,
op_queue<operation> ops;
std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
lock.unlock();
- io_service_.post_deferred_completions(ops);
+ scheduler_.post_deferred_completions(ops);
return n;
}
+template <typename Time_Traits>
+void select_reactor::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)
+{
+ boost::asio::detail::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
} // namespace boost
diff --git a/boost/asio/detail/impl/select_reactor.ipp b/boost/asio/detail/impl/select_reactor.ipp
index 869f73492b..44fab64269 100644
--- a/boost/asio/detail/impl/select_reactor.ipp
+++ b/boost/asio/detail/impl/select_reactor.ipp
@@ -23,7 +23,6 @@
&& !defined(BOOST_ASIO_HAS_KQUEUE) \
&& !defined(BOOST_ASIO_WINDOWS_RUNTIME))
-#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/fd_set_adapter.hpp>
#include <boost/asio/detail/select_reactor.hpp>
#include <boost/asio/detail/signal_blocker.hpp>
@@ -35,9 +34,28 @@ namespace boost {
namespace asio {
namespace detail {
-select_reactor::select_reactor(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<select_reactor>(io_service),
- io_service_(use_service<io_service_impl>(io_service)),
+#if defined(BOOST_ASIO_HAS_IOCP)
+class select_reactor::thread_function
+{
+public:
+ explicit thread_function(select_reactor* r)
+ : this_(r)
+ {
+ }
+
+ void operator()()
+ {
+ this_->run_thread();
+ }
+
+private:
+ select_reactor* this_;
+};
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+select_reactor::select_reactor(boost::asio::execution_context& ctx)
+ : execution_context_service_base<select_reactor>(ctx),
+ scheduler_(use_service<scheduler_type>(ctx)),
mutex_(),
interrupter_(),
#if defined(BOOST_ASIO_HAS_IOCP)
@@ -48,17 +66,16 @@ select_reactor::select_reactor(boost::asio::io_service& io_service)
{
#if defined(BOOST_ASIO_HAS_IOCP)
boost::asio::detail::signal_blocker sb;
- thread_ = new boost::asio::detail::thread(
- bind_handler(&select_reactor::call_run_thread, this));
+ thread_ = new boost::asio::detail::thread(thread_function(this));
#endif // defined(BOOST_ASIO_HAS_IOCP)
}
select_reactor::~select_reactor()
{
- shutdown_service();
+ shutdown();
}
-void select_reactor::shutdown_service()
+void select_reactor::shutdown()
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
shutdown_ = true;
@@ -84,18 +101,19 @@ void select_reactor::shutdown_service()
timer_queues_.get_all_timers(ops);
- io_service_.abandon_operations(ops);
+ scheduler_.abandon_operations(ops);
}
-void select_reactor::fork_service(boost::asio::io_service::fork_event fork_ev)
+void select_reactor::notify_fork(
+ boost::asio::execution_context::fork_event fork_ev)
{
- if (fork_ev == boost::asio::io_service::fork_child)
+ if (fork_ev == boost::asio::execution_context::fork_child)
interrupter_.recreate();
}
void select_reactor::init_task()
{
- io_service_.init_task();
+ scheduler_.init_task();
}
int select_reactor::register_descriptor(socket_type,
@@ -135,7 +153,7 @@ void select_reactor::start_op(int op_type, socket_type descriptor,
}
bool first = op_queue_[op_type].enqueue_operation(descriptor, op);
- io_service_.work_started();
+ scheduler_.work_started();
if (first)
interrupter_.interrupt();
}
@@ -168,7 +186,7 @@ void select_reactor::cleanup_descriptor_data(
{
}
-void select_reactor::run(bool block, op_queue<operation>& ops)
+void select_reactor::run(long usec, op_queue<operation>& ops)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
@@ -205,12 +223,12 @@ void select_reactor::run(bool block, op_queue<operation>& ops)
// We can return immediately if there's no work to do and the reactor is
// not supposed to block.
- if (!block && !have_work_to_do)
+ if (!usec && !have_work_to_do)
return;
// Determine how long to block while waiting for events.
timeval tv_buf = { 0, 0 };
- timeval* tv = block ? get_timeout(tv_buf) : &tv_buf;
+ timeval* tv = usec ? get_timeout(usec, tv_buf) : &tv_buf;
lock.unlock();
@@ -259,15 +277,10 @@ void select_reactor::run_thread()
lock.unlock();
op_queue<operation> ops;
run(true, ops);
- io_service_.post_deferred_completions(ops);
+ scheduler_.post_deferred_completions(ops);
lock.lock();
}
}
-
-void select_reactor::call_run_thread(select_reactor* reactor)
-{
- reactor->run_thread();
-}
#endif // defined(BOOST_ASIO_HAS_IOCP)
void select_reactor::do_add_timer_queue(timer_queue_base& queue)
@@ -282,11 +295,13 @@ void select_reactor::do_remove_timer_queue(timer_queue_base& queue)
timer_queues_.erase(&queue);
}
-timeval* select_reactor::get_timeout(timeval& tv)
+timeval* select_reactor::get_timeout(long usec, timeval& tv)
{
// By default we will wait no longer than 5 minutes. This will ensure that
// any changes to the system clock are detected after no longer than this.
- long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);
+ const long max_usec = 5 * 60 * 1000 * 1000;
+ usec = timer_queues_.wait_duration_usec(
+ (usec < 0 || max_usec < usec) ? max_usec : usec);
tv.tv_sec = usec / 1000000;
tv.tv_usec = usec % 1000000;
return &tv;
@@ -300,7 +315,7 @@ void select_reactor::cancel_ops_unlocked(socket_type descriptor,
for (int i = 0; i < max_ops; ++i)
need_interrupt = op_queue_[i].cancel_operations(
descriptor, ops, ec) || need_interrupt;
- io_service_.post_deferred_completions(ops);
+ scheduler_.post_deferred_completions(ops);
if (need_interrupt)
interrupter_.interrupt();
}
diff --git a/boost/asio/detail/impl/service_registry.hpp b/boost/asio/detail/impl/service_registry.hpp
index 7ffdd029f7..11ad4cf5cc 100644
--- a/boost/asio/detail/impl/service_registry.hpp
+++ b/boost/asio/detail/impl/service_registry.hpp
@@ -21,64 +21,70 @@ namespace boost {
namespace asio {
namespace detail {
-template <typename Service, typename Arg>
-service_registry::service_registry(
- boost::asio::io_service& o, Service*, Arg arg)
- : owner_(o),
- first_service_(new Service(o, arg))
-{
- boost::asio::io_service::service::key key;
- init_key(key, Service::id);
- first_service_->key_ = key;
- first_service_->next_ = 0;
-}
-
template <typename Service>
-Service& service_registry::first_service()
+Service& service_registry::use_service()
{
- return *static_cast<Service*>(first_service_);
+ execution_context::service::key key;
+ init_key<Service>(key, 0);
+ factory_type factory = &service_registry::create<Service, execution_context>;
+ return *static_cast<Service*>(do_use_service(key, factory, &owner_));
}
template <typename Service>
-Service& service_registry::use_service()
+Service& service_registry::use_service(io_context& owner)
{
- boost::asio::io_service::service::key key;
- init_key(key, Service::id);
- factory_type factory = &service_registry::create<Service>;
- return *static_cast<Service*>(do_use_service(key, factory));
+ execution_context::service::key key;
+ init_key<Service>(key, 0);
+ factory_type factory = &service_registry::create<Service, io_context>;
+ return *static_cast<Service*>(do_use_service(key, factory, &owner));
}
template <typename Service>
void service_registry::add_service(Service* new_service)
{
- boost::asio::io_service::service::key key;
- init_key(key, Service::id);
+ execution_context::service::key key;
+ init_key<Service>(key, 0);
return do_add_service(key, new_service);
}
template <typename Service>
bool service_registry::has_service() const
{
- boost::asio::io_service::service::key key;
- init_key(key, Service::id);
+ execution_context::service::key key;
+ init_key<Service>(key, 0);
return do_has_service(key);
}
+template <typename Service>
+inline void service_registry::init_key(
+ execution_context::service::key& key, ...)
+{
+ init_key_from_id(key, Service::id);
+}
+
#if !defined(BOOST_ASIO_NO_TYPEID)
template <typename Service>
-void service_registry::init_key(boost::asio::io_service::service::key& key,
- const boost::asio::detail::service_id<Service>& /*id*/)
+void service_registry::init_key(execution_context::service::key& key,
+ typename enable_if<
+ is_base_of<typename Service::key_type, Service>::value>::type*)
{
key.type_info_ = &typeid(typeid_wrapper<Service>);
key.id_ = 0;
}
-#endif // !defined(BOOST_ASIO_NO_TYPEID)
template <typename Service>
-boost::asio::io_service::service* service_registry::create(
- boost::asio::io_service& owner)
+void service_registry::init_key_from_id(execution_context::service::key& key,
+ const service_id<Service>& /*id*/)
+{
+ key.type_info_ = &typeid(typeid_wrapper<Service>);
+ key.id_ = 0;
+}
+#endif // !defined(BOOST_ASIO_NO_TYPEID)
+
+template <typename Service, typename Owner>
+execution_context::service* service_registry::create(void* owner)
{
- return new Service(owner);
+ return new Service(*static_cast<Owner*>(owner));
}
} // namespace detail
diff --git a/boost/asio/detail/impl/service_registry.ipp b/boost/asio/detail/impl/service_registry.ipp
index 25ac8eccc6..75c3f45625 100644
--- a/boost/asio/detail/impl/service_registry.ipp
+++ b/boost/asio/detail/impl/service_registry.ipp
@@ -26,36 +26,45 @@ namespace boost {
namespace asio {
namespace detail {
+service_registry::service_registry(execution_context& owner)
+ : owner_(owner),
+ first_service_(0)
+{
+}
+
service_registry::~service_registry()
{
- // Shutdown all services. This must be done in a separate loop before the
- // services are destroyed since the destructors of user-defined handler
- // objects may try to access other service objects.
- boost::asio::io_service::service* service = first_service_;
+}
+
+void service_registry::shutdown_services()
+{
+ execution_context::service* service = first_service_;
while (service)
{
- service->shutdown_service();
+ service->shutdown();
service = service->next_;
}
+}
- // Destroy all services.
+void service_registry::destroy_services()
+{
while (first_service_)
{
- boost::asio::io_service::service* next_service = first_service_->next_;
+ execution_context::service* next_service = first_service_->next_;
destroy(first_service_);
first_service_ = next_service;
}
}
-void service_registry::notify_fork(boost::asio::io_service::fork_event fork_ev)
+void service_registry::notify_fork(execution_context::fork_event fork_ev)
{
// Make a copy of all of the services while holding the lock. We don't want
// to hold the lock while calling into each service, as it may try to call
// back into this class.
- std::vector<boost::asio::io_service::service*> services;
+ std::vector<execution_context::service*> services;
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
- boost::asio::io_service::service* service = first_service_;
+ execution_context::service* service = first_service_;
while (service)
{
services.push_back(service);
@@ -68,24 +77,24 @@ void service_registry::notify_fork(boost::asio::io_service::fork_event fork_ev)
// services in the vector. For the other events we want to go in the other
// direction.
std::size_t num_services = services.size();
- if (fork_ev == boost::asio::io_service::fork_prepare)
+ if (fork_ev == execution_context::fork_prepare)
for (std::size_t i = 0; i < num_services; ++i)
- services[i]->fork_service(fork_ev);
+ services[i]->notify_fork(fork_ev);
else
for (std::size_t i = num_services; i > 0; --i)
- services[i - 1]->fork_service(fork_ev);
+ services[i - 1]->notify_fork(fork_ev);
}
-void service_registry::init_key(boost::asio::io_service::service::key& key,
- const boost::asio::io_service::id& id)
+void service_registry::init_key_from_id(execution_context::service::key& key,
+ const execution_context::id& id)
{
key.type_info_ = 0;
key.id_ = &id;
}
bool service_registry::keys_match(
- const boost::asio::io_service::service::key& key1,
- const boost::asio::io_service::service::key& key2)
+ const execution_context::service::key& key1,
+ const execution_context::service::key& key2)
{
if (key1.id_ && key2.id_)
if (key1.id_ == key2.id_)
@@ -96,19 +105,19 @@ bool service_registry::keys_match(
return false;
}
-void service_registry::destroy(boost::asio::io_service::service* service)
+void service_registry::destroy(execution_context::service* service)
{
delete service;
}
-boost::asio::io_service::service* service_registry::do_use_service(
- const boost::asio::io_service::service::key& key,
- factory_type factory)
+execution_context::service* service_registry::do_use_service(
+ const execution_context::service::key& key,
+ factory_type factory, void* owner)
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
// First see if there is an existing service object with the given key.
- boost::asio::io_service::service* service = first_service_;
+ execution_context::service* service = first_service_;
while (service)
{
if (keys_match(service->key_, key))
@@ -120,7 +129,7 @@ boost::asio::io_service::service* service_registry::do_use_service(
// at this time to allow for nested calls into this function from the new
// service's constructor.
lock.unlock();
- auto_service_ptr new_service = { factory(owner_) };
+ auto_service_ptr new_service = { factory(owner) };
new_service.ptr_->key_ = key;
lock.lock();
@@ -142,16 +151,16 @@ boost::asio::io_service::service* service_registry::do_use_service(
}
void service_registry::do_add_service(
- const boost::asio::io_service::service::key& key,
- boost::asio::io_service::service* new_service)
+ const execution_context::service::key& key,
+ execution_context::service* new_service)
{
- if (&owner_ != &new_service->get_io_service())
+ if (&owner_ != &new_service->context())
boost::asio::detail::throw_exception(invalid_service_owner());
boost::asio::detail::mutex::scoped_lock lock(mutex_);
// Check if there is an existing service object with the given key.
- boost::asio::io_service::service* service = first_service_;
+ execution_context::service* service = first_service_;
while (service)
{
if (keys_match(service->key_, key))
@@ -166,11 +175,11 @@ void service_registry::do_add_service(
}
bool service_registry::do_has_service(
- const boost::asio::io_service::service::key& key) const
+ const execution_context::service::key& key) const
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
- boost::asio::io_service::service* service = first_service_;
+ execution_context::service* service = first_service_;
while (service)
{
if (keys_match(service->key_, key))
diff --git a/boost/asio/detail/impl/signal_set_service.ipp b/boost/asio/detail/impl/signal_set_service.ipp
index 95ea8bee21..376d311471 100644
--- a/boost/asio/detail/impl/signal_set_service.ipp
+++ b/boost/asio/detail/impl/signal_set_service.ipp
@@ -18,10 +18,12 @@
#include <boost/asio/detail/config.hpp>
#include <cstring>
+#include <stdexcept>
#include <boost/asio/detail/reactor.hpp>
#include <boost/asio/detail/signal_blocker.hpp>
#include <boost/asio/detail/signal_set_service.hpp>
#include <boost/asio/detail/static_mutex.hpp>
+#include <boost/asio/detail/throw_exception.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -92,7 +94,7 @@ public:
{
}
- static bool do_perform(reactor_op*)
+ static status do_perform(reactor_op*)
{
signal_state* state = get_signal_state();
@@ -102,10 +104,10 @@ public:
if (signal_number >= 0 && signal_number < max_signal_number)
signal_set_service::deliver_signal(signal_number);
- return false;
+ return not_done;
}
- static void do_complete(io_service_impl* /*owner*/, operation* base,
+ static void do_complete(void* /*owner*/, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
@@ -118,12 +120,13 @@ public:
// && !defined(__CYGWIN__)
signal_set_service::signal_set_service(
- boost::asio::io_service& io_service)
- : io_service_(boost::asio::use_service<io_service_impl>(io_service)),
+ boost::asio::io_context& io_context)
+ : service_base<signal_set_service>(io_context),
+ io_context_(boost::asio::use_service<io_context_impl>(io_context)),
#if !defined(BOOST_ASIO_WINDOWS) \
&& !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
&& !defined(__CYGWIN__)
- reactor_(boost::asio::use_service<reactor>(io_service)),
+ reactor_(boost::asio::use_service<reactor>(io_context)),
#endif // !defined(BOOST_ASIO_WINDOWS)
// && !defined(BOOST_ASIO_WINDOWS_RUNTIME)
// && !defined(__CYGWIN__)
@@ -151,7 +154,7 @@ signal_set_service::~signal_set_service()
remove_service(this);
}
-void signal_set_service::shutdown_service()
+void signal_set_service::shutdown()
{
remove_service(this);
@@ -167,11 +170,11 @@ void signal_set_service::shutdown_service()
}
}
- io_service_.abandon_operations(ops);
+ io_context_.abandon_operations(ops);
}
-void signal_set_service::fork_service(
- boost::asio::io_service::fork_event fork_ev)
+void signal_set_service::notify_fork(
+ boost::asio::io_context::fork_event fork_ev)
{
#if !defined(BOOST_ASIO_WINDOWS) \
&& !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
@@ -181,7 +184,7 @@ void signal_set_service::fork_service(
switch (fork_ev)
{
- case boost::asio::io_service::fork_prepare:
+ case boost::asio::io_context::fork_prepare:
{
int read_descriptor = state->read_descriptor_;
state->fork_prepared_ = true;
@@ -190,7 +193,7 @@ void signal_set_service::fork_service(
reactor_.cleanup_descriptor_data(reactor_data_);
}
break;
- case boost::asio::io_service::fork_parent:
+ case boost::asio::io_context::fork_parent:
if (state->fork_prepared_)
{
int read_descriptor = state->read_descriptor_;
@@ -200,7 +203,7 @@ void signal_set_service::fork_service(
read_descriptor, reactor_data_, new pipe_read_op);
}
break;
- case boost::asio::io_service::fork_child:
+ case boost::asio::io_context::fork_child:
if (state->fork_prepared_)
{
boost::asio::detail::signal_blocker blocker;
@@ -439,7 +442,8 @@ boost::system::error_code signal_set_service::cancel(
signal_set_service::implementation_type& impl,
boost::system::error_code& ec)
{
- BOOST_ASIO_HANDLER_OPERATION(("signal_set", &impl, "cancel"));
+ BOOST_ASIO_HANDLER_OPERATION((io_context_.context(),
+ "signal_set", &impl, 0, "cancel"));
op_queue<operation> ops;
{
@@ -454,7 +458,7 @@ boost::system::error_code signal_set_service::cancel(
}
}
- io_service_.post_deferred_completions(ops);
+ io_context_.post_deferred_completions(ops);
ec = boost::system::error_code();
return ec;
@@ -490,7 +494,7 @@ void signal_set_service::deliver_signal(int signal_number)
reg = reg->next_in_table_;
}
- service->io_service_.post_deferred_completions(ops);
+ service->io_context_.post_deferred_completions(ops);
service = service->next_;
}
@@ -507,6 +511,22 @@ void signal_set_service::add_service(signal_set_service* service)
open_descriptors();
#endif // !defined(BOOST_ASIO_WINDOWS) && !defined(__CYGWIN__)
+ // If an io_context object is thread-unsafe then it must be the only
+ // io_context used to create signal_set objects.
+ if (state->service_list_ != 0)
+ {
+ if (!BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,
+ service->io_context_.concurrency_hint())
+ || !BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,
+ state->service_list_->io_context_.concurrency_hint()))
+ {
+ std::logic_error ex(
+ "Thread-unsafe io_context objects require "
+ "exclusive access to signal handling.");
+ boost::asio::detail::throw_exception(ex);
+ }
+ }
+
// Insert service into linked list of all services.
service->next_ = state->service_list_;
service->prev_ = 0;
@@ -620,7 +640,7 @@ void signal_set_service::close_descriptors()
void signal_set_service::start_wait_op(
signal_set_service::implementation_type& impl, signal_op* op)
{
- io_service_.work_started();
+ io_context_.work_started();
signal_state* state = get_signal_state();
static_mutex::scoped_lock lock(state->mutex_);
@@ -632,7 +652,7 @@ void signal_set_service::start_wait_op(
{
--reg->undelivered_;
op->signal_number_ = reg->signal_number_;
- io_service_.post_deferred_completion(op);
+ io_context_.post_deferred_completion(op);
return;
}
diff --git a/boost/asio/detail/impl/socket_ops.ipp b/boost/asio/detail/impl/socket_ops.ipp
index c9683f4a09..94be0f280c 100644
--- a/boost/asio/detail/impl/socket_ops.ipp
+++ b/boost/asio/detail/impl/socket_ops.ipp
@@ -169,7 +169,7 @@ socket_type sync_accept(socket_type s, state_type state,
return invalid_socket;
// Wait for socket to become ready.
- if (socket_ops::poll_read(s, 0, ec) < 0)
+ if (socket_ops::poll_read(s, 0, -1, ec) < 0)
return invalid_socket;
}
}
@@ -242,8 +242,6 @@ bool non_blocking_accept(socket_type s,
if (ec == boost::asio::error::would_block
|| ec == boost::asio::error::try_again)
{
- if (state & user_set_non_blocking)
- return true;
// Fall through to retry operation.
}
else if (ec == boost::asio::error::connection_aborted)
@@ -506,7 +504,7 @@ void sync_connect(socket_type s, const socket_addr_type* addr,
}
// Wait for socket to become ready.
- if (socket_ops::poll_connect(s, ec) < 0)
+ if (socket_ops::poll_connect(s, -1, ec) < 0)
return;
// Get the error code from the connect operation.
@@ -773,6 +771,8 @@ signed_size_type recv(socket_type s, buf* bufs, size_t count,
ec = boost::asio::error::connection_reset;
else if (ec.value() == ERROR_PORT_UNREACHABLE)
ec = boost::asio::error::connection_refused;
+ else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
+ ec.assign(0, ec.category());
if (result != 0)
return socket_error_retval;
ec = boost::system::error_code();
@@ -828,7 +828,7 @@ size_t sync_recv(socket_type s, state_type state, buf* bufs,
return 0;
// Wait for socket to become ready.
- if (socket_ops::poll_read(s, 0, ec) < 0)
+ if (socket_ops::poll_read(s, 0, -1, ec) < 0)
return 0;
}
}
@@ -851,6 +851,10 @@ void complete_iocp_recv(state_type state,
{
ec = boost::asio::error::connection_refused;
}
+ else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
+ {
+ ec.assign(0, ec.category());
+ }
// Check for connection closed.
else if (!ec && bytes_transferred == 0
@@ -921,6 +925,8 @@ signed_size_type recvfrom(socket_type s, buf* bufs, size_t count,
ec = boost::asio::error::connection_reset;
else if (ec.value() == ERROR_PORT_UNREACHABLE)
ec = boost::asio::error::connection_refused;
+ else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
+ ec.assign(0, ec.category());
if (result != 0)
return socket_error_retval;
ec = boost::system::error_code();
@@ -967,7 +973,7 @@ size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,
return 0;
// Wait for socket to become ready.
- if (socket_ops::poll_read(s, 0, ec) < 0)
+ if (socket_ops::poll_read(s, 0, -1, ec) < 0)
return 0;
}
}
@@ -990,6 +996,10 @@ void complete_iocp_recvfrom(
{
ec = boost::asio::error::connection_refused;
}
+ else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
+ {
+ ec.assign(0, ec.category());
+ }
}
#else // defined(BOOST_ASIO_HAS_IOCP)
@@ -1080,7 +1090,7 @@ size_t sync_recvmsg(socket_type s, state_type state,
return 0;
// Wait for socket to become ready.
- if (socket_ops::poll_read(s, 0, ec) < 0)
+ if (socket_ops::poll_read(s, 0, -1, ec) < 0)
return 0;
}
}
@@ -1103,6 +1113,10 @@ void complete_iocp_recvmsg(
{
ec = boost::asio::error::connection_refused;
}
+ else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)
+ {
+ ec.assign(0, ec.category());
+ }
}
#else // defined(BOOST_ASIO_HAS_IOCP)
@@ -1207,7 +1221,7 @@ size_t sync_send(socket_type s, state_type state, const buf* bufs,
return 0;
// Wait for socket to become ready.
- if (socket_ops::poll_write(s, 0, ec) < 0)
+ if (socket_ops::poll_write(s, 0, -1, ec) < 0)
return 0;
}
}
@@ -1331,7 +1345,7 @@ size_t sync_sendto(socket_type s, state_type state, const buf* bufs,
return 0;
// Wait for socket to become ready.
- if (socket_ops::poll_write(s, 0, ec) < 0)
+ if (socket_ops::poll_write(s, 0, -1, ec) < 0)
return 0;
}
}
@@ -1785,7 +1799,8 @@ int select(int nfds, fd_set* readfds, fd_set* writefds,
#endif
}
-int poll_read(socket_type s, state_type state, boost::system::error_code& ec)
+int poll_read(socket_type s, state_type state,
+ int msec, boost::system::error_code& ec)
{
if (s == invalid_socket)
{
@@ -1799,10 +1814,22 @@ int poll_read(socket_type s, state_type state, boost::system::error_code& ec)
fd_set fds;
FD_ZERO(&fds);
FD_SET(s, &fds);
- timeval zero_timeout;
- zero_timeout.tv_sec = 0;
- zero_timeout.tv_usec = 0;
- timeval* timeout = (state & user_set_non_blocking) ? &zero_timeout : 0;
+ timeval timeout_obj;
+ timeval* timeout;
+ if (state & user_set_non_blocking)
+ {
+ timeout_obj.tv_sec = 0;
+ timeout_obj.tv_usec = 0;
+ timeout = &timeout_obj;
+ }
+ else if (msec >= 0)
+ {
+ timeout_obj.tv_sec = msec / 1000;
+ timeout_obj.tv_usec = (msec % 1000) * 1000;
+ timeout = &timeout_obj;
+ }
+ else
+ timeout = 0;
clear_last_error();
int result = error_wrapper(::select(s + 1, &fds, 0, 0, timeout), ec);
#else // defined(BOOST_ASIO_WINDOWS)
@@ -1812,7 +1839,7 @@ int poll_read(socket_type s, state_type state, boost::system::error_code& ec)
fds.fd = s;
fds.events = POLLIN;
fds.revents = 0;
- int timeout = (state & user_set_non_blocking) ? 0 : -1;
+ int timeout = (state & user_set_non_blocking) ? 0 : msec;
clear_last_error();
int result = error_wrapper(::poll(&fds, 1, timeout), ec);
#endif // defined(BOOST_ASIO_WINDOWS)
@@ -1826,7 +1853,8 @@ int poll_read(socket_type s, state_type state, boost::system::error_code& ec)
return result;
}
-int poll_write(socket_type s, state_type state, boost::system::error_code& ec)
+int poll_write(socket_type s, state_type state,
+ int msec, boost::system::error_code& ec)
{
if (s == invalid_socket)
{
@@ -1840,10 +1868,22 @@ int poll_write(socket_type s, state_type state, boost::system::error_code& ec)
fd_set fds;
FD_ZERO(&fds);
FD_SET(s, &fds);
- timeval zero_timeout;
- zero_timeout.tv_sec = 0;
- zero_timeout.tv_usec = 0;
- timeval* timeout = (state & user_set_non_blocking) ? &zero_timeout : 0;
+ timeval timeout_obj;
+ timeval* timeout;
+ if (state & user_set_non_blocking)
+ {
+ timeout_obj.tv_sec = 0;
+ timeout_obj.tv_usec = 0;
+ timeout = &timeout_obj;
+ }
+ else if (msec >= 0)
+ {
+ timeout_obj.tv_sec = msec / 1000;
+ timeout_obj.tv_usec = (msec % 1000) * 1000;
+ timeout = &timeout_obj;
+ }
+ else
+ timeout = 0;
clear_last_error();
int result = error_wrapper(::select(s + 1, 0, &fds, 0, timeout), ec);
#else // defined(BOOST_ASIO_WINDOWS)
@@ -1853,7 +1893,7 @@ int poll_write(socket_type s, state_type state, boost::system::error_code& ec)
fds.fd = s;
fds.events = POLLOUT;
fds.revents = 0;
- int timeout = (state & user_set_non_blocking) ? 0 : -1;
+ int timeout = (state & user_set_non_blocking) ? 0 : msec;
clear_last_error();
int result = error_wrapper(::poll(&fds, 1, timeout), ec);
#endif // defined(BOOST_ASIO_WINDOWS)
@@ -1867,7 +1907,61 @@ int poll_write(socket_type s, state_type state, boost::system::error_code& ec)
return result;
}
-int poll_connect(socket_type s, boost::system::error_code& ec)
+int poll_error(socket_type s, state_type state,
+ int msec, boost::system::error_code& ec)
+{
+ if (s == invalid_socket)
+ {
+ ec = boost::asio::error::bad_descriptor;
+ return socket_error_retval;
+ }
+
+#if defined(BOOST_ASIO_WINDOWS) \
+ || defined(__CYGWIN__) \
+ || defined(__SYMBIAN32__)
+ fd_set fds;
+ FD_ZERO(&fds);
+ FD_SET(s, &fds);
+ timeval timeout_obj;
+ timeval* timeout;
+ if (state & user_set_non_blocking)
+ {
+ timeout_obj.tv_sec = 0;
+ timeout_obj.tv_usec = 0;
+ timeout = &timeout_obj;
+ }
+ else if (msec >= 0)
+ {
+ timeout_obj.tv_sec = msec / 1000;
+ timeout_obj.tv_usec = (msec % 1000) * 1000;
+ timeout = &timeout_obj;
+ }
+ else
+ timeout = 0;
+ clear_last_error();
+ int result = error_wrapper(::select(s + 1, 0, 0, &fds, timeout), ec);
+#else // defined(BOOST_ASIO_WINDOWS)
+ // || defined(__CYGWIN__)
+ // || defined(__SYMBIAN32__)
+ pollfd fds;
+ fds.fd = s;
+ fds.events = POLLPRI | POLLERR | POLLHUP;
+ fds.revents = 0;
+ int timeout = (state & user_set_non_blocking) ? 0 : msec;
+ clear_last_error();
+ int result = error_wrapper(::poll(&fds, 1, timeout), ec);
+#endif // defined(BOOST_ASIO_WINDOWS)
+ // || defined(__CYGWIN__)
+ // || defined(__SYMBIAN32__)
+ if (result == 0)
+ ec = (state & user_set_non_blocking)
+ ? boost::asio::error::would_block : boost::system::error_code();
+ else if (result > 0)
+ ec = boost::system::error_code();
+ return result;
+}
+
+int poll_connect(socket_type s, int msec, boost::system::error_code& ec)
{
if (s == invalid_socket)
{
@@ -1884,9 +1978,19 @@ int poll_connect(socket_type s, boost::system::error_code& ec)
fd_set except_fds;
FD_ZERO(&except_fds);
FD_SET(s, &except_fds);
+ timeval timeout_obj;
+ timeval* timeout;
+ if (msec >= 0)
+ {
+ timeout_obj.tv_sec = msec / 1000;
+ timeout_obj.tv_usec = (msec % 1000) * 1000;
+ timeout = &timeout_obj;
+ }
+ else
+ timeout = 0;
clear_last_error();
int result = error_wrapper(::select(
- s + 1, 0, &write_fds, &except_fds, 0), ec);
+ s + 1, 0, &write_fds, &except_fds, timeout), ec);
if (result >= 0)
ec = boost::system::error_code();
return result;
@@ -1898,7 +2002,7 @@ int poll_connect(socket_type s, boost::system::error_code& ec)
fds.events = POLLOUT;
fds.revents = 0;
clear_last_error();
- int result = error_wrapper(::poll(&fds, 1, -1), ec);
+ int result = error_wrapper(::poll(&fds, 1, msec), ec);
if (result >= 0)
ec = boost::system::error_code();
return result;
@@ -3346,7 +3450,6 @@ boost::system::error_code getnameinfo(const socket_addr_type* addr,
using namespace std; // For memcpy.
sockaddr_storage_type tmp_addr;
memcpy(&tmp_addr, addr, addrlen);
- tmp_addr.ss_len = addrlen;
addr = reinterpret_cast<socket_addr_type*>(&tmp_addr);
clear_last_error();
return getnameinfo_emulation(addr, addrlen,
diff --git a/boost/asio/detail/impl/strand_executor_service.hpp b/boost/asio/detail/impl/strand_executor_service.hpp
new file mode 100644
index 0000000000..6821c2ec64
--- /dev/null
+++ b/boost/asio/detail/impl/strand_executor_service.hpp
@@ -0,0 +1,181 @@
+//
+// detail/impl/strand_executor_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/call_stack.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/recycling_allocator.hpp>
+#include <boost/asio/executor_work_guard.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Executor>
+class strand_executor_service::invoker
+{
+public:
+ invoker(const implementation_type& impl, Executor& ex)
+ : impl_(impl),
+ work_(ex)
+ {
+ }
+
+ invoker(const invoker& other)
+ : impl_(other.impl_),
+ work_(other.work_)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ invoker(invoker&& other)
+ : impl_(BOOST_ASIO_MOVE_CAST(implementation_type)(other.impl_)),
+ work_(BOOST_ASIO_MOVE_CAST(executor_work_guard<Executor>)(other.work_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ struct on_invoker_exit
+ {
+ invoker* this_;
+
+ ~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)
+ {
+ Executor ex(this_->work_.get_executor());
+ recycling_allocator<void> allocator;
+ ex.post(BOOST_ASIO_MOVE_CAST(invoker)(*this_), allocator);
+ }
+ }
+ };
+
+ 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.
+ boost::system::error_code ec;
+ while (scheduler_operation* o = impl_->ready_queue_.front())
+ {
+ impl_->ready_queue_.pop();
+ o->complete(impl_.get(), ec, 0);
+ }
+ }
+
+private:
+ implementation_type impl_;
+ executor_work_guard<Executor> work_;
+};
+
+template <typename Executor, typename Function, typename Allocator>
+void strand_executor_service::dispatch(const implementation_type& impl,
+ Executor& ex, BOOST_ASIO_MOVE_ARG(Function) function, const Allocator& a)
+{
+ 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()))
+ {
+ // Make a local, non-const copy of the function.
+ function_type tmp(BOOST_ASIO_MOVE_CAST(Function)(function));
+
+ fenced_block b(fenced_block::full);
+ boost_asio_handler_invoke_helpers::invoke(tmp, tmp);
+ return;
+ }
+
+ // Allocate and construct an operation to wrap the function.
+ typedef executor_op<function_type, Allocator> op;
+ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
+ p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(function), a);
+
+ BOOST_ASIO_HANDLER_CREATION((impl->service_->context(), *p.p,
+ "strand_executor", impl.get(), 0, "dispatch"));
+
+ // Add the function to the strand and schedule the strand if required.
+ bool first = enqueue(impl, p.p);
+ p.v = p.p = 0;
+ if (first)
+ ex.dispatch(invoker<Executor>(impl, ex), a);
+}
+
+// Request invocation of the given function and return immediately.
+template <typename Executor, typename Function, typename Allocator>
+void strand_executor_service::post(const implementation_type& impl,
+ Executor& ex, BOOST_ASIO_MOVE_ARG(Function) function, const Allocator& a)
+{
+ typedef typename decay<Function>::type function_type;
+
+ // Allocate and construct an operation to wrap the function.
+ typedef executor_op<function_type, Allocator> op;
+ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
+ p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(function), a);
+
+ BOOST_ASIO_HANDLER_CREATION((impl->service_->context(), *p.p,
+ "strand_executor", impl.get(), 0, "post"));
+
+ // Add the function to the strand and schedule the strand if required.
+ bool first = enqueue(impl, p.p);
+ p.v = p.p = 0;
+ if (first)
+ ex.post(invoker<Executor>(impl, ex), a);
+}
+
+// Request invocation of the given function and return immediately.
+template <typename Executor, typename Function, typename Allocator>
+void strand_executor_service::defer(const implementation_type& impl,
+ Executor& ex, BOOST_ASIO_MOVE_ARG(Function) function, const Allocator& a)
+{
+ typedef typename decay<Function>::type function_type;
+
+ // Allocate and construct an operation to wrap the function.
+ typedef executor_op<function_type, Allocator> op;
+ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
+ p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(function), a);
+
+ BOOST_ASIO_HANDLER_CREATION((impl->service_->context(), *p.p,
+ "strand_executor", impl.get(), 0, "defer"));
+
+ // Add the function to the strand and schedule the strand if required.
+ bool first = enqueue(impl, p.p);
+ p.v = p.p = 0;
+ if (first)
+ ex.defer(invoker<Executor>(impl, ex), a);
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_HPP
diff --git a/boost/asio/detail/impl/strand_executor_service.ipp b/boost/asio/detail/impl/strand_executor_service.ipp
new file mode 100644
index 0000000000..353304ae27
--- /dev/null
+++ b/boost/asio/detail/impl/strand_executor_service.ipp
@@ -0,0 +1,126 @@
+//
+// detail/impl/strand_executor_service.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_IPP
+#define BOOST_ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/strand_executor_service.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+strand_executor_service::strand_executor_service(execution_context& ctx)
+ : execution_context_service_base<strand_executor_service>(ctx),
+ mutex_(),
+ salt_(0),
+ impl_list_(0)
+{
+}
+
+void strand_executor_service::shutdown()
+{
+ op_queue<scheduler_operation> ops;
+
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ strand_impl* impl = impl_list_;
+ while (impl)
+ {
+ ops.push(impl->waiting_queue_);
+ ops.push(impl->ready_queue_);
+ impl = impl->next_;
+ }
+}
+
+strand_executor_service::implementation_type
+strand_executor_service::create_implementation()
+{
+ implementation_type new_impl(new strand_impl);
+ new_impl->locked_ = false;
+
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+
+ // Select a mutex from the pool of shared mutexes.
+ std::size_t salt = salt_++;
+ std::size_t mutex_index = reinterpret_cast<std::size_t>(new_impl.get());
+ mutex_index += (reinterpret_cast<std::size_t>(new_impl.get()) >> 3);
+ mutex_index ^= salt + 0x9e3779b9 + (mutex_index << 6) + (mutex_index >> 2);
+ mutex_index = mutex_index % num_mutexes;
+ if (!mutexes_[mutex_index].get())
+ mutexes_[mutex_index].reset(new mutex);
+ new_impl->mutex_ = mutexes_[mutex_index].get();
+
+ // Insert implementation into linked list of all implementations.
+ new_impl->next_ = impl_list_;
+ new_impl->prev_ = 0;
+ if (impl_list_)
+ impl_list_->prev_ = new_impl.get();
+ impl_list_ = new_impl.get();
+ new_impl->service_ = this;
+
+ return new_impl;
+}
+
+strand_executor_service::strand_impl::~strand_impl()
+{
+ boost::asio::detail::mutex::scoped_lock lock(service_->mutex_);
+
+ // Remove implementation from linked list of all implementations.
+ if (service_->impl_list_ == this)
+ service_->impl_list_ = next_;
+ if (prev_)
+ prev_->next_ = next_;
+ if (next_)
+ next_->prev_= prev_;
+}
+
+bool strand_executor_service::enqueue(const implementation_type& impl,
+ scheduler_operation* op)
+{
+ impl->mutex_->lock();
+ if (impl->locked_)
+ {
+ // Some other function already holds the strand lock. Enqueue for later.
+ impl->waiting_queue_.push(op);
+ impl->mutex_->unlock();
+ return false;
+ }
+ else
+ {
+ // The function is acquiring the strand lock and so is responsible for
+ // scheduling the strand.
+ impl->locked_ = true;
+ impl->mutex_->unlock();
+ impl->ready_queue_.push(op);
+ return true;
+ }
+}
+
+bool strand_executor_service::running_in_this_thread(
+ const implementation_type& impl)
+{
+ return !!call_stack<strand_impl>::contains(impl.get());
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_IPP
diff --git a/boost/asio/detail/impl/strand_service.hpp b/boost/asio/detail/impl/strand_service.hpp
index 4167f686d1..df21099971 100644
--- a/boost/asio/detail/impl/strand_service.hpp
+++ b/boost/asio/detail/impl/strand_service.hpp
@@ -15,12 +15,12 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/call_stack.hpp>
#include <boost/asio/detail/completion_handler.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -36,7 +36,7 @@ inline strand_service::strand_impl::strand_impl()
struct strand_service::on_dispatch_exit
{
- io_service_impl* io_service_;
+ io_context_impl* io_context_;
strand_impl* impl_;
~on_dispatch_exit()
@@ -47,7 +47,7 @@ struct strand_service::on_dispatch_exit
impl_->mutex_.unlock();
if (more_handlers)
- io_service_->post_immediate_completion(impl_, false);
+ io_context_->post_immediate_completion(impl_, false);
}
};
@@ -66,11 +66,11 @@ void strand_service::dispatch(strand_service::implementation_type& impl,
// Allocate and construct an operation to wrap the handler.
typedef completion_handler<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "strand", impl, "dispatch"));
+ BOOST_ASIO_HANDLER_CREATION((this->context(),
+ *p.p, "strand", impl, 0, "dispatch"));
bool dispatch_immediately = do_dispatch(impl, p.p);
operation* o = p.p;
@@ -82,15 +82,15 @@ void strand_service::dispatch(strand_service::implementation_type& impl,
call_stack<strand_impl>::context ctx(impl);
// Ensure the next handler, if any, is scheduled on block exit.
- on_dispatch_exit on_exit = { &io_service_, impl };
+ on_dispatch_exit on_exit = { &io_context_, impl };
(void)on_exit;
completion_handler<Handler>::do_complete(
- &io_service_, o, boost::system::error_code(), 0);
+ &io_context_, o, boost::system::error_code(), 0);
}
}
-// Request the io_service to invoke the given handler and return immediately.
+// Request the io_context to invoke the given handler and return immediately.
template <typename Handler>
void strand_service::post(strand_service::implementation_type& impl,
Handler& handler)
@@ -101,11 +101,11 @@ void strand_service::post(strand_service::implementation_type& impl,
// Allocate and construct an operation to wrap the handler.
typedef completion_handler<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "strand", impl, "post"));
+ BOOST_ASIO_HANDLER_CREATION((this->context(),
+ *p.p, "strand", impl, 0, "post"));
do_post(impl, p.p, is_continuation);
p.v = p.p = 0;
diff --git a/boost/asio/detail/impl/strand_service.ipp b/boost/asio/detail/impl/strand_service.ipp
index 54ecde2cc7..e92355d837 100644
--- a/boost/asio/detail/impl/strand_service.ipp
+++ b/boost/asio/detail/impl/strand_service.ipp
@@ -27,7 +27,7 @@ namespace detail {
struct strand_service::on_do_complete_exit
{
- io_service_impl* owner_;
+ io_context_impl* owner_;
strand_impl* impl_;
~on_do_complete_exit()
@@ -42,15 +42,15 @@ struct strand_service::on_do_complete_exit
}
};
-strand_service::strand_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<strand_service>(io_service),
- io_service_(boost::asio::use_service<io_service_impl>(io_service)),
+strand_service::strand_service(boost::asio::io_context& io_context)
+ : boost::asio::detail::service_base<strand_service>(io_context),
+ io_context_(boost::asio::use_service<io_context_impl>(io_context)),
mutex_(),
salt_(0)
{
}
-void strand_service::shutdown_service()
+void strand_service::shutdown()
{
op_queue<operation> ops;
@@ -93,9 +93,9 @@ bool strand_service::running_in_this_thread(
bool strand_service::do_dispatch(implementation_type& impl, operation* op)
{
- // If we are running inside the io_service, and no other handler already
+ // 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_service_.can_dispatch();
+ bool can_dispatch = io_context_.can_dispatch();
impl->mutex_.lock();
if (can_dispatch && !impl->locked_)
{
@@ -118,7 +118,7 @@ bool strand_service::do_dispatch(implementation_type& impl, operation* op)
impl->locked_ = true;
impl->mutex_.unlock();
impl->ready_queue_.push(op);
- io_service_.post_immediate_completion(impl, false);
+ io_context_.post_immediate_completion(impl, false);
}
return false;
@@ -141,11 +141,11 @@ void strand_service::do_post(implementation_type& impl,
impl->locked_ = true;
impl->mutex_.unlock();
impl->ready_queue_.push(op);
- io_service_.post_immediate_completion(impl, is_continuation);
+ io_context_.post_immediate_completion(impl, is_continuation);
}
}
-void strand_service::do_complete(io_service_impl* owner, operation* base,
+void strand_service::do_complete(void* owner, operation* base,
const boost::system::error_code& ec, std::size_t /*bytes_transferred*/)
{
if (owner)
@@ -156,15 +156,16 @@ void strand_service::do_complete(io_service_impl* owner, operation* base,
call_stack<strand_impl>::context ctx(impl);
// Ensure the next handler, if any, is scheduled on block exit.
- on_do_complete_exit on_exit = { owner, impl };
- (void)on_exit;
+ on_do_complete_exit on_exit;
+ on_exit.owner_ = static_cast<io_context_impl*>(owner);
+ on_exit.impl_ = impl;
// Run all ready handlers. No lock is required since the ready queue is
// accessed only within the strand.
while (operation* o = impl->ready_queue_.front())
{
impl->ready_queue_.pop();
- o->complete(*owner, ec, 0);
+ o->complete(owner, ec, 0);
}
}
}
diff --git a/boost/asio/detail/impl/task_io_service.hpp b/boost/asio/detail/impl/task_io_service.hpp
deleted file mode 100644
index 09b4ba6985..0000000000
--- a/boost/asio/detail/impl/task_io_service.hpp
+++ /dev/null
@@ -1,80 +0,0 @@
-//
-// detail/impl/task_io_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP
-#define BOOST_ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/addressof.hpp>
-#include <boost/asio/detail/completion_handler.hpp>
-#include <boost/asio/detail/fenced_block.hpp>
-#include <boost/asio/detail/handler_alloc_helpers.hpp>
-#include <boost/asio/detail/handler_cont_helpers.hpp>
-#include <boost/asio/detail/handler_invoke_helpers.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-template <typename Handler>
-void task_io_service::dispatch(Handler& handler)
-{
- if (thread_call_stack::contains(this))
- {
- fenced_block b(fenced_block::full);
- boost_asio_handler_invoke_helpers::invoke(handler, handler);
- }
- else
- {
- // Allocate and construct an operation to wrap the handler.
- typedef completion_handler<Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "dispatch"));
-
- do_dispatch(p.p);
- p.v = p.p = 0;
- }
-}
-
-template <typename Handler>
-void task_io_service::post(Handler& handler)
-{
- bool is_continuation =
- boost_asio_handler_cont_helpers::is_continuation(handler);
-
- // Allocate and construct an operation to wrap the handler.
- typedef completion_handler<Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "post"));
-
- post_immediate_completion(p.p, is_continuation);
- p.v = p.p = 0;
-}
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_DETAIL_IMPL_TASK_IO_SERVICE_HPP
diff --git a/boost/asio/detail/impl/timer_queue_ptime.ipp b/boost/asio/detail/impl/timer_queue_ptime.ipp
index 0216d20ba5..885ee7d06e 100644
--- a/boost/asio/detail/impl/timer_queue_ptime.ipp
+++ b/boost/asio/detail/impl/timer_queue_ptime.ipp
@@ -16,12 +16,13 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
#include <boost/asio/detail/timer_queue_ptime.hpp>
#include <boost/asio/detail/push_options.hpp>
-#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
-
namespace boost {
namespace asio {
namespace detail {
@@ -75,12 +76,18 @@ std::size_t timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer(
return impl_.cancel_timer(timer, ops, max_cancelled);
}
+void timer_queue<time_traits<boost::posix_time::ptime> >::move_timer(
+ per_timer_data& target, per_timer_data& source)
+{
+ impl_.move_timer(target, source);
+}
+
} // namespace detail
} // namespace asio
} // namespace boost
-#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
-
#include <boost/asio/detail/pop_options.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
#endif // BOOST_ASIO_DETAIL_IMPL_TIMER_QUEUE_PTIME_IPP
diff --git a/boost/asio/detail/impl/win_event.ipp b/boost/asio/detail/impl/win_event.ipp
index 2519d3165d..4e084de2ba 100644
--- a/boost/asio/detail/impl/win_event.ipp
+++ b/boost/asio/detail/impl/win_event.ipp
@@ -33,7 +33,8 @@ win_event::win_event()
: state_(0)
{
#if defined(BOOST_ASIO_WINDOWS_APP)
- events_[0] = ::CreateEventExW(0, 0, CREATE_EVENT_MANUAL_RESET, 0);
+ events_[0] = ::CreateEventExW(0, 0,
+ CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);
#else // defined(BOOST_ASIO_WINDOWS_APP)
events_[0] = ::CreateEventW(0, true, false, 0);
#endif // defined(BOOST_ASIO_WINDOWS_APP)
@@ -46,7 +47,7 @@ win_event::win_event()
}
#if defined(BOOST_ASIO_WINDOWS_APP)
- events_[1] = ::CreateEventExW(0, 0, 0, 0);
+ events_[1] = ::CreateEventExW(0, 0, 0, EVENT_ALL_ACCESS);
#else // defined(BOOST_ASIO_WINDOWS_APP)
events_[1] = ::CreateEventW(0, false, false, 0);
#endif // defined(BOOST_ASIO_WINDOWS_APP)
diff --git a/boost/asio/detail/impl/win_iocp_handle_service.ipp b/boost/asio/detail/impl/win_iocp_handle_service.ipp
index ea513bc1dd..4f35a1c0a8 100644
--- a/boost/asio/detail/impl/win_iocp_handle_service.ipp
+++ b/boost/asio/detail/impl/win_iocp_handle_service.ipp
@@ -67,14 +67,15 @@ public:
};
win_iocp_handle_service::win_iocp_handle_service(
- boost::asio::io_service& io_service)
- : iocp_service_(boost::asio::use_service<win_iocp_io_service>(io_service)),
+ boost::asio::io_context& io_context)
+ : service_base<win_iocp_handle_service>(io_context),
+ iocp_service_(boost::asio::use_service<win_iocp_io_context>(io_context)),
mutex_(),
impl_list_(0)
{
}
-void win_iocp_handle_service::shutdown_service()
+void win_iocp_handle_service::shutdown()
{
// Close all implementations, causing all operations to complete.
boost::asio::detail::mutex::scoped_lock lock(mutex_);
@@ -200,7 +201,8 @@ boost::system::error_code win_iocp_handle_service::close(
{
if (is_open(impl))
{
- BOOST_ASIO_HANDLER_OPERATION(("handle", &impl, "close"));
+ BOOST_ASIO_HANDLER_OPERATION((iocp_service_.context(), "handle",
+ &impl, reinterpret_cast<uintmax_t>(impl.handle_), "close"));
if (!::CloseHandle(impl.handle_))
{
@@ -234,7 +236,8 @@ boost::system::error_code win_iocp_handle_service::cancel(
return ec;
}
- BOOST_ASIO_HANDLER_OPERATION(("handle", &impl, "cancel"));
+ BOOST_ASIO_HANDLER_OPERATION((iocp_service_.context(), "handle",
+ &impl, reinterpret_cast<uintmax_t>(impl.handle_), "cancel"));
if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
@@ -304,7 +307,7 @@ size_t win_iocp_handle_service::do_write(
}
// A request to write 0 bytes on a handle is a no-op.
- if (boost::asio::buffer_size(buffer) == 0)
+ if (buffer.size() == 0)
{
ec = boost::system::error_code();
return 0;
@@ -319,9 +322,8 @@ size_t win_iocp_handle_service::do_write(
// Write the data.
overlapped.Offset = offset & 0xFFFFFFFF;
overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
- BOOL ok = ::WriteFile(impl.handle_,
- boost::asio::buffer_cast<LPCVOID>(buffer),
- static_cast<DWORD>(boost::asio::buffer_size(buffer)), 0, &overlapped);
+ BOOL ok = ::WriteFile(impl.handle_, buffer.data(),
+ static_cast<DWORD>(buffer.size()), 0, &overlapped);
if (!ok)
{
DWORD last_error = ::GetLastError();
@@ -360,7 +362,7 @@ void win_iocp_handle_service::start_write_op(
{
iocp_service_.on_completion(op, boost::asio::error::bad_descriptor);
}
- else if (boost::asio::buffer_size(buffer) == 0)
+ else if (buffer.size() == 0)
{
// A request to write 0 bytes on a handle is a no-op.
iocp_service_.on_completion(op);
@@ -370,9 +372,8 @@ void win_iocp_handle_service::start_write_op(
DWORD bytes_transferred = 0;
op->Offset = offset & 0xFFFFFFFF;
op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
- BOOL ok = ::WriteFile(impl.handle_,
- boost::asio::buffer_cast<LPCVOID>(buffer),
- static_cast<DWORD>(boost::asio::buffer_size(buffer)),
+ BOOL ok = ::WriteFile(impl.handle_, buffer.data(),
+ static_cast<DWORD>(buffer.size()),
&bytes_transferred, op);
DWORD last_error = ::GetLastError();
if (!ok && last_error != ERROR_IO_PENDING
@@ -398,7 +399,7 @@ size_t win_iocp_handle_service::do_read(
}
// A request to read 0 bytes on a stream handle is a no-op.
- if (boost::asio::buffer_size(buffer) == 0)
+ if (buffer.size() == 0)
{
ec = boost::system::error_code();
return 0;
@@ -413,9 +414,8 @@ size_t win_iocp_handle_service::do_read(
// Read some data.
overlapped.Offset = offset & 0xFFFFFFFF;
overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
- BOOL ok = ::ReadFile(impl.handle_,
- boost::asio::buffer_cast<LPVOID>(buffer),
- static_cast<DWORD>(boost::asio::buffer_size(buffer)), 0, &overlapped);
+ BOOL ok = ::ReadFile(impl.handle_, buffer.data(),
+ static_cast<DWORD>(buffer.size()), 0, &overlapped);
if (!ok)
{
DWORD last_error = ::GetLastError();
@@ -468,7 +468,7 @@ void win_iocp_handle_service::start_read_op(
{
iocp_service_.on_completion(op, boost::asio::error::bad_descriptor);
}
- else if (boost::asio::buffer_size(buffer) == 0)
+ else if (buffer.size() == 0)
{
// A request to read 0 bytes on a handle is a no-op.
iocp_service_.on_completion(op);
@@ -478,9 +478,8 @@ void win_iocp_handle_service::start_read_op(
DWORD bytes_transferred = 0;
op->Offset = offset & 0xFFFFFFFF;
op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;
- BOOL ok = ::ReadFile(impl.handle_,
- boost::asio::buffer_cast<LPVOID>(buffer),
- static_cast<DWORD>(boost::asio::buffer_size(buffer)),
+ BOOL ok = ::ReadFile(impl.handle_, buffer.data(),
+ static_cast<DWORD>(buffer.size()),
&bytes_transferred, op);
DWORD last_error = ::GetLastError();
if (!ok && last_error != ERROR_IO_PENDING
@@ -508,7 +507,8 @@ void win_iocp_handle_service::close_for_destruction(implementation_type& impl)
{
if (is_open(impl))
{
- BOOST_ASIO_HANDLER_OPERATION(("handle", &impl, "close"));
+ BOOST_ASIO_HANDLER_OPERATION((iocp_service_.context(), "handle",
+ &impl, reinterpret_cast<uintmax_t>(impl.handle_), "close"));
::CloseHandle(impl.handle_);
impl.handle_ = INVALID_HANDLE_VALUE;
diff --git a/boost/asio/detail/impl/win_iocp_io_service.hpp b/boost/asio/detail/impl/win_iocp_io_context.hpp
index e3505cb852..948b0c93d4 100644
--- a/boost/asio/detail/impl/win_iocp_io_service.hpp
+++ b/boost/asio/detail/impl/win_iocp_io_context.hpp
@@ -1,5 +1,5 @@
//
-// detail/impl/win_iocp_io_service.hpp
+// detail/impl/win_iocp_io_context.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
@@ -8,8 +8,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP
-#define BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP
+#ifndef BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_HPP
+#define BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
@@ -19,11 +19,11 @@
#if defined(BOOST_ASIO_HAS_IOCP)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/completion_handler.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -31,62 +31,22 @@ namespace boost {
namespace asio {
namespace detail {
-template <typename Handler>
-void win_iocp_io_service::dispatch(Handler& handler)
-{
- if (thread_call_stack::contains(this))
- {
- fenced_block b(fenced_block::full);
- boost_asio_handler_invoke_helpers::invoke(handler, handler);
- }
- else
- {
- // Allocate and construct an operation to wrap the handler.
- typedef completion_handler<Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "dispatch"));
-
- post_immediate_completion(p.p, false);
- p.v = p.p = 0;
- }
-}
-
-template <typename Handler>
-void win_iocp_io_service::post(Handler& handler)
-{
- // Allocate and construct an operation to wrap the handler.
- typedef completion_handler<Handler> op;
- typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(handler);
-
- BOOST_ASIO_HANDLER_CREATION((p.p, "io_service", this, "post"));
-
- post_immediate_completion(p.p, false);
- p.v = p.p = 0;
-}
-
template <typename Time_Traits>
-void win_iocp_io_service::add_timer_queue(
+void win_iocp_io_context::add_timer_queue(
timer_queue<Time_Traits>& queue)
{
do_add_timer_queue(queue);
}
template <typename Time_Traits>
-void win_iocp_io_service::remove_timer_queue(
+void win_iocp_io_context::remove_timer_queue(
timer_queue<Time_Traits>& queue)
{
do_remove_timer_queue(queue);
}
template <typename Time_Traits>
-void win_iocp_io_service::schedule_timer(timer_queue<Time_Traits>& queue,
+void win_iocp_io_context::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)
{
@@ -106,7 +66,7 @@ void win_iocp_io_service::schedule_timer(timer_queue<Time_Traits>& queue,
}
template <typename Time_Traits>
-std::size_t win_iocp_io_service::cancel_timer(timer_queue<Time_Traits>& queue,
+std::size_t win_iocp_io_context::cancel_timer(timer_queue<Time_Traits>& queue,
typename timer_queue<Time_Traits>::per_timer_data& timer,
std::size_t max_cancelled)
{
@@ -121,6 +81,19 @@ std::size_t win_iocp_io_service::cancel_timer(timer_queue<Time_Traits>& queue,
return n;
}
+template <typename Time_Traits>
+void win_iocp_io_context::move_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& to,
+ typename timer_queue<Time_Traits>::per_timer_data& from)
+{
+ boost::asio::detail::mutex::scoped_lock lock(dispatch_mutex_);
+ op_queue<operation> ops;
+ queue.cancel_timer(to, ops);
+ queue.move_timer(to, from);
+ lock.unlock();
+ post_deferred_completions(ops);
+}
+
} // namespace detail
} // namespace asio
} // namespace boost
@@ -129,4 +102,4 @@ std::size_t win_iocp_io_service::cancel_timer(timer_queue<Time_Traits>& queue,
#endif // defined(BOOST_ASIO_HAS_IOCP)
-#endif // BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_HPP
+#endif // BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_HPP
diff --git a/boost/asio/detail/impl/win_iocp_io_service.ipp b/boost/asio/detail/impl/win_iocp_io_context.ipp
index a5bfcbbdea..9071836aa9 100644
--- a/boost/asio/detail/impl/win_iocp_io_service.ipp
+++ b/boost/asio/detail/impl/win_iocp_io_context.ipp
@@ -1,5 +1,5 @@
//
-// detail/impl/win_iocp_io_service.ipp
+// detail/impl/win_iocp_io_context.ipp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
@@ -8,8 +8,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP
-#define BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP
+#ifndef BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_IPP
+#define BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
@@ -20,13 +20,12 @@
#if defined(BOOST_ASIO_HAS_IOCP)
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
#include <boost/asio/detail/cstdint.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/limits.hpp>
#include <boost/asio/detail/throw_error.hpp>
-#include <boost/asio/detail/win_iocp_io_service.hpp>
+#include <boost/asio/detail/win_iocp_io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -34,51 +33,51 @@ namespace boost {
namespace asio {
namespace detail {
-struct win_iocp_io_service::work_finished_on_block_exit
+struct win_iocp_io_context::work_finished_on_block_exit
{
~work_finished_on_block_exit()
{
- io_service_->work_finished();
+ io_context_->work_finished();
}
- win_iocp_io_service* io_service_;
+ win_iocp_io_context* io_context_;
};
-struct win_iocp_io_service::timer_thread_function
+struct win_iocp_io_context::timer_thread_function
{
void operator()()
{
- while (::InterlockedExchangeAdd(&io_service_->shutdown_, 0) == 0)
+ while (::InterlockedExchangeAdd(&io_context_->shutdown_, 0) == 0)
{
- if (::WaitForSingleObject(io_service_->waitable_timer_.handle,
+ if (::WaitForSingleObject(io_context_->waitable_timer_.handle,
INFINITE) == WAIT_OBJECT_0)
{
- ::InterlockedExchange(&io_service_->dispatch_required_, 1);
- ::PostQueuedCompletionStatus(io_service_->iocp_.handle,
+ ::InterlockedExchange(&io_context_->dispatch_required_, 1);
+ ::PostQueuedCompletionStatus(io_context_->iocp_.handle,
0, wake_for_dispatch, 0);
}
}
}
- win_iocp_io_service* io_service_;
+ win_iocp_io_context* io_context_;
};
-win_iocp_io_service::win_iocp_io_service(
- boost::asio::io_service& io_service, size_t concurrency_hint)
- : boost::asio::detail::service_base<win_iocp_io_service>(io_service),
+win_iocp_io_context::win_iocp_io_context(
+ boost::asio::execution_context& ctx, int concurrency_hint)
+ : execution_context_service_base<win_iocp_io_context>(ctx),
iocp_(),
outstanding_work_(0),
stopped_(0),
stop_event_posted_(0),
shutdown_(0),
gqcs_timeout_(get_gqcs_timeout()),
- dispatch_required_(0)
+ dispatch_required_(0),
+ concurrency_hint_(concurrency_hint)
{
BOOST_ASIO_HANDLER_TRACKING_INIT;
iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0,
- static_cast<DWORD>(concurrency_hint < DWORD(~0)
- ? concurrency_hint : DWORD(~0)));
+ static_cast<DWORD>(concurrency_hint >= 0 ? concurrency_hint : DWORD(~0)));
if (!iocp_.handle)
{
DWORD last_error = ::GetLastError();
@@ -88,7 +87,7 @@ win_iocp_io_service::win_iocp_io_service(
}
}
-void win_iocp_io_service::shutdown_service()
+void win_iocp_io_context::shutdown()
{
::InterlockedExchange(&shutdown_, 1);
@@ -132,7 +131,7 @@ void win_iocp_io_service::shutdown_service()
timer_thread_->join();
}
-boost::system::error_code win_iocp_io_service::register_handle(
+boost::system::error_code win_iocp_io_context::register_handle(
HANDLE handle, boost::system::error_code& ec)
{
if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0)
@@ -148,7 +147,7 @@ boost::system::error_code win_iocp_io_service::register_handle(
return ec;
}
-size_t win_iocp_io_service::run(boost::system::error_code& ec)
+size_t win_iocp_io_context::run(boost::system::error_code& ec)
{
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
{
@@ -161,13 +160,13 @@ size_t win_iocp_io_service::run(boost::system::error_code& ec)
thread_call_stack::context ctx(this, this_thread);
size_t n = 0;
- while (do_one(true, ec))
+ while (do_one(INFINITE, ec))
if (n != (std::numeric_limits<size_t>::max)())
++n;
return n;
}
-size_t win_iocp_io_service::run_one(boost::system::error_code& ec)
+size_t win_iocp_io_context::run_one(boost::system::error_code& ec)
{
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
{
@@ -179,10 +178,25 @@ size_t win_iocp_io_service::run_one(boost::system::error_code& ec)
win_iocp_thread_info this_thread;
thread_call_stack::context ctx(this, this_thread);
- return do_one(true, ec);
+ return do_one(INFINITE, ec);
}
-size_t win_iocp_io_service::poll(boost::system::error_code& ec)
+size_t win_iocp_io_context::wait_one(long usec, boost::system::error_code& ec)
+{
+ if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
+ {
+ stop();
+ ec = boost::system::error_code();
+ return 0;
+ }
+
+ win_iocp_thread_info this_thread;
+ thread_call_stack::context ctx(this, this_thread);
+
+ return do_one(usec < 0 ? INFINITE : ((usec - 1) / 1000 + 1), ec);
+}
+
+size_t win_iocp_io_context::poll(boost::system::error_code& ec)
{
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
{
@@ -195,13 +209,13 @@ size_t win_iocp_io_service::poll(boost::system::error_code& ec)
thread_call_stack::context ctx(this, this_thread);
size_t n = 0;
- while (do_one(false, ec))
+ while (do_one(0, ec))
if (n != (std::numeric_limits<size_t>::max)())
++n;
return n;
}
-size_t win_iocp_io_service::poll_one(boost::system::error_code& ec)
+size_t win_iocp_io_context::poll_one(boost::system::error_code& ec)
{
if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)
{
@@ -213,10 +227,10 @@ size_t win_iocp_io_service::poll_one(boost::system::error_code& ec)
win_iocp_thread_info this_thread;
thread_call_stack::context ctx(this, this_thread);
- return do_one(false, ec);
+ return do_one(0, ec);
}
-void win_iocp_io_service::stop()
+void win_iocp_io_context::stop()
{
if (::InterlockedExchange(&stopped_, 1) == 0)
{
@@ -233,7 +247,7 @@ void win_iocp_io_service::stop()
}
}
-void win_iocp_io_service::post_deferred_completion(win_iocp_operation* op)
+void win_iocp_io_context::post_deferred_completion(win_iocp_operation* op)
{
// Flag the operation as ready.
op->ready_ = 1;
@@ -248,7 +262,7 @@ void win_iocp_io_service::post_deferred_completion(win_iocp_operation* op)
}
}
-void win_iocp_io_service::post_deferred_completions(
+void win_iocp_io_context::post_deferred_completions(
op_queue<win_iocp_operation>& ops)
{
while (win_iocp_operation* op = ops.front())
@@ -270,7 +284,7 @@ void win_iocp_io_service::post_deferred_completions(
}
}
-void win_iocp_io_service::abandon_operations(
+void win_iocp_io_context::abandon_operations(
op_queue<win_iocp_operation>& ops)
{
while (win_iocp_operation* op = ops.front())
@@ -281,7 +295,7 @@ void win_iocp_io_service::abandon_operations(
}
}
-void win_iocp_io_service::on_pending(win_iocp_operation* op)
+void win_iocp_io_context::on_pending(win_iocp_operation* op)
{
if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)
{
@@ -297,7 +311,7 @@ void win_iocp_io_service::on_pending(win_iocp_operation* op)
}
}
-void win_iocp_io_service::on_completion(win_iocp_operation* op,
+void win_iocp_io_context::on_completion(win_iocp_operation* op,
DWORD last_error, DWORD bytes_transferred)
{
// Flag that the operation is ready for invocation.
@@ -320,7 +334,7 @@ void win_iocp_io_service::on_completion(win_iocp_operation* op,
}
}
-void win_iocp_io_service::on_completion(win_iocp_operation* op,
+void win_iocp_io_context::on_completion(win_iocp_operation* op,
const boost::system::error_code& ec, DWORD bytes_transferred)
{
// Flag that the operation is ready for invocation.
@@ -342,7 +356,7 @@ void win_iocp_io_service::on_completion(win_iocp_operation* op,
}
}
-size_t win_iocp_io_service::do_one(bool block, boost::system::error_code& ec)
+size_t win_iocp_io_context::do_one(DWORD msec, boost::system::error_code& ec)
{
for (;;)
{
@@ -364,8 +378,9 @@ size_t win_iocp_io_service::do_one(bool block, boost::system::error_code& ec)
dword_ptr_t completion_key = 0;
LPOVERLAPPED overlapped = 0;
::SetLastError(0);
- BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,
- &completion_key, &overlapped, block ? gqcs_timeout_ : 0);
+ BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle,
+ &bytes_transferred, &completion_key, &overlapped,
+ msec < gqcs_timeout_ ? msec : gqcs_timeout_);
DWORD last_error = ::GetLastError();
if (overlapped)
@@ -402,7 +417,7 @@ size_t win_iocp_io_service::do_one(bool block, boost::system::error_code& ec)
work_finished_on_block_exit on_exit = { this };
(void)on_exit;
- op->complete(*this, result_ec, bytes_transferred);
+ op->complete(this, result_ec, bytes_transferred);
ec = boost::system::error_code();
return 1;
}
@@ -416,8 +431,9 @@ size_t win_iocp_io_service::do_one(bool block, boost::system::error_code& ec)
return 0;
}
- // If we're not polling we need to keep going until we get a real handler.
- if (block)
+ // If we're waiting indefinitely we need to keep going until we get a
+ // real handler.
+ if (msec == INFINITE)
continue;
ec = boost::system::error_code();
@@ -456,7 +472,7 @@ size_t win_iocp_io_service::do_one(bool block, boost::system::error_code& ec)
}
}
-DWORD win_iocp_io_service::get_gqcs_timeout()
+DWORD win_iocp_io_context::get_gqcs_timeout()
{
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(osvi));
@@ -472,7 +488,7 @@ DWORD win_iocp_io_service::get_gqcs_timeout()
return default_gqcs_timeout;
}
-void win_iocp_io_service::do_add_timer_queue(timer_queue_base& queue)
+void win_iocp_io_context::do_add_timer_queue(timer_queue_base& queue)
{
mutex::scoped_lock lock(dispatch_mutex_);
@@ -503,14 +519,14 @@ void win_iocp_io_service::do_add_timer_queue(timer_queue_base& queue)
}
}
-void win_iocp_io_service::do_remove_timer_queue(timer_queue_base& queue)
+void win_iocp_io_context::do_remove_timer_queue(timer_queue_base& queue)
{
mutex::scoped_lock lock(dispatch_mutex_);
timer_queues_.erase(&queue);
}
-void win_iocp_io_service::update_timeout()
+void win_iocp_io_context::update_timeout()
{
if (timer_thread_.get())
{
@@ -537,4 +553,4 @@ void win_iocp_io_service::update_timeout()
#endif // defined(BOOST_ASIO_HAS_IOCP)
-#endif // BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_SERVICE_IPP
+#endif // BOOST_ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_IPP
diff --git a/boost/asio/detail/impl/win_iocp_serial_port_service.ipp b/boost/asio/detail/impl/win_iocp_serial_port_service.ipp
index 32ba34684b..c0d2dbbd59 100644
--- a/boost/asio/detail/impl/win_iocp_serial_port_service.ipp
+++ b/boost/asio/detail/impl/win_iocp_serial_port_service.ipp
@@ -30,12 +30,13 @@ namespace asio {
namespace detail {
win_iocp_serial_port_service::win_iocp_serial_port_service(
- boost::asio::io_service& io_service)
- : handle_service_(io_service)
+ boost::asio::io_context& io_context)
+ : service_base<win_iocp_serial_port_service>(io_context),
+ handle_service_(io_context)
{
}
-void win_iocp_serial_port_service::shutdown_service()
+void win_iocp_serial_port_service::shutdown()
{
}
diff --git a/boost/asio/detail/impl/win_iocp_socket_service_base.ipp b/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
index 93f5ed0713..e9a5049345 100644
--- a/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
+++ b/boost/asio/detail/impl/win_iocp_socket_service_base.ipp
@@ -28,24 +28,24 @@ namespace asio {
namespace detail {
win_iocp_socket_service_base::win_iocp_socket_service_base(
- boost::asio::io_service& io_service)
- : io_service_(io_service),
- iocp_service_(use_service<win_iocp_io_service>(io_service)),
+ boost::asio::io_context& io_context)
+ : io_context_(io_context),
+ iocp_service_(use_service<win_iocp_io_context>(io_context)),
reactor_(0),
connect_ex_(0),
+ nt_set_info_(0),
mutex_(),
impl_list_(0)
{
}
-void win_iocp_socket_service_base::shutdown_service()
+void win_iocp_socket_service_base::base_shutdown()
{
// Close all implementations, causing all operations to complete.
boost::asio::detail::mutex::scoped_lock lock(mutex_);
base_implementation_type* impl = impl_list_;
while (impl)
{
- boost::system::error_code ignored_ec;
close_for_destruction(*impl);
impl = impl->next_;
}
@@ -167,12 +167,13 @@ boost::system::error_code win_iocp_socket_service_base::close(
{
if (is_open(impl))
{
- BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+ BOOST_ASIO_HANDLER_OPERATION((iocp_service_.context(),
+ "socket", &impl, impl.socket_, "close"));
// Check if the reactor was created, in which case we need to close the
// socket on the reactor as well to cancel any operations that might be
// running there.
- reactor* r = static_cast<reactor*>(
+ select_reactor* r = static_cast<select_reactor*>(
interlocked_compare_exchange_pointer(
reinterpret_cast<void**>(&reactor_), 0, 0));
if (r)
@@ -198,6 +199,39 @@ boost::system::error_code win_iocp_socket_service_base::close(
return ec;
}
+socket_type win_iocp_socket_service_base::release(
+ win_iocp_socket_service_base::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ return invalid_socket;
+
+ cancel(impl, ec);
+ if (ec)
+ return invalid_socket;
+
+ nt_set_info_fn fn = get_nt_set_info();
+ if (fn == 0)
+ {
+ ec = boost::asio::error::operation_not_supported;
+ return invalid_socket;
+ }
+
+ HANDLE sock_as_handle = reinterpret_cast<HANDLE>(impl.socket_);
+ ULONG_PTR iosb[2] = { 0, 0 };
+ void* info[2] = { 0, 0 };
+ if (fn(sock_as_handle, iosb, &info, sizeof(info),
+ 61 /* FileReplaceCompletionInformation */))
+ {
+ ec = boost::asio::error::operation_not_supported;
+ return invalid_socket;
+ }
+
+ socket_type tmp = impl.socket_;
+ impl.socket_ = invalid_socket;
+ return tmp;
+}
+
boost::system::error_code win_iocp_socket_service_base::cancel(
win_iocp_socket_service_base::base_implementation_type& impl,
boost::system::error_code& ec)
@@ -208,7 +242,8 @@ boost::system::error_code win_iocp_socket_service_base::cancel(
return ec;
}
- BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "cancel"));
+ BOOST_ASIO_HANDLER_OPERATION((iocp_service_.context(),
+ "socket", &impl, impl.socket_, "cancel"));
if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(
::GetModuleHandleA("KERNEL32"), "CancelIoEx"))
@@ -279,7 +314,7 @@ boost::system::error_code win_iocp_socket_service_base::cancel(
// Cancel any operations started via the reactor.
if (!ec)
{
- reactor* r = static_cast<reactor*>(
+ select_reactor* r = static_cast<select_reactor*>(
interlocked_compare_exchange_pointer(
reinterpret_cast<void**>(&reactor_), 0, 0));
if (r)
@@ -445,7 +480,7 @@ void win_iocp_socket_service_base::start_null_buffers_receive_op(
{
start_reactor_op(impl,
(flags & socket_base::message_out_of_band)
- ? reactor::except_op : reactor::read_op,
+ ? select_reactor::except_op : select_reactor::read_op,
op);
}
}
@@ -537,7 +572,7 @@ void win_iocp_socket_service_base::start_reactor_op(
win_iocp_socket_service_base::base_implementation_type& impl,
int op_type, reactor_op* op)
{
- reactor& r = get_reactor();
+ select_reactor& r = get_reactor();
update_cancellation_thread_id(impl);
if (is_open(impl))
@@ -598,7 +633,7 @@ void win_iocp_socket_service_base::start_connect_op(
}
// Otherwise, fall back to a reactor-based implementation.
- reactor& r = get_reactor();
+ select_reactor& r = get_reactor();
update_cancellation_thread_id(impl);
if ((impl.state_ & socket_ops::non_blocking) != 0
@@ -611,7 +646,7 @@ void win_iocp_socket_service_base::start_connect_op(
|| op->ec_ == boost::asio::error::would_block)
{
op->ec_ = boost::system::error_code();
- r.start_op(reactor::connect_op, impl.socket_,
+ r.start_op(select_reactor::connect_op, impl.socket_,
impl.reactor_data_, op, false, false);
return;
}
@@ -626,12 +661,13 @@ void win_iocp_socket_service_base::close_for_destruction(
{
if (is_open(impl))
{
- BOOST_ASIO_HANDLER_OPERATION(("socket", &impl, "close"));
+ BOOST_ASIO_HANDLER_OPERATION((iocp_service_.context(),
+ "socket", &impl, impl.socket_, "close"));
// Check if the reactor was created, in which case we need to close the
// socket on the reactor as well to cancel any operations that might be
// running there.
- reactor* r = static_cast<reactor*>(
+ select_reactor* r = static_cast<select_reactor*>(
interlocked_compare_exchange_pointer(
reinterpret_cast<void**>(&reactor_), 0, 0));
if (r)
@@ -665,14 +701,14 @@ void win_iocp_socket_service_base::update_cancellation_thread_id(
#endif // defined(BOOST_ASIO_ENABLE_CANCELIO)
}
-reactor& win_iocp_socket_service_base::get_reactor()
+select_reactor& win_iocp_socket_service_base::get_reactor()
{
- reactor* r = static_cast<reactor*>(
+ select_reactor* r = static_cast<select_reactor*>(
interlocked_compare_exchange_pointer(
reinterpret_cast<void**>(&reactor_), 0, 0));
if (!r)
{
- r = &(use_service<reactor>(io_service_));
+ r = &(use_service<select_reactor>(io_context_));
interlocked_exchange_pointer(reinterpret_cast<void**>(&reactor_), r);
}
return *r;
@@ -713,6 +749,24 @@ win_iocp_socket_service_base::get_connect_ex(
#endif // defined(BOOST_ASIO_DISABLE_CONNECTEX)
}
+win_iocp_socket_service_base::nt_set_info_fn
+win_iocp_socket_service_base::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_socket_service_base::interlocked_compare_exchange_pointer(
void** dest, void* exch, void* cmp)
{
diff --git a/boost/asio/detail/impl/win_object_handle_service.ipp b/boost/asio/detail/impl/win_object_handle_service.ipp
index a940161cba..31718a012b 100644
--- a/boost/asio/detail/impl/win_object_handle_service.ipp
+++ b/boost/asio/detail/impl/win_object_handle_service.ipp
@@ -29,15 +29,16 @@ namespace asio {
namespace detail {
win_object_handle_service::win_object_handle_service(
- boost::asio::io_service& io_service)
- : io_service_(boost::asio::use_service<io_service_impl>(io_service)),
+ boost::asio::io_context& io_context)
+ : service_base<win_object_handle_service>(io_context),
+ io_context_(boost::asio::use_service<io_context_impl>(io_context)),
mutex_(),
impl_list_(0),
shutdown_(false)
{
}
-void win_object_handle_service::shutdown_service()
+void win_object_handle_service::shutdown()
{
mutex::scoped_lock lock(mutex_);
@@ -52,7 +53,7 @@ void win_object_handle_service::shutdown_service()
lock.unlock();
- io_service_.abandon_operations(ops);
+ io_context_.abandon_operations(ops);
}
void win_object_handle_service::construct(
@@ -178,7 +179,8 @@ void win_object_handle_service::destroy(
if (is_open(impl))
{
- BOOST_ASIO_HANDLER_OPERATION(("object_handle", &impl, "close"));
+ BOOST_ASIO_HANDLER_OPERATION((io_context_.context(), "object_handle",
+ &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "close"));
HANDLE wait_handle = impl.wait_handle_;
impl.wait_handle_ = INVALID_HANDLE_VALUE;
@@ -202,7 +204,7 @@ void win_object_handle_service::destroy(
::CloseHandle(impl.handle_);
impl.handle_ = INVALID_HANDLE_VALUE;
- io_service_.post_deferred_completions(ops);
+ io_context_.post_deferred_completions(ops);
}
}
@@ -227,7 +229,8 @@ boost::system::error_code win_object_handle_service::close(
{
if (is_open(impl))
{
- BOOST_ASIO_HANDLER_OPERATION(("object_handle", &impl, "close"));
+ BOOST_ASIO_HANDLER_OPERATION((io_context_.context(), "object_handle",
+ &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "close"));
mutex::scoped_lock lock(mutex_);
@@ -262,7 +265,7 @@ boost::system::error_code win_object_handle_service::close(
boost::asio::error::get_system_category());
}
- io_service_.post_deferred_completions(completed_ops);
+ io_context_.post_deferred_completions(completed_ops);
}
else
{
@@ -278,7 +281,8 @@ boost::system::error_code win_object_handle_service::cancel(
{
if (is_open(impl))
{
- BOOST_ASIO_HANDLER_OPERATION(("object_handle", &impl, "cancel"));
+ BOOST_ASIO_HANDLER_OPERATION((io_context_.context(), "object_handle",
+ &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "cancel"));
mutex::scoped_lock lock(mutex_);
@@ -303,7 +307,7 @@ boost::system::error_code win_object_handle_service::cancel(
ec = boost::system::error_code();
- io_service_.post_deferred_completions(completed_ops);
+ io_context_.post_deferred_completions(completed_ops);
}
else
{
@@ -337,7 +341,7 @@ void win_object_handle_service::wait(
void win_object_handle_service::start_wait_op(
win_object_handle_service::implementation_type& impl, wait_op* op)
{
- io_service_.work_started();
+ io_context_.work_started();
if (is_open(impl))
{
@@ -355,13 +359,13 @@ void win_object_handle_service::start_wait_op(
else
{
lock.unlock();
- io_service_.post_deferred_completion(op);
+ io_context_.post_deferred_completion(op);
}
}
else
{
op->ec_ = boost::asio::error::bad_descriptor;
- io_service_.post_deferred_completion(op);
+ io_context_.post_deferred_completion(op);
}
}
@@ -388,7 +392,7 @@ void win_object_handle_service::register_wait_callback(
}
lock.unlock();
- io_service_.post_deferred_completions(completed_ops);
+ io_context_.post_deferred_completions(completed_ops);
}
}
@@ -430,9 +434,9 @@ void win_object_handle_service::wait_callback(PVOID param, BOOLEAN)
}
}
- io_service_impl& ios = impl->owner_->io_service_;
+ io_context_impl& ioc = impl->owner_->io_context_;
lock.unlock();
- ios.post_deferred_completions(completed_ops);
+ ioc.post_deferred_completions(completed_ops);
}
}
diff --git a/boost/asio/detail/impl/win_thread.ipp b/boost/asio/detail/impl/win_thread.ipp
index e2d9384007..c90c3f3986 100644
--- a/boost/asio/detail/impl/win_thread.ipp
+++ b/boost/asio/detail/impl/win_thread.ipp
@@ -56,6 +56,13 @@ void win_thread::join()
}
}
+std::size_t win_thread::hardware_concurrency()
+{
+ SYSTEM_INFO system_info;
+ ::GetSystemInfo(&system_info);
+ return system_info.dwNumberOfProcessors;
+}
+
void win_thread::start_thread(func_base* arg, unsigned int stack_size)
{
::HANDLE entry_event = 0;
diff --git a/boost/asio/detail/impl/win_tss_ptr.ipp b/boost/asio/detail/impl/win_tss_ptr.ipp
index 3390066695..105cf3022c 100644
--- a/boost/asio/detail/impl/win_tss_ptr.ipp
+++ b/boost/asio/detail/impl/win_tss_ptr.ipp
@@ -32,9 +32,9 @@ namespace detail {
DWORD win_tss_ptr_create()
{
#if defined(UNDER_CE)
- enum { out_of_indexes = 0xFFFFFFFF };
+ const DWORD out_of_indexes = 0xFFFFFFFF;
#else
- enum { out_of_indexes = TLS_OUT_OF_INDEXES };
+ const DWORD out_of_indexes = TLS_OUT_OF_INDEXES;
#endif
DWORD tss_key = ::TlsAlloc();
diff --git a/boost/asio/detail/impl/winrt_ssocket_service_base.ipp b/boost/asio/detail/impl/winrt_ssocket_service_base.ipp
index f5990a97ad..a7a340b70b 100644
--- a/boost/asio/detail/impl/winrt_ssocket_service_base.ipp
+++ b/boost/asio/detail/impl/winrt_ssocket_service_base.ipp
@@ -31,15 +31,15 @@ namespace asio {
namespace detail {
winrt_ssocket_service_base::winrt_ssocket_service_base(
- boost::asio::io_service& io_service)
- : io_service_(use_service<io_service_impl>(io_service)),
- async_manager_(use_service<winrt_async_manager>(io_service)),
+ boost::asio::io_context& io_context)
+ : io_context_(use_service<io_context_impl>(io_context)),
+ async_manager_(use_service<winrt_async_manager>(io_context)),
mutex_(),
impl_list_(0)
{
}
-void winrt_ssocket_service_base::shutdown_service()
+void winrt_ssocket_service_base::base_shutdown()
{
// Close all implementations, causing all operations to complete.
boost::asio::detail::mutex::scoped_lock lock(mutex_);
@@ -149,6 +149,23 @@ boost::system::error_code winrt_ssocket_service_base::close(
return ec;
}
+winrt_ssocket_service_base::native_handle_type
+winrt_ssocket_service_base::release(
+ winrt_ssocket_service_base::base_implementation_type& impl,
+ boost::system::error_code& ec)
+{
+ if (!is_open(impl))
+ return nullptr;
+
+ cancel(impl, ec);
+ if (ec)
+ return nullptr;
+
+ native_handle_type tmp = impl.socket_;
+ impl.socket_ = nullptr;
+ return tmp;
+}
+
std::size_t winrt_ssocket_service_base::do_get_endpoint(
const base_implementation_type& impl, bool local,
void* addr, std::size_t addr_len, boost::system::error_code& ec) const
@@ -382,7 +399,7 @@ void winrt_ssocket_service_base::start_connect_op(
if (!is_open(impl))
{
op->ec_ = boost::asio::error::bad_descriptor;
- io_service_.post_immediate_completion(op, is_continuation);
+ io_context_.post_immediate_completion(op, is_continuation);
return;
}
@@ -411,7 +428,7 @@ void winrt_ssocket_service_base::start_connect_op(
if (op->ec_)
{
- io_service_.post_immediate_completion(op, is_continuation);
+ io_context_.post_immediate_completion(op, is_continuation);
return;
}
@@ -426,7 +443,7 @@ void winrt_ssocket_service_base::start_connect_op(
{
op->ec_ = boost::system::error_code(
e->HResult, boost::system::system_category());
- io_service_.post_immediate_completion(op, is_continuation);
+ io_context_.post_immediate_completion(op, is_continuation);
}
}
@@ -450,7 +467,7 @@ std::size_t winrt_ssocket_service_base::do_send(
try
{
buffer_sequence_adapter<boost::asio::const_buffer,
- boost::asio::const_buffers_1> bufs(boost::asio::buffer(data));
+ boost::asio::const_buffer> bufs(boost::asio::buffer(data));
if (bufs.all_empty())
{
@@ -477,25 +494,25 @@ void winrt_ssocket_service_base::start_send_op(
if (flags)
{
op->ec_ = boost::asio::error::operation_not_supported;
- io_service_.post_immediate_completion(op, is_continuation);
+ io_context_.post_immediate_completion(op, is_continuation);
return;
}
if (!is_open(impl))
{
op->ec_ = boost::asio::error::bad_descriptor;
- io_service_.post_immediate_completion(op, is_continuation);
+ io_context_.post_immediate_completion(op, is_continuation);
return;
}
try
{
buffer_sequence_adapter<boost::asio::const_buffer,
- boost::asio::const_buffers_1> bufs(boost::asio::buffer(data));
+ boost::asio::const_buffer> bufs(boost::asio::buffer(data));
if (bufs.all_empty())
{
- io_service_.post_immediate_completion(op, is_continuation);
+ io_context_.post_immediate_completion(op, is_continuation);
return;
}
@@ -506,7 +523,7 @@ void winrt_ssocket_service_base::start_send_op(
{
op->ec_ = boost::system::error_code(e->HResult,
boost::system::system_category());
- io_service_.post_immediate_completion(op, is_continuation);
+ io_context_.post_immediate_completion(op, is_continuation);
}
}
@@ -530,7 +547,7 @@ std::size_t winrt_ssocket_service_base::do_receive(
try
{
buffer_sequence_adapter<boost::asio::mutable_buffer,
- boost::asio::mutable_buffers_1> bufs(boost::asio::buffer(data));
+ boost::asio::mutable_buffer> bufs(boost::asio::buffer(data));
if (bufs.all_empty())
{
@@ -568,25 +585,25 @@ void winrt_ssocket_service_base::start_receive_op(
if (flags)
{
op->ec_ = boost::asio::error::operation_not_supported;
- io_service_.post_immediate_completion(op, is_continuation);
+ io_context_.post_immediate_completion(op, is_continuation);
return;
}
if (!is_open(impl))
{
op->ec_ = boost::asio::error::bad_descriptor;
- io_service_.post_immediate_completion(op, is_continuation);
+ io_context_.post_immediate_completion(op, is_continuation);
return;
}
try
{
buffer_sequence_adapter<boost::asio::mutable_buffer,
- boost::asio::mutable_buffers_1> bufs(boost::asio::buffer(data));
+ boost::asio::mutable_buffer> bufs(boost::asio::buffer(data));
if (bufs.all_empty())
{
- io_service_.post_immediate_completion(op, is_continuation);
+ io_context_.post_immediate_completion(op, is_continuation);
return;
}
@@ -599,7 +616,7 @@ void winrt_ssocket_service_base::start_receive_op(
{
op->ec_ = boost::system::error_code(e->HResult,
boost::system::system_category());
- io_service_.post_immediate_completion(op, is_continuation);
+ io_context_.post_immediate_completion(op, is_continuation);
}
}
diff --git a/boost/asio/detail/impl/winrt_timer_scheduler.hpp b/boost/asio/detail/impl/winrt_timer_scheduler.hpp
index 8d93e57962..b1522b4673 100644
--- a/boost/asio/detail/impl/winrt_timer_scheduler.hpp
+++ b/boost/asio/detail/impl/winrt_timer_scheduler.hpp
@@ -47,12 +47,12 @@ void winrt_timer_scheduler::schedule_timer(timer_queue<Time_Traits>& queue,
if (shutdown_)
{
- io_service_.post_immediate_completion(op, false);
+ io_context_.post_immediate_completion(op, false);
return;
}
bool earliest = queue.enqueue_timer(time, timer, op);
- io_service_.work_started();
+ io_context_.work_started();
if (earliest)
event_.signal(lock);
}
@@ -66,10 +66,23 @@ std::size_t winrt_timer_scheduler::cancel_timer(timer_queue<Time_Traits>& queue,
op_queue<operation> ops;
std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);
lock.unlock();
- io_service_.post_deferred_completions(ops);
+ io_context_.post_deferred_completions(ops);
return n;
}
+template <typename Time_Traits>
+void winrt_timer_scheduler::move_timer(timer_queue<Time_Traits>& queue,
+ typename timer_queue<Time_Traits>::per_timer_data& to,
+ typename timer_queue<Time_Traits>::per_timer_data& from)
+{
+ boost::asio::detail::mutex::scoped_lock lock(mutex_);
+ op_queue<operation> ops;
+ queue.cancel_timer(to, ops);
+ queue.move_timer(to, from);
+ lock.unlock();
+ scheduler_.post_deferred_completions(ops);
+}
+
} // namespace detail
} // namespace asio
} // namespace boost
diff --git a/boost/asio/detail/impl/winrt_timer_scheduler.ipp b/boost/asio/detail/impl/winrt_timer_scheduler.ipp
index 914849d822..2e8145b6b8 100644
--- a/boost/asio/detail/impl/winrt_timer_scheduler.ipp
+++ b/boost/asio/detail/impl/winrt_timer_scheduler.ipp
@@ -29,9 +29,9 @@ namespace asio {
namespace detail {
winrt_timer_scheduler::winrt_timer_scheduler(
- boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<winrt_timer_scheduler>(io_service),
- io_service_(use_service<io_service_impl>(io_service)),
+ boost::asio::io_context& io_context)
+ : boost::asio::detail::service_base<winrt_timer_scheduler>(io_context),
+ io_context_(use_service<io_context_impl>(io_context)),
mutex_(),
event_(),
timer_queues_(),
@@ -45,10 +45,10 @@ winrt_timer_scheduler::winrt_timer_scheduler(
winrt_timer_scheduler::~winrt_timer_scheduler()
{
- shutdown_service();
+ shutdown();
}
-void winrt_timer_scheduler::shutdown_service()
+void winrt_timer_scheduler::shutdown()
{
boost::asio::detail::mutex::scoped_lock lock(mutex_);
shutdown_ = true;
@@ -65,10 +65,10 @@ void winrt_timer_scheduler::shutdown_service()
op_queue<operation> ops;
timer_queues_.get_all_timers(ops);
- io_service_.abandon_operations(ops);
+ io_context_.abandon_operations(ops);
}
-void winrt_timer_scheduler::fork_service(boost::asio::io_service::fork_event)
+void winrt_timer_scheduler::notify_fork(boost::asio::io_context::fork_event)
{
}
@@ -90,7 +90,7 @@ void winrt_timer_scheduler::run_thread()
if (!ops.empty())
{
lock.unlock();
- io_service_.post_deferred_completions(ops);
+ io_context_.post_deferred_completions(ops);
lock.lock();
}
}
diff --git a/boost/asio/detail/io_control.hpp b/boost/asio/detail/io_control.hpp
index 6c7527d1cf..d235fa1fda 100644
--- a/boost/asio/detail/io_control.hpp
+++ b/boost/asio/detail/io_control.hpp
@@ -26,56 +26,6 @@ namespace asio {
namespace detail {
namespace io_control {
-// IO control command for non-blocking I/O.
-class non_blocking_io
-{
-public:
- // Default constructor.
- non_blocking_io()
- : value_(0)
- {
- }
-
- // Construct with a specific command value.
- non_blocking_io(bool value)
- : value_(value ? 1 : 0)
- {
- }
-
- // Get the name of the IO control command.
- int name() const
- {
- return static_cast<int>(BOOST_ASIO_OS_DEF(FIONBIO));
- }
-
- // Set the value of the I/O control command.
- void set(bool value)
- {
- value_ = value ? 1 : 0;
- }
-
- // Get the current value of the I/O control command.
- bool get() const
- {
- return value_ != 0;
- }
-
- // Get the address of the command data.
- detail::ioctl_arg_type* data()
- {
- return &value_;
- }
-
- // Get the address of the command data.
- const detail::ioctl_arg_type* data() const
- {
- return &value_;
- }
-
-private:
- detail::ioctl_arg_type value_;
-};
-
// I/O control command for getting number of bytes available.
class bytes_readable
{
diff --git a/boost/asio/detail/is_buffer_sequence.hpp b/boost/asio/detail/is_buffer_sequence.hpp
new file mode 100644
index 0000000000..c788c55d28
--- /dev/null
+++ b/boost/asio/detail/is_buffer_sequence.hpp
@@ -0,0 +1,241 @@
+//
+// detail/is_buffer_sequence.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_IS_BUFFER_SEQUENCE_HPP
+#define BOOST_ASIO_DETAIL_IS_BUFFER_SEQUENCE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+class mutable_buffer;
+class const_buffer;
+
+namespace detail {
+
+struct buffer_sequence_memfns_base
+{
+ void begin();
+ void end();
+ void size();
+ void max_size();
+ void capacity();
+ void data();
+ void prepare();
+ void commit();
+ void consume();
+};
+
+template <typename T>
+struct buffer_sequence_memfns_derived
+ : T, buffer_sequence_memfns_base
+{
+};
+
+template <typename T, T>
+struct buffer_sequence_memfns_check
+{
+};
+
+template <typename>
+char (&begin_memfn_helper(...))[2];
+
+template <typename T>
+char begin_memfn_helper(
+ buffer_sequence_memfns_check<
+ void (buffer_sequence_memfns_base::*)(),
+ &buffer_sequence_memfns_derived<T>::begin>*);
+
+template <typename>
+char (&end_memfn_helper(...))[2];
+
+template <typename T>
+char end_memfn_helper(
+ buffer_sequence_memfns_check<
+ void (buffer_sequence_memfns_base::*)(),
+ &buffer_sequence_memfns_derived<T>::end>*);
+
+template <typename>
+char (&size_memfn_helper(...))[2];
+
+template <typename T>
+char size_memfn_helper(
+ buffer_sequence_memfns_check<
+ void (buffer_sequence_memfns_base::*)(),
+ &buffer_sequence_memfns_derived<T>::size>*);
+
+template <typename>
+char (&max_size_memfn_helper(...))[2];
+
+template <typename T>
+char max_size_memfn_helper(
+ buffer_sequence_memfns_check<
+ void (buffer_sequence_memfns_base::*)(),
+ &buffer_sequence_memfns_derived<T>::max_size>*);
+
+template <typename>
+char (&capacity_memfn_helper(...))[2];
+
+template <typename T>
+char capacity_memfn_helper(
+ buffer_sequence_memfns_check<
+ void (buffer_sequence_memfns_base::*)(),
+ &buffer_sequence_memfns_derived<T>::capacity>*);
+
+template <typename>
+char (&data_memfn_helper(...))[2];
+
+template <typename T>
+char data_memfn_helper(
+ buffer_sequence_memfns_check<
+ void (buffer_sequence_memfns_base::*)(),
+ &buffer_sequence_memfns_derived<T>::data>*);
+
+template <typename>
+char (&prepare_memfn_helper(...))[2];
+
+template <typename T>
+char prepare_memfn_helper(
+ buffer_sequence_memfns_check<
+ void (buffer_sequence_memfns_base::*)(),
+ &buffer_sequence_memfns_derived<T>::data>*);
+
+template <typename>
+char (&commit_memfn_helper(...))[2];
+
+template <typename T>
+char commit_memfn_helper(
+ buffer_sequence_memfns_check<
+ void (buffer_sequence_memfns_base::*)(),
+ &buffer_sequence_memfns_derived<T>::commit>*);
+
+template <typename>
+char (&consume_memfn_helper(...))[2];
+
+template <typename T>
+char consume_memfn_helper(
+ buffer_sequence_memfns_check<
+ void (buffer_sequence_memfns_base::*)(),
+ &buffer_sequence_memfns_derived<T>::consume>*);
+
+template <typename, typename>
+char (&buffer_element_type_helper(...))[2];
+
+#if defined(BOOST_ASIO_HAS_DECL_TYPE)
+
+template <typename T, typename Buffer>
+char buffer_element_type_helper(T* t,
+ typename enable_if<is_convertible<
+ decltype(*buffer_sequence_begin(*t)),
+ Buffer>::value>::type*);
+
+#else // defined(BOOST_ASIO_HAS_DECL_TYPE)
+
+template <typename T, typename Buffer>
+char buffer_element_type_helper(
+ typename T::const_iterator*,
+ typename enable_if<is_convertible<
+ typename T::value_type, Buffer>::value>::type*);
+
+#endif // defined(BOOST_ASIO_HAS_DECL_TYPE)
+
+template <typename>
+char (&const_buffers_type_typedef_helper(...))[2];
+
+template <typename T>
+char const_buffers_type_typedef_helper(
+ typename T::const_buffers_type*);
+
+template <typename>
+char (&mutable_buffers_type_typedef_helper(...))[2];
+
+template <typename T>
+char mutable_buffers_type_typedef_helper(
+ typename T::mutable_buffers_type*);
+
+template <typename T, typename Buffer>
+struct is_buffer_sequence_class
+ : integral_constant<bool,
+ sizeof(begin_memfn_helper<T>(0)) != 1 &&
+ sizeof(end_memfn_helper<T>(0)) != 1 &&
+ sizeof(buffer_element_type_helper<T, Buffer>(0, 0)) == 1>
+{
+};
+
+template <typename T, typename Buffer>
+struct is_buffer_sequence
+ : conditional<is_class<T>::value,
+ is_buffer_sequence_class<T, Buffer>,
+ false_type>::type
+{
+};
+
+template <>
+struct is_buffer_sequence<mutable_buffer, mutable_buffer>
+ : true_type
+{
+};
+
+template <>
+struct is_buffer_sequence<mutable_buffer, const_buffer>
+ : true_type
+{
+};
+
+template <>
+struct is_buffer_sequence<const_buffer, const_buffer>
+ : true_type
+{
+};
+
+template <>
+struct is_buffer_sequence<const_buffer, mutable_buffer>
+ : false_type
+{
+};
+
+template <typename T>
+struct is_dynamic_buffer_class
+ : integral_constant<bool,
+ sizeof(size_memfn_helper<T>(0)) != 1 &&
+ sizeof(max_size_memfn_helper<T>(0)) != 1 &&
+ sizeof(capacity_memfn_helper<T>(0)) != 1 &&
+ sizeof(data_memfn_helper<T>(0)) != 1 &&
+ sizeof(consume_memfn_helper<T>(0)) != 1 &&
+ sizeof(prepare_memfn_helper<T>(0)) != 1 &&
+ sizeof(commit_memfn_helper<T>(0)) != 1 &&
+ sizeof(const_buffers_type_typedef_helper<T>(0)) == 1 &&
+ sizeof(mutable_buffers_type_typedef_helper<T>(0)) == 1>
+{
+};
+
+template <typename T>
+struct is_dynamic_buffer
+ : conditional<is_class<T>::value,
+ is_dynamic_buffer_class<T>,
+ false_type>::type
+{
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_IS_BUFFER_SEQUENCE_HPP
diff --git a/boost/asio/detail/is_executor.hpp b/boost/asio/detail/is_executor.hpp
new file mode 100644
index 0000000000..43db5d0120
--- /dev/null
+++ b/boost/asio/detail/is_executor.hpp
@@ -0,0 +1,128 @@
+//
+// detail/is_executor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_IS_EXECUTOR_HPP
+#define BOOST_ASIO_DETAIL_IS_EXECUTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+struct executor_memfns_base
+{
+ void context();
+ void on_work_started();
+ void on_work_finished();
+ void dispatch();
+ void post();
+ void defer();
+};
+
+template <typename T>
+struct executor_memfns_derived
+ : T, executor_memfns_base
+{
+};
+
+template <typename T, T>
+struct executor_memfns_check
+{
+};
+
+template <typename>
+char (&context_memfn_helper(...))[2];
+
+template <typename T>
+char context_memfn_helper(
+ executor_memfns_check<
+ void (executor_memfns_base::*)(),
+ &executor_memfns_derived<T>::context>*);
+
+template <typename>
+char (&on_work_started_memfn_helper(...))[2];
+
+template <typename T>
+char on_work_started_memfn_helper(
+ executor_memfns_check<
+ void (executor_memfns_base::*)(),
+ &executor_memfns_derived<T>::on_work_started>*);
+
+template <typename>
+char (&on_work_finished_memfn_helper(...))[2];
+
+template <typename T>
+char on_work_finished_memfn_helper(
+ executor_memfns_check<
+ void (executor_memfns_base::*)(),
+ &executor_memfns_derived<T>::on_work_finished>*);
+
+template <typename>
+char (&dispatch_memfn_helper(...))[2];
+
+template <typename T>
+char dispatch_memfn_helper(
+ executor_memfns_check<
+ void (executor_memfns_base::*)(),
+ &executor_memfns_derived<T>::dispatch>*);
+
+template <typename>
+char (&post_memfn_helper(...))[2];
+
+template <typename T>
+char post_memfn_helper(
+ executor_memfns_check<
+ void (executor_memfns_base::*)(),
+ &executor_memfns_derived<T>::post>*);
+
+template <typename>
+char (&defer_memfn_helper(...))[2];
+
+template <typename T>
+char defer_memfn_helper(
+ executor_memfns_check<
+ void (executor_memfns_base::*)(),
+ &executor_memfns_derived<T>::defer>*);
+
+template <typename T>
+struct is_executor_class
+ : integral_constant<bool,
+ sizeof(context_memfn_helper<T>(0)) != 1 &&
+ sizeof(on_work_started_memfn_helper<T>(0)) != 1 &&
+ sizeof(on_work_finished_memfn_helper<T>(0)) != 1 &&
+ sizeof(dispatch_memfn_helper<T>(0)) != 1 &&
+ sizeof(post_memfn_helper<T>(0)) != 1 &&
+ sizeof(defer_memfn_helper<T>(0)) != 1>
+{
+};
+
+template <typename T>
+struct is_executor
+ : conditional<is_class<T>::value,
+ is_executor_class<T>,
+ false_type>::type
+{
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_IS_EXECUTOR_HPP
diff --git a/boost/asio/detail/kqueue_reactor.hpp b/boost/asio/detail/kqueue_reactor.hpp
index c6182b4d55..492b7ff016 100644
--- a/boost/asio/detail/kqueue_reactor.hpp
+++ b/boost/asio/detail/kqueue_reactor.hpp
@@ -35,7 +35,7 @@
#include <boost/asio/detail/timer_queue_set.hpp>
#include <boost/asio/detail/wait_op.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/execution_context.hpp>
// Older versions of Mac OS X may not define EV_OOBAND.
#if !defined(EV_OOBAND)
@@ -48,9 +48,15 @@ namespace boost {
namespace asio {
namespace detail {
+class scheduler;
+
class kqueue_reactor
- : public boost::asio::detail::service_base<kqueue_reactor>
+ : public execution_context_service_base<kqueue_reactor>
{
+private:
+ // The mutex type used by this reactor.
+ typedef conditionally_enabled_mutex mutex;
+
public:
enum op_types { read_op = 0, write_op = 1,
connect_op = 1, except_op = 2, max_ops = 3 };
@@ -58,6 +64,8 @@ public:
// Per-descriptor queues.
struct descriptor_state
{
+ descriptor_state(bool locking) : mutex_(locking) {}
+
friend class kqueue_reactor;
friend class object_pool_access;
@@ -75,17 +83,17 @@ public:
typedef descriptor_state* per_descriptor_data;
// Constructor.
- BOOST_ASIO_DECL kqueue_reactor(boost::asio::io_service& io_service);
+ BOOST_ASIO_DECL kqueue_reactor(boost::asio::execution_context& ctx);
// Destructor.
BOOST_ASIO_DECL ~kqueue_reactor();
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Recreate internal descriptors following a fork.
- BOOST_ASIO_DECL void fork_service(
- boost::asio::io_service::fork_event fork_ev);
+ BOOST_ASIO_DECL void notify_fork(
+ boost::asio::execution_context::fork_event fork_ev);
// Initialise the task.
BOOST_ASIO_DECL void init_task();
@@ -109,7 +117,7 @@ public:
// Post a reactor operation for immediate completion.
void post_immediate_completion(reactor_op* op, bool is_continuation)
{
- io_service_.post_immediate_completion(op, is_continuation);
+ scheduler_.post_immediate_completion(op, is_continuation);
}
// Start a new operation. The reactor operation will be performed when the
@@ -163,8 +171,14 @@ public:
typename timer_queue<Time_Traits>::per_timer_data& timer,
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
+ // 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);
+
// Run the kqueue loop.
- BOOST_ASIO_DECL void run(bool block, op_queue<operation>& ops);
+ BOOST_ASIO_DECL void run(long usec, op_queue<operation>& ops);
// Interrupt the kqueue loop.
BOOST_ASIO_DECL void interrupt();
@@ -187,10 +201,10 @@ private:
BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
// Get the timeout value for the kevent call.
- BOOST_ASIO_DECL timespec* get_timeout(timespec& ts);
+ BOOST_ASIO_DECL timespec* get_timeout(long usec, timespec& ts);
- // The io_service implementation used to post completions.
- io_service_impl& io_service_;
+ // The scheduler used to post completions.
+ scheduler& scheduler_;
// Mutex to protect access to internal data.
mutex mutex_;
diff --git a/boost/asio/detail/macos_fenced_block.hpp b/boost/asio/detail/macos_fenced_block.hpp
index 5ab7f91c5e..20a995ebec 100644
--- a/boost/asio/detail/macos_fenced_block.hpp
+++ b/boost/asio/detail/macos_fenced_block.hpp
@@ -20,6 +20,7 @@
#if defined(__MACH__) && defined(__APPLE__)
#include <libkern/OSAtomic.h>
+#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/push_options.hpp>
diff --git a/boost/asio/detail/memory.hpp b/boost/asio/detail/memory.hpp
index 479b57a3d1..c0a205e169 100644
--- a/boost/asio/detail/memory.hpp
+++ b/boost/asio/detail/memory.hpp
@@ -18,14 +18,55 @@
#include <boost/asio/detail/config.hpp>
#include <memory>
+#if !defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
+# include <boost/shared_ptr.hpp>
+# include <boost/weak_ptr.hpp>
+#endif // !defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
+
+#if !defined(BOOST_ASIO_HAS_STD_ADDRESSOF)
+# include <boost/utility/addressof.hpp>
+#endif // !defined(BOOST_ASIO_HAS_STD_ADDRESSOF)
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+#if defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
+using std::shared_ptr;
+using std::weak_ptr;
+#else // defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
+using boost::shared_ptr;
+using boost::weak_ptr;
+#endif // defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
+
+#if defined(BOOST_ASIO_HAS_STD_ADDRESSOF)
+using std::addressof;
+#else // defined(BOOST_ASIO_HAS_STD_ADDRESSOF)
+using boost::addressof;
+#endif // defined(BOOST_ASIO_HAS_STD_ADDRESSOF)
+
+} // namespace detail
+
#if defined(BOOST_ASIO_HAS_CXX11_ALLOCATORS)
+using std::allocator_arg_t;
+# define BOOST_ASIO_USES_ALLOCATOR(t) \
+ namespace std { \
+ template <typename Allocator> \
+ struct uses_allocator<t, Allocator> : true_type {}; \
+ } \
+ /**/
# define BOOST_ASIO_REBIND_ALLOC(alloc, t) \
typename std::allocator_traits<alloc>::template rebind_alloc<t>
/**/
#else // defined(BOOST_ASIO_HAS_CXX11_ALLOCATORS)
+struct allocator_arg_t {};
+# define BOOST_ASIO_USES_ALLOCATOR(t)
# define BOOST_ASIO_REBIND_ALLOC(alloc, t) \
typename alloc::template rebind<t>::other
/**/
#endif // defined(BOOST_ASIO_HAS_CXX11_ALLOCATORS)
+} // namespace asio
+} // namespace boost
+
#endif // BOOST_ASIO_DETAIL_MEMORY_HPP
diff --git a/boost/asio/detail/null_event.hpp b/boost/asio/detail/null_event.hpp
index 28ba5ede55..3bc74afb68 100644
--- a/boost/asio/detail/null_event.hpp
+++ b/boost/asio/detail/null_event.hpp
@@ -16,9 +16,6 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-
-#if !defined(BOOST_ASIO_HAS_THREADS)
-
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -76,7 +73,20 @@ public:
template <typename Lock>
void wait(Lock&)
{
+ do_wait();
}
+
+ // Timed wait for the event to become signalled.
+ template <typename Lock>
+ bool wait_for_usec(Lock&, long usec)
+ {
+ do_wait_for_usec(usec);
+ return true;
+ }
+
+private:
+ BOOST_ASIO_DECL static void do_wait();
+ BOOST_ASIO_DECL static void do_wait_for_usec(long usec);
};
} // namespace detail
@@ -85,6 +95,8 @@ public:
#include <boost/asio/detail/pop_options.hpp>
-#endif // !defined(BOOST_ASIO_HAS_THREADS)
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/null_event.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
#endif // BOOST_ASIO_DETAIL_NULL_EVENT_HPP
diff --git a/boost/asio/detail/null_fenced_block.hpp b/boost/asio/detail/null_fenced_block.hpp
index 27029b9e31..6d2b22f8cf 100644
--- a/boost/asio/detail/null_fenced_block.hpp
+++ b/boost/asio/detail/null_fenced_block.hpp
@@ -15,6 +15,8 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+#include <boost/asio/detail/noncopyable.hpp>
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
diff --git a/boost/asio/detail/null_global.hpp b/boost/asio/detail/null_global.hpp
new file mode 100644
index 0000000000..fa24b5cbaf
--- /dev/null
+++ b/boost/asio/detail/null_global.hpp
@@ -0,0 +1,61 @@
+//
+// detail/null_global.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_NULL_GLOBAL_HPP
+#define BOOST_ASIO_DETAIL_NULL_GLOBAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+struct null_global_impl
+{
+ null_global_impl()
+ : ptr_(0)
+ {
+ }
+
+ // Destructor automatically cleans up the global.
+ ~null_global_impl()
+ {
+ delete ptr_;
+ }
+
+ static null_global_impl instance_;
+ T* ptr_;
+};
+
+template <typename T>
+null_global_impl<T> null_global_impl<T>::instance_;
+
+template <typename T>
+T& null_global()
+{
+ if (null_global_impl<T>::instance_.ptr_ == 0)
+ null_global_impl<T>::instance_.ptr_ = new T;
+ return *null_global_impl<T>::instance_.ptr_;
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_NULL_GLOBAL_HPP
diff --git a/boost/asio/detail/null_reactor.hpp b/boost/asio/detail/null_reactor.hpp
index 2cfce63a4c..30a07390a7 100644
--- a/boost/asio/detail/null_reactor.hpp
+++ b/boost/asio/detail/null_reactor.hpp
@@ -17,9 +17,10 @@
#include <boost/asio/detail/config.hpp>
-#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+#if defined(BOOST_ASIO_HAS_IOCP) || defined(BOOST_ASIO_WINDOWS_RUNTIME)
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/scheduler_operation.hpp>
+#include <boost/asio/execution_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -28,12 +29,12 @@ namespace asio {
namespace detail {
class null_reactor
- : public boost::asio::detail::service_base<null_reactor>
+ : public execution_context_service_base<null_reactor>
{
public:
// Constructor.
- null_reactor(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<null_reactor>(io_service)
+ null_reactor(boost::asio::execution_context& ctx)
+ : execution_context_service_base<null_reactor>(ctx)
{
}
@@ -43,12 +44,12 @@ public:
}
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
}
// No-op because should never be called.
- void run(bool /*block*/, op_queue<operation>& /*ops*/)
+ void run(long /*usec*/, op_queue<scheduler_operation>& /*ops*/)
{
}
@@ -64,6 +65,6 @@ public:
#include <boost/asio/detail/pop_options.hpp>
-#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+#endif // defined(BOOST_ASIO_HAS_IOCP) || defined(BOOST_ASIO_WINDOWS_RUNTIME)
#endif // BOOST_ASIO_DETAIL_NULL_REACTOR_HPP
diff --git a/boost/asio/detail/null_socket_service.hpp b/boost/asio/detail/null_socket_service.hpp
index bf06ebb545..73a11cf9e8 100644
--- a/boost/asio/detail/null_socket_service.hpp
+++ b/boost/asio/detail/null_socket_service.hpp
@@ -21,7 +21,7 @@
#include <boost/asio/buffer.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/socket_base.hpp>
#include <boost/asio/detail/bind_handler.hpp>
@@ -32,7 +32,8 @@ namespace asio {
namespace detail {
template <typename Protocol>
-class null_socket_service
+class null_socket_service :
+ public service_base<null_socket_service<Protocol> >
{
public:
// The protocol type.
@@ -50,13 +51,14 @@ public:
};
// Constructor.
- null_socket_service(boost::asio::io_service& io_service)
- : io_service_(io_service)
+ null_socket_service(boost::asio::io_context& io_context)
+ : service_base<null_socket_service<Protocol> >(io_context),
+ io_context_(io_context)
{
}
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
}
@@ -119,6 +121,14 @@ public:
return ec;
}
+ // Release ownership of the socket.
+ native_handle_type release(implementation_type&,
+ boost::system::error_code& ec)
+ {
+ ec = boost::asio::error::operation_not_supported;
+ return 0;
+ }
+
// Get the native socket representation.
native_handle_type native_handle(implementation_type&)
{
@@ -269,7 +279,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.post(detail::bind_handler(handler, ec, bytes_transferred));
+ io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
}
// Start an asynchronous wait until data can be sent without blocking.
@@ -279,7 +289,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.post(detail::bind_handler(handler, ec, bytes_transferred));
+ io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
}
// Receive some data from the peer. Returns the number of bytes received.
@@ -307,7 +317,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.post(detail::bind_handler(handler, ec, bytes_transferred));
+ io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
}
// Wait until data can be received without blocking.
@@ -317,7 +327,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.post(detail::bind_handler(handler, ec, bytes_transferred));
+ io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
}
// Receive some data with associated flags. Returns the number of bytes
@@ -349,7 +359,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.post(detail::bind_handler(handler, ec, bytes_transferred));
+ io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
}
// Wait until data can be received without blocking.
@@ -360,7 +370,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.post(detail::bind_handler(handler, ec, bytes_transferred));
+ io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
}
// Send a datagram to the specified endpoint. Returns the number of bytes
@@ -392,7 +402,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.post(detail::bind_handler(handler, ec, bytes_transferred));
+ io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
}
// Start an asynchronous wait until data can be sent without blocking.
@@ -402,7 +412,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.post(detail::bind_handler(handler, ec, bytes_transferred));
+ io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
}
// Receive a datagram with the endpoint of the sender. Returns the number of
@@ -435,7 +445,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.post(detail::bind_handler(handler, ec, bytes_transferred));
+ io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
}
// Wait until data can be received without blocking.
@@ -446,7 +456,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.post(detail::bind_handler(handler, ec, bytes_transferred));
+ io_context_.post(detail::bind_handler(handler, ec, bytes_transferred));
}
// Accept a new connection.
@@ -465,7 +475,7 @@ public:
endpoint_type*, Handler& handler)
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
- io_service_.post(detail::bind_handler(handler, ec));
+ io_context_.post(detail::bind_handler(handler, ec));
}
// Connect the socket to the specified endpoint.
@@ -482,11 +492,11 @@ public:
const endpoint_type&, Handler& handler)
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
- io_service_.post(detail::bind_handler(handler, ec));
+ io_context_.post(detail::bind_handler(handler, ec));
}
private:
- boost::asio::io_service& io_service_;
+ boost::asio::io_context& io_context_;
};
} // namespace detail
diff --git a/boost/asio/detail/null_thread.hpp b/boost/asio/detail/null_thread.hpp
index 5e9b458638..bdb9912be3 100644
--- a/boost/asio/detail/null_thread.hpp
+++ b/boost/asio/detail/null_thread.hpp
@@ -50,6 +50,12 @@ public:
void join()
{
}
+
+ // Get number of CPUs.
+ static std::size_t hardware_concurrency()
+ {
+ return 1;
+ }
};
} // namespace detail
diff --git a/boost/asio/detail/object_pool.hpp b/boost/asio/detail/object_pool.hpp
index 692efed09d..3affeb8dab 100644
--- a/boost/asio/detail/object_pool.hpp
+++ b/boost/asio/detail/object_pool.hpp
@@ -35,6 +35,12 @@ public:
return new Object;
}
+ template <typename Object, typename Arg>
+ static Object* create(Arg arg)
+ {
+ return new Object(arg);
+ }
+
template <typename Object>
static void destroy(Object* o)
{
@@ -97,6 +103,25 @@ public:
return o;
}
+ // Allocate a new object with an argument.
+ template <typename Arg>
+ Object* alloc(Arg arg)
+ {
+ Object* o = free_list_;
+ if (o)
+ free_list_ = object_pool_access::next(free_list_);
+ else
+ o = object_pool_access::create<Object>(arg);
+
+ object_pool_access::next(o) = live_list_;
+ object_pool_access::prev(o) = 0;
+ if (live_list_)
+ object_pool_access::prev(live_list_) = o;
+ live_list_ = o;
+
+ return o;
+ }
+
// Free an object. Moves it to the free list. No destructors are run.
void free(Object* o)
{
diff --git a/boost/asio/detail/operation.hpp b/boost/asio/detail/operation.hpp
index a186a1f4d8..be62d12514 100644
--- a/boost/asio/detail/operation.hpp
+++ b/boost/asio/detail/operation.hpp
@@ -20,7 +20,7 @@
#if defined(BOOST_ASIO_HAS_IOCP)
# include <boost/asio/detail/win_iocp_operation.hpp>
#else
-# include <boost/asio/detail/task_io_service_operation.hpp>
+# include <boost/asio/detail/scheduler_operation.hpp>
#endif
namespace boost {
@@ -30,7 +30,7 @@ namespace detail {
#if defined(BOOST_ASIO_HAS_IOCP)
typedef win_iocp_operation operation;
#else
-typedef task_io_service_operation operation;
+typedef scheduler_operation operation;
#endif
} // namespace detail
diff --git a/boost/asio/detail/pop_options.hpp b/boost/asio/detail/pop_options.hpp
index 29213ede7b..7126d75040 100644
--- a/boost/asio/detail/pop_options.hpp
+++ b/boost/asio/detail/pop_options.hpp
@@ -67,6 +67,10 @@
# pragma GCC visibility pop
# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# if (__GNUC__ >= 7)
+# pragma GCC diagnostic pop
+# endif // (__GNUC__ >= 7)
+
#elif defined(__KCC)
// Kai C++
diff --git a/boost/asio/detail/posix_event.hpp b/boost/asio/detail/posix_event.hpp
index 4eae96e2a8..970f298638 100644
--- a/boost/asio/detail/posix_event.hpp
+++ b/boost/asio/detail/posix_event.hpp
@@ -108,6 +108,39 @@ public:
}
}
+ // Timed wait for the event to become signalled.
+ template <typename Lock>
+ bool wait_for_usec(Lock& lock, long usec)
+ {
+ BOOST_ASIO_ASSERT(lock.locked());
+ if ((state_ & 1) == 0)
+ {
+ state_ += 2;
+ timespec ts;
+#if (defined(__MACH__) && defined(__APPLE__)) \
+ || (defined(__ANDROID__) && (__ANDROID_API__ < 21))
+ ts.tv_sec = usec / 1000000;
+ ts.tv_nsec = (usec % 1000000) * 1000;
+ ::pthread_cond_timedwait_relative_np(
+ &cond_, &lock.mutex().mutex_, &ts); // Ignore EINVAL.
+#else // (defined(__MACH__) && defined(__APPLE__))
+ // || (defined(__ANDROID__) && (__ANDROID_API__ < 21))
+ if (::clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+ {
+ ts.tv_sec += usec / 1000000;
+ ts.tv_nsec = (usec % 1000000) * 1000;
+ ts.tv_sec += ts.tv_nsec / 1000000000;
+ ts.tv_nsec = ts.tv_nsec % 1000000000;
+ ::pthread_cond_timedwait(&cond_,
+ &lock.mutex().mutex_, &ts); // Ignore EINVAL.
+ }
+#endif // (defined(__MACH__) && defined(__APPLE__))
+ // || (defined(__ANDROID__) && (__ANDROID_API__ < 21))
+ state_ -= 2;
+ }
+ return (state_ & 1) != 0;
+ }
+
private:
::pthread_cond_t cond_;
std::size_t state_;
diff --git a/boost/asio/detail/posix_global.hpp b/boost/asio/detail/posix_global.hpp
new file mode 100644
index 0000000000..463809fc29
--- /dev/null
+++ b/boost/asio/detail/posix_global.hpp
@@ -0,0 +1,82 @@
+//
+// detail/posix_global.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_POSIX_GLOBAL_HPP
+#define BOOST_ASIO_DETAIL_POSIX_GLOBAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_PTHREADS)
+
+#include <exception>
+#include <pthread.h>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+struct posix_global_impl
+{
+ // Helper function to perform initialisation.
+ static void do_init()
+ {
+ instance_.static_ptr_ = instance_.ptr_ = new T;
+ }
+
+ // Destructor automatically cleans up the global.
+ ~posix_global_impl()
+ {
+ delete static_ptr_;
+ }
+
+ static ::pthread_once_t init_once_;
+ static T* static_ptr_;
+ static posix_global_impl instance_;
+ T* ptr_;
+};
+
+template <typename T>
+::pthread_once_t posix_global_impl<T>::init_once_ = PTHREAD_ONCE_INIT;
+
+template <typename T>
+T* posix_global_impl<T>::static_ptr_ = 0;
+
+template <typename T>
+posix_global_impl<T> posix_global_impl<T>::instance_;
+
+template <typename T>
+T& posix_global()
+{
+ int result = ::pthread_once(
+ &posix_global_impl<T>::init_once_,
+ &posix_global_impl<T>::do_init);
+
+ if (result != 0)
+ std::terminate();
+
+ return *posix_global_impl<T>::instance_.ptr_;
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_PTHREADS)
+
+#endif // BOOST_ASIO_DETAIL_POSIX_GLOBAL_HPP
diff --git a/boost/asio/detail/posix_thread.hpp b/boost/asio/detail/posix_thread.hpp
index ddf5ba46f3..985e14028f 100644
--- a/boost/asio/detail/posix_thread.hpp
+++ b/boost/asio/detail/posix_thread.hpp
@@ -19,6 +19,7 @@
#if defined(BOOST_ASIO_HAS_PTHREADS)
+#include <cstddef>
#include <pthread.h>
#include <boost/asio/detail/noncopyable.hpp>
@@ -51,6 +52,9 @@ public:
// Wait for the thread to exit.
BOOST_ASIO_DECL void join();
+ // Get number of CPUs.
+ BOOST_ASIO_DECL static std::size_t hardware_concurrency();
+
private:
friend void* boost_asio_detail_posix_thread_function(void* arg);
diff --git a/boost/asio/detail/push_options.hpp b/boost/asio/detail/push_options.hpp
index ae189c0519..08e541d0d1 100644
--- a/boost/asio/detail/push_options.hpp
+++ b/boost/asio/detail/push_options.hpp
@@ -71,6 +71,11 @@
# pragma GCC visibility push (default)
# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)
+# if (__GNUC__ >= 7)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+# endif // (__GNUC__ >= 7)
+
#elif defined(__KCC)
// Kai C++
@@ -135,6 +140,10 @@
# pragma warning (disable:4512)
# pragma warning (disable:4610)
# pragma warning (disable:4675)
+# if (_MSC_VER < 1600)
+// Visual Studio 2008 generates spurious warnings about unused parameters.
+# pragma warning (disable:4100)
+# endif // (_MSC_VER < 1600)
# if defined(_M_IX86) && defined(_Wp64)
// The /Wp64 option is broken. If you want to check 64 bit portability, use a
// 64 bit compiler!
diff --git a/boost/asio/detail/reactive_descriptor_service.hpp b/boost/asio/detail/reactive_descriptor_service.hpp
index 3d6d1e98c8..f413edbc7b 100644
--- a/boost/asio/detail/reactive_descriptor_service.hpp
+++ b/boost/asio/detail/reactive_descriptor_service.hpp
@@ -22,17 +22,19 @@
&& !defined(__CYGWIN__)
#include <boost/asio/buffer.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/descriptor_ops.hpp>
#include <boost/asio/detail/descriptor_read_op.hpp>
#include <boost/asio/detail/descriptor_write_op.hpp>
#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/reactive_null_buffers_op.hpp>
+#include <boost/asio/detail/reactive_wait_op.hpp>
#include <boost/asio/detail/reactor.hpp>
+#include <boost/asio/posix/descriptor_base.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -40,7 +42,8 @@ namespace boost {
namespace asio {
namespace detail {
-class reactive_descriptor_service
+class reactive_descriptor_service :
+ public service_base<reactive_descriptor_service>
{
public:
// The native type of a descriptor.
@@ -74,10 +77,10 @@ public:
// Constructor.
BOOST_ASIO_DECL reactive_descriptor_service(
- boost::asio::io_service& io_service);
+ boost::asio::io_context& io_context);
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Construct a new descriptor implementation.
BOOST_ASIO_DECL void construct(implementation_type& impl);
@@ -162,6 +165,71 @@ public:
return ec;
}
+ // Wait for the descriptor to become ready to read, ready to write, or to have
+ // pending error conditions.
+ boost::system::error_code wait(implementation_type& impl,
+ posix::descriptor_base::wait_type w, boost::system::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 = boost::asio::error::invalid_argument;
+ break;
+ }
+
+ return ec;
+ }
+
+ // Asynchronously wait for the descriptor to become ready to read, ready to
+ // write, or to have pending error conditions.
+ template <typename Handler>
+ void async_wait(implementation_type& impl,
+ posix::descriptor_base::wait_type w, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_wait_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor",
+ &impl, impl.descriptor_, "async_wait"));
+
+ int op_type;
+ switch (w)
+ {
+ case posix::descriptor_base::wait_read:
+ op_type = reactor::read_op;
+ break;
+ case posix::descriptor_base::wait_write:
+ op_type = reactor::write_op;
+ break;
+ case posix::descriptor_base::wait_error:
+ op_type = reactor::except_op;
+ break;
+ default:
+ p.p->ec_ = boost::asio::error::invalid_argument;
+ reactor_.post_immediate_completion(p.p, is_continuation);
+ p.v = p.p = 0;
+ return;
+ }
+
+ start_op(impl, op_type, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
// Write some data to the descriptor.
template <typename ConstBufferSequence>
size_t write_some(implementation_type& impl,
@@ -196,11 +264,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef descriptor_write_op<ConstBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.descriptor_, buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor", &impl, "async_write_some"));
+ BOOST_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<boost::asio::const_buffer,
@@ -219,12 +287,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor",
- &impl, "async_write_some(null_buffers)"));
+ BOOST_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);
p.v = p.p = 0;
@@ -264,11 +331,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef descriptor_read_op<MutableBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.descriptor_, buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor", &impl, "async_read_some"));
+ BOOST_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<boost::asio::mutable_buffer,
@@ -287,12 +354,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "descriptor",
- &impl, "async_read_some(null_buffers)"));
+ BOOST_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);
p.v = p.p = 0;
diff --git a/boost/asio/detail/reactive_null_buffers_op.hpp b/boost/asio/detail/reactive_null_buffers_op.hpp
index 4b1c7fedbf..0983b8a52e 100644
--- a/boost/asio/detail/reactive_null_buffers_op.hpp
+++ b/boost/asio/detail/reactive_null_buffers_op.hpp
@@ -16,10 +16,10 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -39,22 +39,24 @@ public:
&reactive_null_buffers_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static bool do_perform(reactor_op*)
+ static status do_perform(reactor_op*)
{
- return true;
+ return done;
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -72,7 +74,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/reactive_serial_port_service.hpp b/boost/asio/detail/reactive_serial_port_service.hpp
index 4976fbd08e..225f0828f5 100644
--- a/boost/asio/detail/reactive_serial_port_service.hpp
+++ b/boost/asio/detail/reactive_serial_port_service.hpp
@@ -23,7 +23,7 @@
#include <string>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/serial_port_base.hpp>
#include <boost/asio/detail/descriptor_ops.hpp>
#include <boost/asio/detail/reactive_descriptor_service.hpp>
@@ -35,7 +35,8 @@ namespace asio {
namespace detail {
// Extend reactive_descriptor_service to provide serial port support.
-class reactive_serial_port_service
+class reactive_serial_port_service :
+ public service_base<reactive_serial_port_service>
{
public:
// The native type of a serial port.
@@ -45,10 +46,10 @@ public:
typedef reactive_descriptor_service::implementation_type implementation_type;
BOOST_ASIO_DECL reactive_serial_port_service(
- boost::asio::io_service& io_service);
+ boost::asio::io_context& io_context);
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Construct a new serial port implementation.
void construct(implementation_type& impl)
@@ -190,8 +191,8 @@ private:
static boost::system::error_code store_option(const void* option,
termios& storage, boost::system::error_code& ec)
{
- return static_cast<const SettableSerialPortOption*>(option)->store(
- storage, ec);
+ static_cast<const SettableSerialPortOption*>(option)->store(storage, ec);
+ return ec;
}
// Helper function to set a serial port option.
@@ -208,7 +209,8 @@ private:
static boost::system::error_code load_option(void* option,
const termios& storage, boost::system::error_code& ec)
{
- return static_cast<GettableSerialPortOption*>(option)->load(storage, ec);
+ static_cast<GettableSerialPortOption*>(option)->load(storage, ec);
+ return ec;
}
// Helper function to get a serial port option.
diff --git a/boost/asio/detail/reactive_socket_accept_op.hpp b/boost/asio/detail/reactive_socket_accept_op.hpp
index fec6bddb55..ca996b2ab5 100644
--- a/boost/asio/detail/reactive_socket_accept_op.hpp
+++ b/boost/asio/detail/reactive_socket_accept_op.hpp
@@ -16,10 +16,10 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/socket_holder.hpp>
#include <boost/asio/detail/socket_ops.hpp>
@@ -42,40 +42,48 @@ public:
state_(state),
peer_(peer),
protocol_(protocol),
- peer_endpoint_(peer_endpoint)
+ peer_endpoint_(peer_endpoint),
+ addrlen_(peer_endpoint ? peer_endpoint->capacity() : 0)
{
}
- static bool do_perform(reactor_op* base)
+ static status do_perform(reactor_op* base)
{
reactive_socket_accept_op_base* o(
static_cast<reactive_socket_accept_op_base*>(base));
- std::size_t addrlen = o->peer_endpoint_ ? o->peer_endpoint_->capacity() : 0;
socket_type new_socket = invalid_socket;
- 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);
+ status result = socket_ops::non_blocking_accept(o->socket_,
+ o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0,
+ o->peer_endpoint_ ? &o->addrlen_ : 0, o->ec_, new_socket)
+ ? done : not_done;
+ o->new_socket_.reset(new_socket);
- // On success, assign new connection to peer socket object.
- if (new_socket != invalid_socket)
- {
- socket_holder new_socket_holder(new_socket);
- if (o->peer_endpoint_)
- o->peer_endpoint_->resize(addrlen);
- if (!o->peer_.assign(o->protocol_, new_socket, o->ec_))
- new_socket_holder.release();
- }
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_accept", o->ec_));
return result;
}
+ 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_;
+ std::size_t addrlen_;
};
template <typename Socket, typename Protocol, typename Handler>
@@ -92,17 +100,23 @@ public:
protocol, peer_endpoint, &reactive_socket_accept_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
+
+ // On success, assign new connection to peer socket object.
+ if (owner)
+ o->do_assign();
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -120,7 +134,72 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+
+template <typename Protocol, typename Handler>
+class reactive_socket_move_accept_op :
+ private Protocol::socket,
+ public reactive_socket_accept_op_base<typename Protocol::socket, Protocol>
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op);
+
+ reactive_socket_move_accept_op(io_context& ioc, socket_type socket,
+ socket_ops::state_type state, const Protocol& protocol,
+ typename Protocol::endpoint* peer_endpoint, Handler& handler)
+ : Protocol::socket(ioc),
+ reactive_socket_accept_op_base<typename Protocol::socket, Protocol>(
+ socket, state, *this, protocol, peer_endpoint,
+ &reactive_socket_move_accept_op::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ handler_work<Handler>::start(handler_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_socket_move_accept_op* o(
+ static_cast<reactive_socket_move_accept_op*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
+
+ // On success, assign new connection to peer socket object.
+ if (owner)
+ o->do_assign();
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // 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,
+ boost::system::error_code, typename Protocol::socket>
+ handler(0, BOOST_ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_,
+ BOOST_ASIO_MOVE_CAST(typename Protocol::socket)(*o));
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
@@ -129,6 +208,8 @@ private:
Handler handler_;
};
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
} // namespace detail
} // namespace asio
} // namespace boost
diff --git a/boost/asio/detail/reactive_socket_connect_op.hpp b/boost/asio/detail/reactive_socket_connect_op.hpp
index 809d63b7ae..410da203ad 100644
--- a/boost/asio/detail/reactive_socket_connect_op.hpp
+++ b/boost/asio/detail/reactive_socket_connect_op.hpp
@@ -16,10 +16,10 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/socket_ops.hpp>
@@ -38,12 +38,17 @@ public:
{
}
- static bool do_perform(reactor_op* base)
+ static status do_perform(reactor_op* base)
{
reactive_socket_connect_op_base* o(
static_cast<reactive_socket_connect_op_base*>(base));
- return socket_ops::non_blocking_connect(o->socket_, o->ec_);
+ status result = socket_ops::non_blocking_connect(
+ o->socket_, o->ec_) ? done : not_done;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_connect", o->ec_));
+
+ return result;
}
private:
@@ -61,9 +66,10 @@ public:
&reactive_socket_connect_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
@@ -71,8 +77,9 @@ public:
reactive_socket_connect_op* o
(static_cast<reactive_socket_connect_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -90,7 +97,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/reactive_socket_recv_op.hpp b/boost/asio/detail/reactive_socket_recv_op.hpp
index 751160c48f..ea7d84a0c5 100644
--- a/boost/asio/detail/reactive_socket_recv_op.hpp
+++ b/boost/asio/detail/reactive_socket_recv_op.hpp
@@ -16,10 +16,10 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/socket_ops.hpp>
@@ -44,7 +44,7 @@ public:
{
}
- static bool do_perform(reactor_op* base)
+ static status do_perform(reactor_op* base)
{
reactive_socket_recv_op_base* o(
static_cast<reactive_socket_recv_op_base*>(base));
@@ -52,10 +52,20 @@ public:
buffer_sequence_adapter<boost::asio::mutable_buffer,
MutableBufferSequence> bufs(o->buffers_);
- return socket_ops::non_blocking_recv(o->socket_,
+ status result = socket_ops::non_blocking_recv(o->socket_,
bufs.buffers(), bufs.count(), o->flags_,
(o->state_ & socket_ops::stream_oriented) != 0,
- o->ec_, o->bytes_transferred_);
+ o->ec_, o->bytes_transferred_) ? done : not_done;
+
+ if (result == done)
+ if ((o->state_ & socket_ops::stream_oriented) != 0)
+ if (o->bytes_transferred_ == 0)
+ result = done_and_exhausted;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
}
private:
@@ -79,17 +89,19 @@ public:
buffers, flags, &reactive_socket_recv_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -107,7 +119,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/reactive_socket_recvfrom_op.hpp b/boost/asio/detail/reactive_socket_recvfrom_op.hpp
index 14829a0d75..9631465f24 100644
--- a/boost/asio/detail/reactive_socket_recvfrom_op.hpp
+++ b/boost/asio/detail/reactive_socket_recvfrom_op.hpp
@@ -16,10 +16,10 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/socket_ops.hpp>
@@ -45,7 +45,7 @@ public:
{
}
- static bool do_perform(reactor_op* base)
+ static status do_perform(reactor_op* base)
{
reactive_socket_recvfrom_op_base* o(
static_cast<reactive_socket_recvfrom_op_base*>(base));
@@ -54,14 +54,17 @@ public:
MutableBufferSequence> bufs(o->buffers_);
std::size_t addr_len = o->sender_endpoint_.capacity();
- bool result = socket_ops::non_blocking_recvfrom(o->socket_,
+ status result = socket_ops::non_blocking_recvfrom(o->socket_,
bufs.buffers(), bufs.count(), o->flags_,
o->sender_endpoint_.data(), &addr_len,
- o->ec_, o->bytes_transferred_);
+ o->ec_, o->bytes_transferred_) ? done : not_done;
if (result && !o->ec_)
o->sender_endpoint_.resize(addr_len);
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom",
+ o->ec_, o->bytes_transferred_));
+
return result;
}
@@ -88,9 +91,10 @@ public:
&reactive_socket_recvfrom_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
@@ -98,8 +102,9 @@ public:
reactive_socket_recvfrom_op* o(
static_cast<reactive_socket_recvfrom_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -117,7 +122,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/reactive_socket_recvmsg_op.hpp b/boost/asio/detail/reactive_socket_recvmsg_op.hpp
index fed5d01098..c48b1aba7e 100644
--- a/boost/asio/detail/reactive_socket_recvmsg_op.hpp
+++ b/boost/asio/detail/reactive_socket_recvmsg_op.hpp
@@ -16,10 +16,10 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/socket_base.hpp>
@@ -45,7 +45,7 @@ public:
{
}
- static bool do_perform(reactor_op* base)
+ static status do_perform(reactor_op* base)
{
reactive_socket_recvmsg_op_base* o(
static_cast<reactive_socket_recvmsg_op_base*>(base));
@@ -53,10 +53,15 @@ public:
buffer_sequence_adapter<boost::asio::mutable_buffer,
MutableBufferSequence> bufs(o->buffers_);
- return socket_ops::non_blocking_recvmsg(o->socket_,
+ status result = socket_ops::non_blocking_recvmsg(o->socket_,
bufs.buffers(), bufs.count(),
o->in_flags_, o->out_flags_,
- o->ec_, o->bytes_transferred_);
+ o->ec_, o->bytes_transferred_) ? done : not_done;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
}
private:
@@ -80,9 +85,10 @@ public:
in_flags, out_flags, &reactive_socket_recvmsg_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
@@ -90,8 +96,9 @@ public:
reactive_socket_recvmsg_op* o(
static_cast<reactive_socket_recvmsg_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -109,7 +116,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/reactive_socket_send_op.hpp b/boost/asio/detail/reactive_socket_send_op.hpp
index 776117b6f7..01bb58f9ae 100644
--- a/boost/asio/detail/reactive_socket_send_op.hpp
+++ b/boost/asio/detail/reactive_socket_send_op.hpp
@@ -16,10 +16,10 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/socket_ops.hpp>
@@ -34,16 +34,17 @@ class reactive_socket_send_op_base : public reactor_op
{
public:
reactive_socket_send_op_base(socket_type socket,
- const ConstBufferSequence& buffers,
+ socket_ops::state_type state, const ConstBufferSequence& buffers,
socket_base::message_flags flags, func_type complete_func)
: reactor_op(&reactive_socket_send_op_base::do_perform, complete_func),
socket_(socket),
+ state_(state),
buffers_(buffers),
flags_(flags)
{
}
- static bool do_perform(reactor_op* base)
+ static status do_perform(reactor_op* base)
{
reactive_socket_send_op_base* o(
static_cast<reactive_socket_send_op_base*>(base));
@@ -51,13 +52,24 @@ public:
buffer_sequence_adapter<boost::asio::const_buffer,
ConstBufferSequence> bufs(o->buffers_);
- return socket_ops::non_blocking_send(o->socket_,
+ status result = socket_ops::non_blocking_send(o->socket_,
bufs.buffers(), bufs.count(), o->flags_,
- o->ec_, o->bytes_transferred_);
+ o->ec_, o->bytes_transferred_) ? done : not_done;
+
+ if (result == done)
+ if ((o->state_ & socket_ops::stream_oriented) != 0)
+ if (o->bytes_transferred_ < bufs.total_size())
+ result = done_and_exhausted;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_send",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
}
private:
socket_type socket_;
+ socket_ops::state_type state_;
ConstBufferSequence buffers_;
socket_base::message_flags flags_;
};
@@ -70,23 +82,25 @@ public:
BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_socket_send_op);
reactive_socket_send_op(socket_type socket,
- const ConstBufferSequence& buffers,
+ socket_ops::state_type state, const ConstBufferSequence& buffers,
socket_base::message_flags flags, Handler& handler)
: reactive_socket_send_op_base<ConstBufferSequence>(socket,
- buffers, flags, &reactive_socket_send_op::do_complete),
+ state, buffers, flags, &reactive_socket_send_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -104,7 +118,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/reactive_socket_sendto_op.hpp b/boost/asio/detail/reactive_socket_sendto_op.hpp
index 134c767c86..47a2656e22 100644
--- a/boost/asio/detail/reactive_socket_sendto_op.hpp
+++ b/boost/asio/detail/reactive_socket_sendto_op.hpp
@@ -16,10 +16,10 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/socket_ops.hpp>
@@ -44,7 +44,7 @@ public:
{
}
- static bool do_perform(reactor_op* base)
+ static status do_perform(reactor_op* base)
{
reactive_socket_sendto_op_base* o(
static_cast<reactive_socket_sendto_op_base*>(base));
@@ -52,10 +52,15 @@ public:
buffer_sequence_adapter<boost::asio::const_buffer,
ConstBufferSequence> bufs(o->buffers_);
- return socket_ops::non_blocking_sendto(o->socket_,
+ status result = socket_ops::non_blocking_sendto(o->socket_,
bufs.buffers(), bufs.count(), o->flags_,
o->destination_.data(), o->destination_.size(),
- o->ec_, o->bytes_transferred_);
+ o->ec_, o->bytes_transferred_) ? done : not_done;
+
+ BOOST_ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_sendto",
+ o->ec_, o->bytes_transferred_));
+
+ return result;
}
private:
@@ -79,17 +84,19 @@ public:
buffers, endpoint, flags, &reactive_socket_sendto_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -107,7 +114,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/reactive_socket_service.hpp b/boost/asio/detail/reactive_socket_service.hpp
index d5a6e08eab..186cf35336 100644
--- a/boost/asio/detail/reactive_socket_service.hpp
+++ b/boost/asio/detail/reactive_socket_service.hpp
@@ -21,10 +21,10 @@
#include <boost/asio/buffer.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/socket_base.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/reactive_null_buffers_op.hpp>
#include <boost/asio/detail/reactive_socket_accept_op.hpp>
@@ -46,6 +46,7 @@ namespace detail {
template <typename Protocol>
class reactive_socket_service :
+ public service_base<reactive_socket_service<Protocol> >,
public reactive_socket_service_base
{
public:
@@ -73,11 +74,18 @@ public:
};
// Constructor.
- reactive_socket_service(boost::asio::io_service& io_service)
- : reactive_socket_service_base(io_service)
+ reactive_socket_service(boost::asio::io_context& io_context)
+ : service_base<reactive_socket_service<Protocol> >(io_context),
+ reactive_socket_service_base(io_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)
@@ -196,6 +204,14 @@ public:
return endpoint;
}
+ // Disable sends or receives on the socket.
+ boost::system::error_code shutdown(base_implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
// Send a datagram to the specified endpoint. Returns the number of bytes
// sent.
template <typename ConstBufferSequence>
@@ -217,7 +233,7 @@ public:
boost::system::error_code& ec)
{
// Wait for socket to become ready.
- socket_ops::poll_write(impl.socket_, impl.state_, ec);
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
return 0;
}
@@ -237,11 +253,11 @@ public:
typedef reactive_socket_sendto_op<ConstBufferSequence,
endpoint_type, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.socket_, buffers, destination, flags, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to"));
+ BOOST_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);
p.v = p.p = 0;
@@ -258,12 +274,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_send_to(null_buffers)"));
+ BOOST_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);
p.v = p.p = 0;
@@ -297,7 +312,7 @@ public:
boost::system::error_code& ec)
{
// Wait for socket to become ready.
- socket_ops::poll_read(impl.socket_, impl.state_, ec);
+ 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();
@@ -320,14 +335,13 @@ public:
typedef reactive_socket_recvfrom_op<MutableBufferSequence,
endpoint_type, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
int protocol = impl.protocol_.type();
p.p = new (p.v) op(impl.socket_, protocol,
buffers, sender_endpoint, flags, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_receive_from"));
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_from"));
start_op(impl,
(flags & socket_base::message_out_of_band)
@@ -348,12 +362,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_receive_from(null_buffers)"));
+ BOOST_ASIO_HANDLER_CREATION((reactor_.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();
@@ -387,15 +400,44 @@ public:
{
if (peer_endpoint)
peer_endpoint->resize(addr_len);
- if (!peer.assign(impl.protocol_, new_socket.get(), ec))
+ peer.assign(impl.protocol_, new_socket.get(), ec);
+ if (!ec)
new_socket.release();
}
return ec;
}
- // Start an asynchronous accept. The peer and peer_endpoint objects
- // must be valid until the accept's handler is invoked.
+#if defined(BOOST_ASIO_HAS_MOVE)
+ // Accept a new connection.
+ typename Protocol::socket accept(implementation_type& impl,
+ io_context* peer_io_context, endpoint_type* peer_endpoint,
+ boost::system::error_code& ec)
+ {
+ typename Protocol::socket peer(
+ peer_io_context ? *peer_io_context : io_context_);
+
+ 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();
+ }
+
+ return peer;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ // 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>
void async_accept(implementation_type& impl, Socket& peer,
endpoint_type* peer_endpoint, Handler& handler)
@@ -406,17 +448,43 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_socket_accept_op<Socket, Protocol, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.socket_, impl.state_, peer,
impl.protocol_, peer_endpoint, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
+ BOOST_ASIO_HANDLER_CREATION((reactor_.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(BOOST_ASIO_HAS_MOVE)
+ // Start an asynchronous accept. The peer_endpoint object must be valid until
+ // the accept's handler is invoked.
+ template <typename Handler>
+ void async_accept(implementation_type& impl,
+ boost::asio::io_context* peer_io_context,
+ endpoint_type* peer_endpoint, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_socket_move_accept_op<Protocol, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(peer_io_context ? *peer_io_context : io_context_,
+ impl.socket_, impl.state_, impl.protocol_, peer_endpoint, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.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(BOOST_ASIO_HAS_MOVE)
+
// Connect the socket to the specified endpoint.
boost::system::error_code connect(implementation_type& impl,
const endpoint_type& peer_endpoint, boost::system::error_code& ec)
@@ -437,11 +505,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_socket_connect_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.socket_, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
+ BOOST_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());
diff --git a/boost/asio/detail/reactive_socket_service_base.hpp b/boost/asio/detail/reactive_socket_service_base.hpp
index fb2aa5d028..17c694a3cd 100644
--- a/boost/asio/detail/reactive_socket_service_base.hpp
+++ b/boost/asio/detail/reactive_socket_service_base.hpp
@@ -22,14 +22,15 @@
#include <boost/asio/buffer.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/socket_base.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactive_null_buffers_op.hpp>
#include <boost/asio/detail/reactive_socket_recv_op.hpp>
#include <boost/asio/detail/reactive_socket_recvmsg_op.hpp>
#include <boost/asio/detail/reactive_socket_send_op.hpp>
+#include <boost/asio/detail/reactive_wait_op.hpp>
#include <boost/asio/detail/reactor.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/socket_holder.hpp>
@@ -63,10 +64,10 @@ public:
// Constructor.
BOOST_ASIO_DECL reactive_socket_service_base(
- boost::asio::io_service& io_service);
+ boost::asio::io_context& io_context);
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void base_shutdown();
// Construct a new socket implementation.
BOOST_ASIO_DECL void construct(base_implementation_type& impl);
@@ -93,6 +94,10 @@ public:
BOOST_ASIO_DECL boost::system::error_code close(
base_implementation_type& impl, boost::system::error_code& ec);
+ // Release ownership of the socket.
+ BOOST_ASIO_DECL socket_type release(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
// Get the native socket representation.
native_handle_type native_handle(base_implementation_type& impl)
{
@@ -163,14 +168,71 @@ public:
return ec;
}
- // Disable sends or receives on the socket.
- boost::system::error_code shutdown(base_implementation_type& impl,
- socket_base::shutdown_type what, boost::system::error_code& ec)
+ // Wait for the socket to become ready to read, ready to write, or to have
+ // pending error conditions.
+ boost::system::error_code wait(base_implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
{
- socket_ops::shutdown(impl.socket_, what, 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 = boost::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>
+ void async_wait(base_implementation_type& impl,
+ socket_base::wait_type w, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef reactive_wait_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(handler);
+
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_wait"));
+
+ 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_ = boost::asio::error::invalid_argument;
+ reactor_.post_immediate_completion(p.p, is_continuation);
+ p.v = p.p = 0;
+ return;
+ }
+
+ start_op(impl, op_type, p.p, is_continuation, false, false);
+ p.v = p.p = 0;
+ }
+
// Send the given data to the peer.
template <typename ConstBufferSequence>
size_t send(base_implementation_type& impl,
@@ -189,7 +251,7 @@ public:
socket_base::message_flags, boost::system::error_code& ec)
{
// Wait for socket to become ready.
- socket_ops::poll_write(impl.socket_, impl.state_, ec);
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
return 0;
}
@@ -207,11 +269,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_socket_send_op<ConstBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(impl.socket_, buffers, flags, handler);
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
+ BOOST_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)
@@ -231,12 +293,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_send(null_buffers)"));
+ BOOST_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);
p.v = p.p = 0;
@@ -260,7 +321,7 @@ public:
socket_base::message_flags, boost::system::error_code& ec)
{
// Wait for socket to become ready.
- socket_ops::poll_read(impl.socket_, impl.state_, ec);
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
return 0;
}
@@ -278,11 +339,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_socket_recv_op<MutableBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.socket_, impl.state_, buffers, flags, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive"));
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive"));
start_op(impl,
(flags & socket_base::message_out_of_band)
@@ -306,12 +367,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_receive(null_buffers)"));
+ BOOST_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)
@@ -341,7 +401,7 @@ public:
socket_base::message_flags& out_flags, boost::system::error_code& ec)
{
// Wait for socket to become ready.
- socket_ops::poll_read(impl.socket_, impl.state_, ec);
+ 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.
@@ -363,12 +423,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_socket_recvmsg_op<MutableBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.socket_, buffers, in_flags, out_flags, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_receive_with_flags"));
+ BOOST_ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",
+ &impl, impl.socket_, "async_receive_with_flags"));
start_op(impl,
(in_flags & socket_base::message_out_of_band)
@@ -390,12 +449,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef reactive_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl,
- "async_receive_with_flags(null_buffers)"));
+ BOOST_ASIO_HANDLER_CREATION((reactor_.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.
@@ -432,6 +490,9 @@ protected:
reactor_op* op, bool is_continuation,
const socket_addr_type* addr, size_t addrlen);
+ // The io_context that owns this socket service.
+ io_context& io_context_;
+
// The selector that performs event demultiplexing for the service.
reactor& reactor_;
};
diff --git a/boost/asio/detail/reactive_wait_op.hpp b/boost/asio/detail/reactive_wait_op.hpp
new file mode 100644
index 0000000000..9bc4e2c1c5
--- /dev/null
+++ b/boost/asio/detail/reactive_wait_op.hpp
@@ -0,0 +1,92 @@
+//
+// detail/reactive_wait_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_REACTIVE_WAIT_OP_HPP
+#define BOOST_ASIO_DETAIL_REACTIVE_WAIT_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class reactive_wait_op : public reactor_op
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(reactive_wait_op);
+
+ reactive_wait_op(Handler& handler)
+ : reactor_op(&reactive_wait_op::do_perform,
+ &reactive_wait_op::do_complete),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ handler_work<Handler>::start(handler_);
+ }
+
+ static status do_perform(reactor_op*)
+ {
+ return done;
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the handler object.
+ reactive_wait_op* o(static_cast<reactive_wait_op*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // 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, boost::system::error_code>
+ handler(o->handler_, o->ec_);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_REACTIVE_WAIT_OP_HPP
diff --git a/boost/asio/detail/reactor.hpp b/boost/asio/detail/reactor.hpp
index 1a4ace8776..e65df12863 100644
--- a/boost/asio/detail/reactor.hpp
+++ b/boost/asio/detail/reactor.hpp
@@ -23,7 +23,7 @@
# include <boost/asio/detail/kqueue_reactor.hpp>
#elif defined(BOOST_ASIO_HAS_DEV_POLL)
# include <boost/asio/detail/dev_poll_reactor.hpp>
-#elif defined(BOOST_ASIO_WINDOWS_RUNTIME)
+#elif defined(BOOST_ASIO_HAS_IOCP) || defined(BOOST_ASIO_WINDOWS_RUNTIME)
# include <boost/asio/detail/null_reactor.hpp>
#else
# include <boost/asio/detail/select_reactor.hpp>
diff --git a/boost/asio/detail/reactor_fwd.hpp b/boost/asio/detail/reactor_fwd.hpp
index 6b2e49f5a4..d14ed4cf9c 100644
--- a/boost/asio/detail/reactor_fwd.hpp
+++ b/boost/asio/detail/reactor_fwd.hpp
@@ -21,7 +21,7 @@ namespace boost {
namespace asio {
namespace detail {
-#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+#if defined(BOOST_ASIO_HAS_IOCP) || defined(BOOST_ASIO_WINDOWS_RUNTIME)
typedef class null_reactor reactor;
#elif defined(BOOST_ASIO_HAS_IOCP)
typedef class select_reactor reactor;
diff --git a/boost/asio/detail/reactor_op.hpp b/boost/asio/detail/reactor_op.hpp
index c5964dea37..c2540545d5 100644
--- a/boost/asio/detail/reactor_op.hpp
+++ b/boost/asio/detail/reactor_op.hpp
@@ -34,14 +34,18 @@ public:
// The number of bytes transferred, to be passed to the completion handler.
std::size_t bytes_transferred_;
+ // Status returned by perform function. May be used to decide whether it is
+ // worth performing more operations on the descriptor immediately.
+ enum status { not_done, done, done_and_exhausted };
+
// Perform the operation. Returns true if it is finished.
- bool perform()
+ status perform()
{
return perform_func_(this);
}
protected:
- typedef bool (*perform_func_type)(reactor_op*);
+ typedef status (*perform_func_type)(reactor_op*);
reactor_op(perform_func_type perform_func, func_type complete_func)
: operation(complete_func),
diff --git a/boost/asio/detail/recycling_allocator.hpp b/boost/asio/detail/recycling_allocator.hpp
new file mode 100644
index 0000000000..050e8bdfa0
--- /dev/null
+++ b/boost/asio/detail/recycling_allocator.hpp
@@ -0,0 +1,106 @@
+//
+// detail/recycling_allocator.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_RECYCLING_ALLOCATOR_HPP
+#define BOOST_ASIO_DETAIL_RECYCLING_ALLOCATOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/thread_context.hpp>
+#include <boost/asio/detail/thread_info_base.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+class recycling_allocator
+{
+public:
+ typedef T value_type;
+
+ template <typename U>
+ struct rebind
+ {
+ typedef recycling_allocator<U> other;
+ };
+
+ recycling_allocator()
+ {
+ }
+
+ template <typename U>
+ recycling_allocator(const recycling_allocator<U>&)
+ {
+ }
+
+ T* allocate(std::size_t n)
+ {
+ typedef thread_context::thread_call_stack call_stack;
+ void* p = thread_info_base::allocate(call_stack::top(), sizeof(T) * n);
+ 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(call_stack::top(), p, sizeof(T) * n);
+ }
+};
+
+template <>
+class recycling_allocator<void>
+{
+public:
+ typedef void value_type;
+
+ template <typename U>
+ struct rebind
+ {
+ typedef recycling_allocator<U> other;
+ };
+
+ recycling_allocator()
+ {
+ }
+
+ template <typename U>
+ recycling_allocator(const recycling_allocator<U>&)
+ {
+ }
+};
+
+template <typename Allocator>
+struct get_recycling_allocator
+{
+ typedef Allocator type;
+ static type get(const Allocator& a) { return a; }
+};
+
+template <typename T>
+struct get_recycling_allocator<std::allocator<T> >
+{
+ typedef recycling_allocator<T> type;
+ static type get(const std::allocator<T>&) { return type(); }
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_RECYCLING_ALLOCATOR_HPP
diff --git a/boost/asio/detail/resolve_endpoint_op.hpp b/boost/asio/detail/resolve_endpoint_op.hpp
index 0b7060ad6b..4a2c06798a 100644
--- a/boost/asio/detail/resolve_endpoint_op.hpp
+++ b/boost/asio/detail/resolve_endpoint_op.hpp
@@ -17,14 +17,14 @@
#include <boost/asio/detail/config.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/ip/basic_resolver_iterator.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/basic_resolver_results.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
-#include <boost/asio/detail/operation.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/resolve_op.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -34,35 +34,37 @@ namespace asio {
namespace detail {
template <typename Protocol, typename Handler>
-class resolve_endpoint_op : public operation
+class resolve_endpoint_op : public resolve_op
{
public:
BOOST_ASIO_DEFINE_HANDLER_PTR(resolve_endpoint_op);
typedef typename Protocol::endpoint endpoint_type;
- typedef boost::asio::ip::basic_resolver_iterator<Protocol> iterator_type;
+ typedef boost::asio::ip::basic_resolver_results<Protocol> results_type;
resolve_endpoint_op(socket_ops::weak_cancel_token_type cancel_token,
- const endpoint_type& endpoint, io_service_impl& ios, Handler& handler)
- : operation(&resolve_endpoint_op::do_complete),
+ const endpoint_type& endpoint, io_context_impl& ioc, Handler& handler)
+ : resolve_op(&resolve_endpoint_op::do_complete),
cancel_token_(cancel_token),
endpoint_(endpoint),
- io_service_impl_(ios),
+ io_context_impl_(ioc),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
// Take ownership of the operation object.
resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- if (owner && owner != &o->io_service_impl_)
+ if (owner && owner != &o->io_context_impl_)
{
- // The operation is being run on the worker io_service. Time to perform
+ // The operation is being run on the worker io_context. Time to perform
// the resolver operation.
// Perform the blocking endpoint resolution operation.
@@ -71,18 +73,18 @@ public:
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_);
- o->iter_ = iterator_type::create(o->endpoint_, host_name, service_name);
+ o->results_ = results_type::create(o->endpoint_, host_name, service_name);
- // Pass operation back to main io_service for completion.
- o->io_service_impl_.post_deferred_completion(o);
+ // Pass operation back to main io_context for completion.
+ o->io_context_impl_.post_deferred_completion(o);
p.v = p.p = 0;
}
else
{
- // The operation has been returned to the main io_service. The completion
+ // The operation has been returned to the main io_context. The completion
// handler is ready to be delivered.
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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,
@@ -90,8 +92,8 @@ public:
// 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, boost::system::error_code, iterator_type>
- handler(o->handler_, o->ec_, o->iter_);
+ detail::binder2<Handler, boost::system::error_code, results_type>
+ handler(o->handler_, o->ec_, o->results_);
p.h = boost::asio::detail::addressof(handler.handler_);
p.reset();
@@ -99,7 +101,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
@@ -108,10 +110,9 @@ public:
private:
socket_ops::weak_cancel_token_type cancel_token_;
endpoint_type endpoint_;
- io_service_impl& io_service_impl_;
+ io_context_impl& io_context_impl_;
Handler handler_;
- boost::system::error_code ec_;
- iterator_type iter_;
+ results_type results_;
};
} // namespace detail
diff --git a/boost/asio/detail/resolve_op.hpp b/boost/asio/detail/resolve_op.hpp
index 435e27026f..99f9772f97 100644
--- a/boost/asio/detail/resolve_op.hpp
+++ b/boost/asio/detail/resolve_op.hpp
@@ -17,16 +17,7 @@
#include <boost/asio/detail/config.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/ip/basic_resolver_iterator.hpp>
-#include <boost/asio/ip/basic_resolver_query.hpp>
-#include <boost/asio/detail/addressof.hpp>
-#include <boost/asio/detail/bind_handler.hpp>
-#include <boost/asio/detail/fenced_block.hpp>
-#include <boost/asio/detail/handler_alloc_helpers.hpp>
-#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/operation.hpp>
-#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -34,94 +25,17 @@ namespace boost {
namespace asio {
namespace detail {
-template <typename Protocol, typename Handler>
class resolve_op : public operation
{
public:
- BOOST_ASIO_DEFINE_HANDLER_PTR(resolve_op);
-
- typedef boost::asio::ip::basic_resolver_query<Protocol> query_type;
- typedef boost::asio::ip::basic_resolver_iterator<Protocol> iterator_type;
-
- resolve_op(socket_ops::weak_cancel_token_type cancel_token,
- const query_type& query, io_service_impl& ios, Handler& handler)
- : operation(&resolve_op::do_complete),
- cancel_token_(cancel_token),
- query_(query),
- io_service_impl_(ios),
- handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
- addrinfo_(0)
- {
- }
+ // The error code to be passed to the completion handler.
+ boost::system::error_code ec_;
- ~resolve_op()
+protected:
+ resolve_op(func_type complete_func)
+ : operation(complete_func)
{
- if (addrinfo_)
- socket_ops::freeaddrinfo(addrinfo_);
}
-
- static void do_complete(io_service_impl* owner, operation* base,
- const boost::system::error_code& /*ec*/,
- std::size_t /*bytes_transferred*/)
- {
- // Take ownership of the operation object.
- resolve_op* o(static_cast<resolve_op*>(base));
- ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
-
- if (owner && owner != &o->io_service_impl_)
- {
- // The operation is being run on the worker io_service. Time to perform
- // the resolver operation.
-
- // Perform the blocking host resolution operation.
- socket_ops::background_getaddrinfo(o->cancel_token_,
- o->query_.host_name().c_str(), o->query_.service_name().c_str(),
- o->query_.hints(), &o->addrinfo_, o->ec_);
-
- // Pass operation back to main io_service for completion.
- o->io_service_impl_.post_deferred_completion(o);
- p.v = p.p = 0;
- }
- else
- {
- // The operation has been returned to the main io_service. The completion
- // handler is ready to be delivered.
-
- BOOST_ASIO_HANDLER_COMPLETION((o));
-
- // 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, boost::system::error_code, iterator_type>
- handler(o->handler_, o->ec_, iterator_type());
- p.h = boost::asio::detail::addressof(handler.handler_);
- if (o->addrinfo_)
- {
- handler.arg2_ = iterator_type::create(o->addrinfo_,
- o->query_.host_name(), o->query_.service_name());
- }
- p.reset();
-
- if (owner)
- {
- fenced_block b(fenced_block::half);
- BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
- BOOST_ASIO_HANDLER_INVOCATION_END;
- }
- }
- }
-
-private:
- socket_ops::weak_cancel_token_type cancel_token_;
- query_type query_;
- io_service_impl& io_service_impl_;
- Handler handler_;
- boost::system::error_code ec_;
- boost::asio::detail::addrinfo_type* addrinfo_;
};
} // namespace detail
diff --git a/boost/asio/detail/resolve_query_op.hpp b/boost/asio/detail/resolve_query_op.hpp
new file mode 100644
index 0000000000..6e5c431941
--- /dev/null
+++ b/boost/asio/detail/resolve_query_op.hpp
@@ -0,0 +1,136 @@
+//
+// detail/resolve_query_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_RESOLVE_QUERY_OP_HPP
+#define BOOST_ASIO_DETAIL_RESOLVE_QUERY_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ip/basic_resolver_query.hpp>
+#include <boost/asio/ip/basic_resolver_results.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/resolve_op.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Protocol, typename Handler>
+class resolve_query_op : public resolve_op
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(resolve_query_op);
+
+ typedef boost::asio::ip::basic_resolver_query<Protocol> query_type;
+ typedef boost::asio::ip::basic_resolver_results<Protocol> results_type;
+
+ resolve_query_op(socket_ops::weak_cancel_token_type cancel_token,
+ const query_type& query, io_context_impl& ioc, Handler& handler)
+ : resolve_op(&resolve_query_op::do_complete),
+ cancel_token_(cancel_token),
+ query_(query),
+ io_context_impl_(ioc),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler)),
+ addrinfo_(0)
+ {
+ handler_work<Handler>::start(handler_);
+ }
+
+ ~resolve_query_op()
+ {
+ if (addrinfo_)
+ socket_ops::freeaddrinfo(addrinfo_);
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& /*ec*/,
+ std::size_t /*bytes_transferred*/)
+ {
+ // Take ownership of the operation object.
+ resolve_query_op* o(static_cast<resolve_query_op*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+
+ if (owner && owner != &o->io_context_impl_)
+ {
+ // The operation is being run on the worker io_context. Time to perform
+ // the resolver operation.
+
+ // Perform the blocking host resolution operation.
+ socket_ops::background_getaddrinfo(o->cancel_token_,
+ o->query_.host_name().c_str(), o->query_.service_name().c_str(),
+ o->query_.hints(), &o->addrinfo_, o->ec_);
+
+ // Pass operation back to main io_context for completion.
+ o->io_context_impl_.post_deferred_completion(o);
+ p.v = p.p = 0;
+ }
+ else
+ {
+ // The operation has been returned to the main io_context. The completion
+ // handler is ready to be delivered.
+
+ // Take ownership of the operation's outstanding work.
+ handler_work<Handler> w(o->handler_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // 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, boost::system::error_code, results_type>
+ handler(o->handler_, o->ec_, results_type());
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ if (o->addrinfo_)
+ {
+ handler.arg2_ = results_type::create(o->addrinfo_,
+ o->query_.host_name(), o->query_.service_name());
+ }
+ p.reset();
+
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+ }
+
+private:
+ socket_ops::weak_cancel_token_type cancel_token_;
+ query_type query_;
+ io_context_impl& io_context_impl_;
+ Handler handler_;
+ boost::asio::detail::addrinfo_type* addrinfo_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_RESOLVE_QUERY_OP_HPP
diff --git a/boost/asio/detail/resolver_service.hpp b/boost/asio/detail/resolver_service.hpp
index f73742e9b0..bda1139eb7 100644
--- a/boost/asio/detail/resolver_service.hpp
+++ b/boost/asio/detail/resolver_service.hpp
@@ -19,11 +19,12 @@
#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
-#include <boost/asio/ip/basic_resolver_iterator.hpp>
#include <boost/asio/ip/basic_resolver_query.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/ip/basic_resolver_results.hpp>
+#include <boost/asio/detail/concurrency_hint.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/resolve_endpoint_op.hpp>
-#include <boost/asio/detail/resolve_op.hpp>
+#include <boost/asio/detail/resolve_query_op.hpp>
#include <boost/asio/detail/resolver_service_base.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -33,7 +34,9 @@ namespace asio {
namespace detail {
template <typename Protocol>
-class resolver_service : public resolver_service_base
+class resolver_service :
+ public service_base<resolver_service<Protocol> >,
+ public resolver_service_base
{
public:
// The implementation type of the resolver. A cancellation token is used to
@@ -46,17 +49,30 @@ public:
// The query type.
typedef boost::asio::ip::basic_resolver_query<Protocol> query_type;
- // The iterator type.
- typedef boost::asio::ip::basic_resolver_iterator<Protocol> iterator_type;
+ // The results type.
+ typedef boost::asio::ip::basic_resolver_results<Protocol> results_type;
// Constructor.
- resolver_service(boost::asio::io_service& io_service)
- : resolver_service_base(io_service)
+ resolver_service(boost::asio::io_context& io_context)
+ : service_base<resolver_service<Protocol> >(io_context),
+ resolver_service_base(io_context)
{
}
+ // Destroy all user-defined handler objects owned by the service.
+ void shutdown()
+ {
+ this->base_shutdown();
+ }
+
+ // Perform any fork-related housekeeping.
+ void notify_fork(boost::asio::io_context::fork_event fork_ev)
+ {
+ this->base_notify_fork(fork_ev);
+ }
+
// Resolve a query to a list of entries.
- iterator_type resolve(implementation_type&, const query_type& query,
+ results_type resolve(implementation_type&, const query_type& query,
boost::system::error_code& ec)
{
boost::asio::detail::addrinfo_type* address_info = 0;
@@ -65,7 +81,7 @@ public:
query.service_name().c_str(), query.hints(), &address_info, ec);
auto_addrinfo auto_address_info(address_info);
- return ec ? iterator_type() : iterator_type::create(
+ return ec ? results_type() : results_type::create(
address_info, query.host_name(), query.service_name());
}
@@ -75,20 +91,20 @@ public:
const query_type& query, Handler& handler)
{
// Allocate and construct an operation to wrap the handler.
- typedef resolve_op<Protocol, Handler> op;
+ typedef resolve_query_op<Protocol, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(impl, query, io_service_impl_, handler);
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl, query, io_context_impl_, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "resolver", &impl, "async_resolve"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_impl_.context(),
+ *p.p, "resolver", &impl, 0, "async_resolve"));
start_resolve_op(p.p);
p.v = p.p = 0;
}
// Resolve an endpoint to a list of entries.
- iterator_type resolve(implementation_type&,
+ results_type resolve(implementation_type&,
const endpoint_type& endpoint, boost::system::error_code& ec)
{
char host_name[NI_MAXHOST];
@@ -97,7 +113,7 @@ public:
host_name, NI_MAXHOST, service_name, NI_MAXSERV,
endpoint.protocol().type(), ec);
- return ec ? iterator_type() : iterator_type::create(
+ return ec ? results_type() : results_type::create(
endpoint, host_name, service_name);
}
@@ -109,11 +125,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef resolve_endpoint_op<Protocol, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
- p.p = new (p.v) op(impl, endpoint, io_service_impl_, handler);
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl, endpoint, io_context_impl_, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "resolver", &impl, "async_resolve"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_impl_.context(),
+ *p.p, "resolver", &impl, 0, "async_resolve"));
start_resolve_op(p.p);
p.v = p.p = 0;
diff --git a/boost/asio/detail/resolver_service_base.hpp b/boost/asio/detail/resolver_service_base.hpp
index 1a4180c166..818e20b02b 100644
--- a/boost/asio/detail/resolver_service_base.hpp
+++ b/boost/asio/detail/resolver_service_base.hpp
@@ -17,10 +17,11 @@
#include <boost/asio/detail/config.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/executor_work_guard.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/noncopyable.hpp>
-#include <boost/asio/detail/operation.hpp>
+#include <boost/asio/detail/resolve_op.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/scoped_ptr.hpp>
@@ -40,17 +41,17 @@ public:
typedef socket_ops::shared_cancel_token_type implementation_type;
// Constructor.
- BOOST_ASIO_DECL resolver_service_base(boost::asio::io_service& io_service);
+ BOOST_ASIO_DECL resolver_service_base(boost::asio::io_context& io_context);
// Destructor.
BOOST_ASIO_DECL ~resolver_service_base();
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void base_shutdown();
// Perform any fork-related housekeeping.
- BOOST_ASIO_DECL void fork_service(
- boost::asio::io_service::fork_event fork_ev);
+ BOOST_ASIO_DECL void base_notify_fork(
+ boost::asio::io_context::fork_event fork_ev);
// Construct a new resolver implementation.
BOOST_ASIO_DECL void construct(implementation_type& impl);
@@ -58,12 +59,21 @@ public:
// Destroy a resolver implementation.
BOOST_ASIO_DECL void destroy(implementation_type&);
+ // Move-construct a new resolver implementation.
+ BOOST_ASIO_DECL void move_construct(implementation_type& impl,
+ implementation_type& other_impl);
+
+ // Move-assign from another resolver implementation.
+ BOOST_ASIO_DECL void move_assign(implementation_type& impl,
+ resolver_service_base& other_service,
+ implementation_type& other_impl);
+
// Cancel pending asynchronous operations.
BOOST_ASIO_DECL void cancel(implementation_type& impl);
protected:
// Helper function to start an asynchronous resolve operation.
- BOOST_ASIO_DECL void start_resolve_op(operation* op);
+ BOOST_ASIO_DECL void start_resolve_op(resolve_op* op);
#if !defined(BOOST_ASIO_WINDOWS_RUNTIME)
// Helper class to perform exception-safe cleanup of addrinfo objects.
@@ -92,29 +102,30 @@ protected:
};
#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
- // Helper class to run the work io_service in a thread.
- class work_io_service_runner;
+ // Helper class to run the work io_context in a thread.
+ class work_io_context_runner;
// Start the work thread if it's not already running.
BOOST_ASIO_DECL void start_work_thread();
- // The io_service implementation used to post completions.
- io_service_impl& io_service_impl_;
+ // The io_context implementation used to post completions.
+ io_context_impl& io_context_impl_;
private:
// Mutex to protect access to internal data.
boost::asio::detail::mutex mutex_;
- // Private io_service used for performing asynchronous host resolution.
- boost::asio::detail::scoped_ptr<boost::asio::io_service> work_io_service_;
+ // Private io_context used for performing asynchronous host resolution.
+ boost::asio::detail::scoped_ptr<boost::asio::io_context> work_io_context_;
- // The work io_service implementation used to post completions.
- io_service_impl& work_io_service_impl_;
+ // The work io_context implementation used to post completions.
+ io_context_impl& work_io_context_impl_;
- // Work for the private io_service to perform.
- boost::asio::detail::scoped_ptr<boost::asio::io_service::work> work_;
+ // Work for the private io_context to perform.
+ boost::asio::executor_work_guard<
+ boost::asio::io_context::executor_type> work_;
- // Thread used for running the work io_service's run loop.
+ // Thread used for running the work io_context's run loop.
boost::asio::detail::scoped_ptr<boost::asio::detail::thread> work_thread_;
};
diff --git a/boost/asio/detail/task_io_service.hpp b/boost/asio/detail/scheduler.hpp
index 5184ea5a58..1d64a062c8 100644
--- a/boost/asio/detail/task_io_service.hpp
+++ b/boost/asio/detail/scheduler.hpp
@@ -1,6 +1,6 @@
//
-// detail/task_io_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/scheduler.hpp
+// ~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
@@ -8,8 +8,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP
-#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP
+#ifndef BOOST_ASIO_DETAIL_SCHEDULER_HPP
+#define BOOST_ASIO_DETAIL_SCHEDULER_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
@@ -17,17 +17,15 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_HAS_IOCP)
-
#include <boost/system/error_code.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/execution_context.hpp>
#include <boost/asio/detail/atomic_count.hpp>
-#include <boost/asio/detail/call_stack.hpp>
-#include <boost/asio/detail/event.hpp>
-#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/conditionally_enabled_event.hpp>
+#include <boost/asio/detail/conditionally_enabled_mutex.hpp>
#include <boost/asio/detail/op_queue.hpp>
#include <boost/asio/detail/reactor_fwd.hpp>
-#include <boost/asio/detail/task_io_service_operation.hpp>
+#include <boost/asio/detail/scheduler_operation.hpp>
+#include <boost/asio/detail/thread_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -35,21 +33,22 @@ namespace boost {
namespace asio {
namespace detail {
-struct task_io_service_thread_info;
+struct scheduler_thread_info;
-class task_io_service
- : public boost::asio::detail::service_base<task_io_service>
+class scheduler
+ : public execution_context_service_base<scheduler>,
+ public thread_context
{
public:
- typedef task_io_service_operation operation;
+ typedef scheduler_operation operation;
// Constructor. Specifies the number of concurrent threads that are likely to
- // run the io_service. If set to 1 certain optimisation are performed.
- BOOST_ASIO_DECL task_io_service(boost::asio::io_service& io_service,
- std::size_t concurrency_hint = 0);
+ // run the scheduler. If set to 1 certain optimisation are performed.
+ BOOST_ASIO_DECL scheduler(boost::asio::execution_context& ctx,
+ int concurrency_hint = 0);
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Initialise the task, if required.
BOOST_ASIO_DECL void init_task();
@@ -60,6 +59,10 @@ public:
// Run until interrupted or one operation is performed.
BOOST_ASIO_DECL std::size_t run_one(boost::system::error_code& ec);
+ // Run until timeout, interrupted, or one operation is performed.
+ BOOST_ASIO_DECL std::size_t wait_one(
+ long usec, boost::system::error_code& ec);
+
// Poll for operations without blocking.
BOOST_ASIO_DECL std::size_t poll(boost::system::error_code& ec);
@@ -69,11 +72,11 @@ public:
// Interrupt the event processing loop.
BOOST_ASIO_DECL void stop();
- // Determine whether the io_service is stopped.
+ // Determine whether the scheduler is stopped.
BOOST_ASIO_DECL bool stopped() const;
- // Reset in preparation for a subsequent run invocation.
- BOOST_ASIO_DECL void reset();
+ // Restart in preparation for a subsequent run invocation.
+ BOOST_ASIO_DECL void restart();
// Notify that some work has started.
void work_started()
@@ -81,6 +84,10 @@ public:
++outstanding_work_;
}
+ // Used to compensate for a forthcoming work_finished call. Must be called
+ // from within a scheduler-owned thread.
+ BOOST_ASIO_DECL void compensating_work_started();
+
// Notify that some work has finished.
void work_finished()
{
@@ -94,14 +101,6 @@ public:
return thread_call_stack::contains(this) != 0;
}
- // Request invocation of the given handler.
- template <typename Handler>
- void dispatch(Handler& handler);
-
- // Request invocation of the given handler and return immediately.
- template <typename Handler>
- void post(Handler& handler);
-
// Request invocation of the given operation and return immediately. Assumes
// that work_started() has not yet been called for the operation.
BOOST_ASIO_DECL void post_immediate_completion(
@@ -115,22 +114,38 @@ public:
// that work_started() was previously called for each operation.
BOOST_ASIO_DECL void post_deferred_completions(op_queue<operation>& ops);
- // Process unfinished operations as part of a shutdown_service operation.
- // Assumes that work_started() was previously called for the operations.
+ // Enqueue the given operation following a failed attempt to dispatch the
+ // operation for immediate invocation.
+ BOOST_ASIO_DECL void do_dispatch(operation* op);
+
+ // Process unfinished operations as part of a shutdownoperation. Assumes that
+ // work_started() was previously called for the operations.
BOOST_ASIO_DECL void abandon_operations(op_queue<operation>& ops);
+ // Get the concurrency hint that was used to initialise the scheduler.
+ int concurrency_hint() const
+ {
+ return concurrency_hint_;
+ }
+
private:
- // Structure containing thread-specific data.
- typedef task_io_service_thread_info thread_info;
+ // The mutex type used by this scheduler.
+ typedef conditionally_enabled_mutex mutex;
- // Enqueue the given operation following a failed attempt to dispatch the
- // operation for immediate invocation.
- BOOST_ASIO_DECL void do_dispatch(operation* op);
+ // The event type used by this scheduler.
+ typedef conditionally_enabled_event event;
+
+ // Structure containing thread-specific data.
+ typedef scheduler_thread_info thread_info;
// Run at most one operation. May block.
BOOST_ASIO_DECL std::size_t do_run_one(mutex::scoped_lock& lock,
thread_info& this_thread, const boost::system::error_code& ec);
+ // Run at most one operation with a timeout. May block.
+ BOOST_ASIO_DECL std::size_t do_wait_one(mutex::scoped_lock& lock,
+ thread_info& this_thread, long usec, const boost::system::error_code& ec);
+
// Poll for at most one operation.
BOOST_ASIO_DECL std::size_t do_poll_one(mutex::scoped_lock& lock,
thread_info& this_thread, const boost::system::error_code& ec);
@@ -183,8 +198,8 @@ private:
// Flag to indicate that the dispatcher has been shut down.
bool shutdown_;
- // Per-thread call stack to track the state of each thread in the io_service.
- typedef call_stack<task_io_service, thread_info> thread_call_stack;
+ // The concurrency hint used to initialise the scheduler.
+ const int concurrency_hint_;
};
} // namespace detail
@@ -193,11 +208,8 @@ private:
#include <boost/asio/detail/pop_options.hpp>
-#include <boost/asio/detail/impl/task_io_service.hpp>
#if defined(BOOST_ASIO_HEADER_ONLY)
-# include <boost/asio/detail/impl/task_io_service.ipp>
+# include <boost/asio/detail/impl/scheduler.ipp>
#endif // defined(BOOST_ASIO_HEADER_ONLY)
-#endif // !defined(BOOST_ASIO_HAS_IOCP)
-
-#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_HPP
+#endif // BOOST_ASIO_DETAIL_SCHEDULER_HPP
diff --git a/boost/asio/detail/task_io_service_operation.hpp b/boost/asio/detail/scheduler_operation.hpp
index 91bee25cb4..54a8a7a206 100644
--- a/boost/asio/detail/task_io_service_operation.hpp
+++ b/boost/asio/detail/scheduler_operation.hpp
@@ -1,6 +1,6 @@
//
-// detail/task_io_service_operation.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/scheduler_operation.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
@@ -8,8 +8,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_ASIO_DETAIL_TASK_IO_SERVICE_OPERATION_HPP
-#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_OPERATION_HPP
+#ifndef BOOST_ASIO_DETAIL_SCHEDULER_OPERATION_HPP
+#define BOOST_ASIO_DETAIL_SCHEDULER_OPERATION_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
@@ -25,17 +25,19 @@ namespace boost {
namespace asio {
namespace detail {
-class task_io_service;
+class scheduler;
// Base class for all operations. A function pointer is used instead of virtual
// functions to avoid the associated overhead.
-class task_io_service_operation BOOST_ASIO_INHERIT_TRACKED_HANDLER
+class scheduler_operation BOOST_ASIO_INHERIT_TRACKED_HANDLER
{
public:
- void complete(task_io_service& owner,
- const boost::system::error_code& ec, std::size_t bytes_transferred)
+ typedef scheduler_operation operation_type;
+
+ void complete(void* owner, const boost::system::error_code& ec,
+ std::size_t bytes_transferred)
{
- func_(&owner, this, ec, bytes_transferred);
+ func_(owner, this, ec, bytes_transferred);
}
void destroy()
@@ -44,11 +46,11 @@ public:
}
protected:
- typedef void (*func_type)(task_io_service*,
- task_io_service_operation*,
+ typedef void (*func_type)(void*,
+ scheduler_operation*,
const boost::system::error_code&, std::size_t);
- task_io_service_operation(func_type func)
+ scheduler_operation(func_type func)
: next_(0),
func_(func),
task_result_(0)
@@ -56,16 +58,16 @@ protected:
}
// Prevents deletion through this type.
- ~task_io_service_operation()
+ ~scheduler_operation()
{
}
private:
friend class op_queue_access;
- task_io_service_operation* next_;
+ scheduler_operation* next_;
func_type func_;
protected:
- friend class task_io_service;
+ friend class scheduler;
unsigned int task_result_; // Passed into bytes transferred.
};
@@ -75,4 +77,4 @@ protected:
#include <boost/asio/detail/pop_options.hpp>
-#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_OPERATION_HPP
+#endif // BOOST_ASIO_DETAIL_SCHEDULER_OPERATION_HPP
diff --git a/boost/asio/detail/task_io_service_thread_info.hpp b/boost/asio/detail/scheduler_thread_info.hpp
index 0af044c009..79d64783c2 100644
--- a/boost/asio/detail/task_io_service_thread_info.hpp
+++ b/boost/asio/detail/scheduler_thread_info.hpp
@@ -1,6 +1,6 @@
//
-// detail/task_io_service_thread_info.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// detail/scheduler_thread_info.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
@@ -8,8 +8,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_ASIO_DETAIL_TASK_IO_SERVICE_THREAD_INFO_HPP
-#define BOOST_ASIO_DETAIL_TASK_IO_SERVICE_THREAD_INFO_HPP
+#ifndef BOOST_ASIO_DETAIL_SCHEDULER_THREAD_INFO_HPP
+#define BOOST_ASIO_DETAIL_SCHEDULER_THREAD_INFO_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
@@ -24,12 +24,12 @@ namespace boost {
namespace asio {
namespace detail {
-class task_io_service;
-class task_io_service_operation;
+class scheduler;
+class scheduler_operation;
-struct task_io_service_thread_info : public thread_info_base
+struct scheduler_thread_info : public thread_info_base
{
- op_queue<task_io_service_operation> private_op_queue;
+ op_queue<scheduler_operation> private_op_queue;
long private_outstanding_work;
};
@@ -39,4 +39,4 @@ struct task_io_service_thread_info : public thread_info_base
#include <boost/asio/detail/pop_options.hpp>
-#endif // BOOST_ASIO_DETAIL_TASK_IO_SERVICE_THREAD_INFO_HPP
+#endif // BOOST_ASIO_DETAIL_SCHEDULER_THREAD_INFO_HPP
diff --git a/boost/asio/detail/scoped_ptr.hpp b/boost/asio/detail/scoped_ptr.hpp
index fd471631e1..80ced171cd 100644
--- a/boost/asio/detail/scoped_ptr.hpp
+++ b/boost/asio/detail/scoped_ptr.hpp
@@ -64,6 +64,14 @@ public:
p_ = p;
}
+ // Release ownership of the pointer.
+ T* release()
+ {
+ T* tmp = p_;
+ p_ = 0;
+ return tmp;
+ }
+
private:
// Disallow copying and assignment.
scoped_ptr(const scoped_ptr&);
diff --git a/boost/asio/detail/select_reactor.hpp b/boost/asio/detail/select_reactor.hpp
index d6f75242e5..030c092250 100644
--- a/boost/asio/detail/select_reactor.hpp
+++ b/boost/asio/detail/select_reactor.hpp
@@ -35,7 +35,7 @@
#include <boost/asio/detail/timer_queue_base.hpp>
#include <boost/asio/detail/timer_queue_set.hpp>
#include <boost/asio/detail/wait_op.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/execution_context.hpp>
#if defined(BOOST_ASIO_HAS_IOCP)
# include <boost/asio/detail/thread.hpp>
@@ -48,7 +48,7 @@ namespace asio {
namespace detail {
class select_reactor
- : public boost::asio::detail::service_base<select_reactor>
+ : public execution_context_service_base<select_reactor>
{
public:
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -65,17 +65,17 @@ public:
};
// Constructor.
- BOOST_ASIO_DECL select_reactor(boost::asio::io_service& io_service);
+ BOOST_ASIO_DECL select_reactor(boost::asio::execution_context& ctx);
// Destructor.
BOOST_ASIO_DECL ~select_reactor();
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Recreate internal descriptors following a fork.
- BOOST_ASIO_DECL void fork_service(
- boost::asio::io_service::fork_event fork_ev);
+ BOOST_ASIO_DECL void notify_fork(
+ boost::asio::execution_context::fork_event fork_ev);
// Initialise the task, but only if the reactor is not in its own thread.
BOOST_ASIO_DECL void init_task();
@@ -93,7 +93,7 @@ public:
// Post a reactor operation for immediate completion.
void post_immediate_completion(reactor_op* op, bool is_continuation)
{
- io_service_.post_immediate_completion(op, is_continuation);
+ scheduler_.post_immediate_completion(op, is_continuation);
}
// Start a new operation. The reactor operation will be performed when the
@@ -149,8 +149,14 @@ public:
typename timer_queue<Time_Traits>::per_timer_data& timer,
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
+ // 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);
+
// Run select once until interrupted or events are ready to be dispatched.
- BOOST_ASIO_DECL void run(bool block, op_queue<operation>& ops);
+ BOOST_ASIO_DECL void run(long usec, op_queue<operation>& ops);
// Interrupt the select loop.
BOOST_ASIO_DECL void interrupt();
@@ -159,9 +165,6 @@ private:
#if defined(BOOST_ASIO_HAS_IOCP)
// Run the select loop in the thread.
BOOST_ASIO_DECL void run_thread();
-
- // Entry point for the select loop thread.
- BOOST_ASIO_DECL static void call_run_thread(select_reactor* reactor);
#endif // defined(BOOST_ASIO_HAS_IOCP)
// Helper function to add a new timer queue.
@@ -171,15 +174,20 @@ private:
BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
// Get the timeout value for the select call.
- BOOST_ASIO_DECL timeval* get_timeout(timeval& tv);
+ BOOST_ASIO_DECL timeval* get_timeout(long usec, timeval& tv);
// Cancel all operations associated with the given descriptor. This function
// does not acquire the select_reactor's mutex.
BOOST_ASIO_DECL void cancel_ops_unlocked(socket_type descriptor,
const boost::system::error_code& ec);
- // The io_service implementation used to post completions.
- io_service_impl& io_service_;
+ // The scheduler implementation used to post completions.
+# if defined(BOOST_ASIO_HAS_IOCP)
+ typedef class win_iocp_io_context scheduler_type;
+# else // defined(BOOST_ASIO_HAS_IOCP)
+ typedef class scheduler scheduler_type;
+# endif // defined(BOOST_ASIO_HAS_IOCP)
+ scheduler_type& scheduler_;
// Mutex to protect access to internal data.
boost::asio::detail::mutex mutex_;
@@ -197,6 +205,10 @@ private:
timer_queue_set timer_queues_;
#if defined(BOOST_ASIO_HAS_IOCP)
+ // Helper class to run the reactor loop in a thread.
+ class thread_function;
+ friend class thread_function;
+
// Does the reactor loop thread need to stop.
bool stop_thread_;
diff --git a/boost/asio/detail/service_registry.hpp b/boost/asio/detail/service_registry.hpp
index b5fa85bd01..7218848e4c 100644
--- a/boost/asio/detail/service_registry.hpp
+++ b/boost/asio/detail/service_registry.hpp
@@ -19,12 +19,16 @@
#include <typeinfo>
#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/noncopyable.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/execution_context.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
+
+class io_context;
+
namespace detail {
template <typename T>
@@ -34,27 +38,34 @@ class service_registry
: private noncopyable
{
public:
- // Constructor. Adds the initial service.
- template <typename Service, typename Arg>
- service_registry(boost::asio::io_service& o,
- Service* initial_service, Arg arg);
+ // Constructor.
+ BOOST_ASIO_DECL service_registry(execution_context& owner);
// Destructor.
BOOST_ASIO_DECL ~service_registry();
+ // Shutdown all services.
+ BOOST_ASIO_DECL void shutdown_services();
+
+ // Destroy all services.
+ BOOST_ASIO_DECL void destroy_services();
+
// Notify all services of a fork event.
- BOOST_ASIO_DECL void notify_fork(boost::asio::io_service::fork_event fork_ev);
+ BOOST_ASIO_DECL void notify_fork(execution_context::fork_event fork_ev);
- // Get the first service object cast to the specified type. Called during
- // io_service construction and so performs no locking or type checking.
+ // Get the service object corresponding to the specified service type. Will
+ // create a new service object automatically if no such object already
+ // exists. Ownership of the service object is not transferred to the caller.
template <typename Service>
- Service& first_service();
+ Service& use_service();
// Get the service object corresponding to the specified service type. Will
// create a new service object automatically if no such object already
// exists. Ownership of the service object is not transferred to the caller.
+ // This overload is used for backwards compatibility with services that
+ // inherit from io_context::service.
template <typename Service>
- Service& use_service();
+ Service& use_service(io_context& owner);
// Add a service object. Throws on error, in which case ownership of the
// object is retained by the caller.
@@ -66,70 +77,79 @@ public:
bool has_service() const;
private:
+ // Initalise a service's key when the key_type typedef is not available.
+ template <typename Service>
+ static void init_key(execution_context::service::key& key, ...);
+
+#if !defined(BOOST_ASIO_NO_TYPEID)
+ // Initalise a service's key when the key_type typedef is available.
+ template <typename Service>
+ static void init_key(execution_context::service::key& key,
+ typename enable_if<
+ is_base_of<typename Service::key_type, Service>::value>::type*);
+#endif // !defined(BOOST_ASIO_NO_TYPEID)
+
// Initialise a service's key based on its id.
- BOOST_ASIO_DECL static void init_key(
- boost::asio::io_service::service::key& key,
- const boost::asio::io_service::id& id);
+ BOOST_ASIO_DECL static void init_key_from_id(
+ execution_context::service::key& key,
+ const execution_context::id& id);
#if !defined(BOOST_ASIO_NO_TYPEID)
// Initialise a service's key based on its id.
template <typename Service>
- static void init_key(boost::asio::io_service::service::key& key,
- const boost::asio::detail::service_id<Service>& /*id*/);
+ static void init_key_from_id(execution_context::service::key& key,
+ const service_id<Service>& /*id*/);
#endif // !defined(BOOST_ASIO_NO_TYPEID)
// Check if a service matches the given id.
BOOST_ASIO_DECL static bool keys_match(
- const boost::asio::io_service::service::key& key1,
- const boost::asio::io_service::service::key& key2);
+ const execution_context::service::key& key1,
+ const execution_context::service::key& key2);
// The type of a factory function used for creating a service instance.
- typedef boost::asio::io_service::service*
- (*factory_type)(boost::asio::io_service&);
+ typedef execution_context::service*(*factory_type)(void*);
// Factory function for creating a service instance.
- template <typename Service>
- static boost::asio::io_service::service* create(
- boost::asio::io_service& owner);
+ template <typename Service, typename Owner>
+ static execution_context::service* create(void* owner);
// Destroy a service instance.
- BOOST_ASIO_DECL static void destroy(
- boost::asio::io_service::service* service);
+ BOOST_ASIO_DECL static void destroy(execution_context::service* service);
// Helper class to manage service pointers.
struct auto_service_ptr;
friend struct auto_service_ptr;
struct auto_service_ptr
{
- boost::asio::io_service::service* ptr_;
+ execution_context::service* ptr_;
~auto_service_ptr() { destroy(ptr_); }
};
// Get the service object corresponding to the specified service key. Will
// create a new service object automatically if no such object already
// exists. Ownership of the service object is not transferred to the caller.
- BOOST_ASIO_DECL boost::asio::io_service::service* do_use_service(
- const boost::asio::io_service::service::key& key,
- factory_type factory);
+ BOOST_ASIO_DECL execution_context::service* do_use_service(
+ const execution_context::service::key& key,
+ factory_type factory, void* owner);
// Add a service object. Throws on error, in which case ownership of the
// object is retained by the caller.
BOOST_ASIO_DECL void do_add_service(
- const boost::asio::io_service::service::key& key,
- boost::asio::io_service::service* new_service);
+ const execution_context::service::key& key,
+ execution_context::service* new_service);
// Check whether a service object with the specified key already exists.
BOOST_ASIO_DECL bool do_has_service(
- const boost::asio::io_service::service::key& key) const;
+ const execution_context::service::key& key) const;
// Mutex to protect access to internal data.
mutable boost::asio::detail::mutex mutex_;
// The owner of this service registry and the services it contains.
- boost::asio::io_service& owner_;
+ execution_context& owner_;
// The first service in the list of contained services.
- boost::asio::io_service::service* first_service_;
+ execution_context::service* first_service_;
};
} // namespace detail
diff --git a/boost/asio/detail/shared_ptr.hpp b/boost/asio/detail/shared_ptr.hpp
deleted file mode 100644
index f26c645121..0000000000
--- a/boost/asio/detail/shared_ptr.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// detail/shared_ptr.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_DETAIL_SHARED_PTR_HPP
-#define BOOST_ASIO_DETAIL_SHARED_PTR_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-
-#if defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-# include <memory>
-#else // defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-# include <boost/shared_ptr.hpp>
-#endif // defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-#if defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-using std::shared_ptr;
-#else // defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-using boost::shared_ptr;
-#endif // defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#endif // BOOST_ASIO_DETAIL_SHARED_PTR_HPP
diff --git a/boost/asio/detail/signal_handler.hpp b/boost/asio/detail/signal_handler.hpp
index edad41b8ee..6ea723a27a 100644
--- a/boost/asio/detail/signal_handler.hpp
+++ b/boost/asio/detail/signal_handler.hpp
@@ -16,10 +16,12 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/handler_work.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/signal_op.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -38,17 +40,19 @@ public:
: signal_op(&signal_handler::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(h))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
signal_handler* h(static_cast<signal_handler*>(base));
ptr p = { boost::asio::detail::addressof(h->handler_), h, h };
+ handler_work<Handler> w(h->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((h));
+ BOOST_ASIO_HANDLER_COMPLETION((*h));
// 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
@@ -66,7 +70,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/signal_set_service.hpp b/boost/asio/detail/signal_set_service.hpp
index a023ebb66f..f27f8652c4 100644
--- a/boost/asio/detail/signal_set_service.hpp
+++ b/boost/asio/detail/signal_set_service.hpp
@@ -20,9 +20,9 @@
#include <cstddef>
#include <signal.h>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/op_queue.hpp>
#include <boost/asio/detail/signal_handler.hpp>
#include <boost/asio/detail/signal_op.hpp>
@@ -48,7 +48,8 @@ extern BOOST_ASIO_DECL struct signal_state* get_signal_state();
extern "C" BOOST_ASIO_DECL void boost_asio_signal_handler(int signal_number);
-class signal_set_service
+class signal_set_service :
+ public service_base<signal_set_service>
{
public:
// Type used for tracking an individual signal registration.
@@ -109,17 +110,17 @@ public:
};
// Constructor.
- BOOST_ASIO_DECL signal_set_service(boost::asio::io_service& io_service);
+ BOOST_ASIO_DECL signal_set_service(boost::asio::io_context& io_context);
// Destructor.
BOOST_ASIO_DECL ~signal_set_service();
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Perform fork-related housekeeping.
- BOOST_ASIO_DECL void fork_service(
- boost::asio::io_service::fork_event fork_ev);
+ BOOST_ASIO_DECL void notify_fork(
+ boost::asio::io_context::fork_event fork_ev);
// Construct a new signal_set implementation.
BOOST_ASIO_DECL void construct(implementation_type& impl);
@@ -150,11 +151,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef signal_handler<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "signal_set", &impl, "async_wait"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_.context(),
+ *p.p, "signal_set", &impl, 0, "async_wait"));
start_wait_op(impl, p.p);
p.v = p.p = 0;
@@ -179,8 +180,8 @@ private:
// Helper function to start a wait operation.
BOOST_ASIO_DECL void start_wait_op(implementation_type& impl, signal_op* op);
- // The io_service instance used for dispatching handlers.
- io_service_impl& io_service_;
+ // The io_context instance used for dispatching handlers.
+ io_context_impl& io_context_;
#if !defined(BOOST_ASIO_WINDOWS) \
&& !defined(BOOST_ASIO_WINDOWS_RUNTIME) \
diff --git a/boost/asio/detail/socket_ops.hpp b/boost/asio/detail/socket_ops.hpp
index 136a3f01f7..8d39ab8737 100644
--- a/boost/asio/detail/socket_ops.hpp
+++ b/boost/asio/detail/socket_ops.hpp
@@ -18,9 +18,8 @@
#include <boost/asio/detail/config.hpp>
#include <boost/system/error_code.hpp>
-#include <boost/asio/detail/shared_ptr.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/weak_ptr.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -265,12 +264,16 @@ BOOST_ASIO_DECL int select(int nfds, fd_set* readfds, fd_set* writefds,
fd_set* exceptfds, timeval* timeout, boost::system::error_code& ec);
BOOST_ASIO_DECL int poll_read(socket_type s,
- state_type state, boost::system::error_code& ec);
+ state_type state, int msec, boost::system::error_code& ec);
BOOST_ASIO_DECL int poll_write(socket_type s,
- state_type state, boost::system::error_code& ec);
+ state_type state, int msec, boost::system::error_code& ec);
-BOOST_ASIO_DECL int poll_connect(socket_type s, boost::system::error_code& ec);
+BOOST_ASIO_DECL int poll_error(socket_type s,
+ state_type state, int msec, boost::system::error_code& ec);
+
+BOOST_ASIO_DECL int poll_connect(socket_type s,
+ int msec, boost::system::error_code& ec);
#endif // !defined(BOOST_ASIO_WINDOWS_RUNTIME)
diff --git a/boost/asio/detail/socket_types.hpp b/boost/asio/detail/socket_types.hpp
index 0768f70077..ca9fc83a29 100644
--- a/boost/asio/detail/socket_types.hpp
+++ b/boost/asio/detail/socket_types.hpp
@@ -59,7 +59,8 @@
# include <sys/ioctl.h>
# if (defined(__MACH__) && defined(__APPLE__)) \
|| defined(__FreeBSD__) || defined(__NetBSD__) \
- || defined(__OpenBSD__) || defined(__linux__)
+ || defined(__OpenBSD__) || defined(__linux__) \
+ || defined(__EMSCRIPTEN__)
# include <poll.h>
# elif !defined(__SYMBIAN32__)
# include <sys/poll.h>
@@ -152,6 +153,7 @@ typedef int signed_size_type;
# define BOOST_ASIO_OS_DEF_SO_DONTROUTE 0x10
# define BOOST_ASIO_OS_DEF_SO_KEEPALIVE 0x8
# define BOOST_ASIO_OS_DEF_SO_LINGER 0x80
+# define BOOST_ASIO_OS_DEF_SO_OOBINLINE 0x100
# define BOOST_ASIO_OS_DEF_SO_SNDBUF 0x1001
# define BOOST_ASIO_OS_DEF_SO_RCVBUF 0x1002
# define BOOST_ASIO_OS_DEF_SO_SNDLOWAT 0x1003
@@ -236,6 +238,7 @@ typedef int signed_size_type;
# define BOOST_ASIO_OS_DEF_SO_DONTROUTE SO_DONTROUTE
# define BOOST_ASIO_OS_DEF_SO_KEEPALIVE SO_KEEPALIVE
# define BOOST_ASIO_OS_DEF_SO_LINGER SO_LINGER
+# define BOOST_ASIO_OS_DEF_SO_OOBINLINE SO_OOBINLINE
# define BOOST_ASIO_OS_DEF_SO_SNDBUF SO_SNDBUF
# define BOOST_ASIO_OS_DEF_SO_RCVBUF SO_RCVBUF
# define BOOST_ASIO_OS_DEF_SO_SNDLOWAT SO_SNDLOWAT
@@ -351,6 +354,7 @@ typedef int signed_size_type;
# define BOOST_ASIO_OS_DEF_SO_DONTROUTE SO_DONTROUTE
# define BOOST_ASIO_OS_DEF_SO_KEEPALIVE SO_KEEPALIVE
# define BOOST_ASIO_OS_DEF_SO_LINGER SO_LINGER
+# define BOOST_ASIO_OS_DEF_SO_OOBINLINE SO_OOBINLINE
# define BOOST_ASIO_OS_DEF_SO_SNDBUF SO_SNDBUF
# define BOOST_ASIO_OS_DEF_SO_RCVBUF SO_RCVBUF
# define BOOST_ASIO_OS_DEF_SO_SNDLOWAT SO_SNDLOWAT
diff --git a/boost/asio/detail/solaris_fenced_block.hpp b/boost/asio/detail/solaris_fenced_block.hpp
index 2aef0229f1..5653a8b4c4 100644
--- a/boost/asio/detail/solaris_fenced_block.hpp
+++ b/boost/asio/detail/solaris_fenced_block.hpp
@@ -20,6 +20,7 @@
#if defined(__sun)
#include <atomic.h>
+#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/push_options.hpp>
diff --git a/boost/asio/detail/std_global.hpp b/boost/asio/detail/std_global.hpp
new file mode 100644
index 0000000000..f0936e5ea9
--- /dev/null
+++ b/boost/asio/detail/std_global.hpp
@@ -0,0 +1,72 @@
+//
+// detail/std_global.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_STD_GLOBAL_HPP
+#define BOOST_ASIO_DETAIL_STD_GLOBAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_STD_CALL_ONCE)
+
+#include <exception>
+#include <mutex>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+struct std_global_impl
+{
+ // Helper function to perform initialisation.
+ static void do_init()
+ {
+ instance_.ptr_ = new T;
+ }
+
+ // Destructor automatically cleans up the global.
+ ~std_global_impl()
+ {
+ delete ptr_;
+ }
+
+ static std::once_flag init_once_;
+ static std_global_impl instance_;
+ T* ptr_;
+};
+
+template <typename T>
+std::once_flag std_global_impl<T>::init_once_;
+
+template <typename T>
+std_global_impl<T> std_global_impl<T>::instance_;
+
+template <typename T>
+T& std_global()
+{
+ std::call_once(std_global_impl<T>::init_once_, &std_global_impl<T>::do_init);
+ return *std_global_impl<T>::instance_.ptr_;
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_STD_CALL_ONCE)
+
+#endif // BOOST_ASIO_DETAIL_STD_GLOBAL_HPP
diff --git a/boost/asio/detail/std_thread.hpp b/boost/asio/detail/std_thread.hpp
index cd2a61dac2..35bcc1722c 100644
--- a/boost/asio/detail/std_thread.hpp
+++ b/boost/asio/detail/std_thread.hpp
@@ -52,6 +52,12 @@ public:
thread_.join();
}
+ // Get number of CPUs.
+ static std::size_t hardware_concurrency()
+ {
+ return std::thread::hardware_concurrency();
+ }
+
private:
std::thread thread_;
};
diff --git a/boost/asio/detail/strand_executor_service.hpp b/boost/asio/detail/strand_executor_service.hpp
new file mode 100644
index 0000000000..38728d4610
--- /dev/null
+++ b/boost/asio/detail/strand_executor_service.hpp
@@ -0,0 +1,140 @@
+//
+// detail/strand_executor_service.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_STRAND_EXECUTOR_SERVICE_HPP
+#define BOOST_ASIO_DETAIL_STRAND_EXECUTOR_SERVICE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/atomic_count.hpp>
+#include <boost/asio/detail/executor_op.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/mutex.hpp>
+#include <boost/asio/detail/op_queue.hpp>
+#include <boost/asio/detail/scheduler_operation.hpp>
+#include <boost/asio/detail/scoped_ptr.hpp>
+#include <boost/asio/execution_context.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+// Default service implementation for a strand.
+class strand_executor_service
+ : public execution_context_service_base<strand_executor_service>
+{
+public:
+ // The underlying implementation of a strand.
+ class strand_impl
+ {
+ public:
+ BOOST_ASIO_DECL ~strand_impl();
+
+ private:
+ friend class strand_executor_service;
+
+ // Mutex to protect access to internal data.
+ mutex* mutex_;
+
+ // Indicates whether the strand is currently "locked" by a handler. This
+ // means that there is a handler upcall in progress, or that the strand
+ // itself has been scheduled in order to invoke some pending handlers.
+ bool locked_;
+
+ // The handlers that are waiting on the strand but should not be run until
+ // after the next time the strand is scheduled. This queue must only be
+ // modified while the mutex is locked.
+ op_queue<scheduler_operation> waiting_queue_;
+
+ // The handlers that are ready to be run. Logically speaking, these are the
+ // handlers that hold the strand's lock. The ready queue is only modified
+ // from within the strand and so may be accessed without locking the mutex.
+ op_queue<scheduler_operation> ready_queue_;
+
+ // Pointers to adjacent handle implementations in linked list.
+ strand_impl* next_;
+ strand_impl* prev_;
+
+ // The strand service in where the implementation is held.
+ strand_executor_service* service_;
+ };
+
+ typedef shared_ptr<strand_impl> implementation_type;
+
+ // Construct a new strand service for the specified context.
+ BOOST_ASIO_DECL explicit strand_executor_service(execution_context& context);
+
+ // Destroy all user-defined handler objects owned by the service.
+ BOOST_ASIO_DECL void shutdown();
+
+ // Create a new strand_executor implementation.
+ BOOST_ASIO_DECL implementation_type create_implementation();
+
+ // Request invocation of the given function.
+ template <typename Executor, typename Function, typename Allocator>
+ static void dispatch(const implementation_type& impl, Executor& ex,
+ BOOST_ASIO_MOVE_ARG(Function) function, const Allocator& a);
+
+ // Request invocation of the given function and return immediately.
+ template <typename Executor, typename Function, typename Allocator>
+ static void post(const implementation_type& impl, Executor& ex,
+ BOOST_ASIO_MOVE_ARG(Function) function, const Allocator& a);
+
+ // Request invocation of the given function and return immediately.
+ template <typename Executor, typename Function, typename Allocator>
+ static void defer(const implementation_type& impl, Executor& ex,
+ BOOST_ASIO_MOVE_ARG(Function) function, const Allocator& a);
+
+ // Determine whether the strand is running in the current thread.
+ BOOST_ASIO_DECL static bool running_in_this_thread(
+ const implementation_type& impl);
+
+private:
+ friend class strand_impl;
+ template <typename Executor> class invoker;
+
+ // Adds a function to the strand. Returns true if it acquires the lock.
+ BOOST_ASIO_DECL static bool enqueue(const implementation_type& impl,
+ scheduler_operation* op);
+
+ // Mutex to protect access to the service-wide state.
+ mutex mutex_;
+
+ // Number of mutexes shared between all strand objects.
+ enum { num_mutexes = 193 };
+
+ // Pool of mutexes.
+ scoped_ptr<mutex> mutexes_[num_mutexes];
+
+ // Extra value used when hashing to prevent recycled memory locations from
+ // getting the same mutex.
+ std::size_t salt_;
+
+ // The head of a linked list of all implementations.
+ strand_impl* impl_list_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/detail/impl/strand_executor_service.hpp>
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/detail/impl/strand_executor_service.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_ASIO_DETAIL_STRAND_EXECUTOR_SERVICE_HPP
diff --git a/boost/asio/detail/strand_service.hpp b/boost/asio/detail/strand_service.hpp
index 8a94e58e36..e9d05b3ae7 100644
--- a/boost/asio/detail/strand_service.hpp
+++ b/boost/asio/detail/strand_service.hpp
@@ -16,7 +16,7 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/op_queue.hpp>
#include <boost/asio/detail/operation.hpp>
@@ -75,20 +75,20 @@ public:
typedef strand_impl* implementation_type;
- // Construct a new strand service for the specified io_service.
- BOOST_ASIO_DECL explicit strand_service(boost::asio::io_service& io_service);
+ // Construct a new strand service for the specified io_context.
+ BOOST_ASIO_DECL explicit strand_service(boost::asio::io_context& io_context);
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Construct a new strand implementation.
BOOST_ASIO_DECL void construct(implementation_type& impl);
- // Request the io_service to invoke the given handler.
+ // Request the io_context to invoke the given handler.
template <typename Handler>
void dispatch(implementation_type& impl, Handler& handler);
- // Request the io_service to invoke the given handler and return immediately.
+ // Request the io_context to invoke the given handler and return immediately.
template <typename Handler>
void post(implementation_type& impl, Handler& handler);
@@ -105,12 +105,12 @@ private:
BOOST_ASIO_DECL void do_post(implementation_type& impl,
operation* op, bool is_continuation);
- BOOST_ASIO_DECL static void do_complete(io_service_impl* owner,
+ BOOST_ASIO_DECL static void do_complete(void* owner,
operation* base, const boost::system::error_code& ec,
std::size_t bytes_transferred);
- // The io_service implementation used to post completions.
- io_service_impl& io_service_;
+ // The io_context implementation used to post completions.
+ io_context_impl& io_context_;
// Mutex to protect access to the array of implementations.
boost::asio::detail::mutex mutex_;
diff --git a/boost/asio/detail/string_view.hpp b/boost/asio/detail/string_view.hpp
new file mode 100644
index 0000000000..3d0a24f4c6
--- /dev/null
+++ b/boost/asio/detail/string_view.hpp
@@ -0,0 +1,47 @@
+//
+// detail/string_view.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_STRING_VIEW_HPP
+#define BOOST_ASIO_DETAIL_STRING_VIEW_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
+#if defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+# include <experimental/string_view>
+#else // defined(BOOST_ASIO_HAS_EXPERIMENTAL_STRING_VIEW)
+# include <string_view>
+#endif // defined(BOOST_ASIO_HAS_EXPERIMENTAL_STRING_VIEW)
+
+namespace boost {
+namespace asio {
+
+#if defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+using std::experimental::basic_string_view;
+using std::experimental::string_view;
+#else // defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+using std::basic_string_view;
+using std::string_view;
+#endif // defined(BOOST_ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)
+
+} // namespace asio
+} // namespace boost
+
+# define BOOST_ASIO_STRING_VIEW_PARAM boost::asio::string_view
+#else // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+# define BOOST_ASIO_STRING_VIEW_PARAM const std::string&
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
+#endif // BOOST_ASIO_DETAIL_STRING_VIEW_HPP
diff --git a/boost/asio/detail/thread.hpp b/boost/asio/detail/thread.hpp
index f385fc85a1..e10040e972 100644
--- a/boost/asio/detail/thread.hpp
+++ b/boost/asio/detail/thread.hpp
@@ -20,8 +20,10 @@
#if !defined(BOOST_ASIO_HAS_THREADS)
# include <boost/asio/detail/null_thread.hpp>
#elif defined(BOOST_ASIO_WINDOWS)
-# if defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE)
-# include <boost/asio/detail/winapi_thread.hpp>
+# if defined(UNDER_CE)
+# include <boost/asio/detail/wince_thread.hpp>
+# elif defined(BOOST_ASIO_WINDOWS_APP)
+# include <boost/asio/detail/winapp_thread.hpp>
# else
# include <boost/asio/detail/win_thread.hpp>
# endif
@@ -40,8 +42,10 @@ namespace detail {
#if !defined(BOOST_ASIO_HAS_THREADS)
typedef null_thread thread;
#elif defined(BOOST_ASIO_WINDOWS)
-# if defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE)
-typedef winapi_thread thread;
+# if defined(UNDER_CE)
+typedef wince_thread thread;
+# elif defined(BOOST_ASIO_WINDOWS_APP)
+typedef winapp_thread thread;
# else
typedef win_thread thread;
# endif
diff --git a/boost/asio/detail/thread_context.hpp b/boost/asio/detail/thread_context.hpp
new file mode 100644
index 0000000000..8c059ccb02
--- /dev/null
+++ b/boost/asio/detail/thread_context.hpp
@@ -0,0 +1,44 @@
+//
+// detail/thread_context.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_THREAD_CONTEXT_HPP
+#define BOOST_ASIO_DETAIL_THREAD_CONTEXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <climits>
+#include <cstddef>
+#include <boost/asio/detail/call_stack.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class thread_info_base;
+
+// Base class for things that manage threads (scheduler, win_iocp_io_context).
+class thread_context
+{
+public:
+ // 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;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_THREAD_CONTEXT_HPP
diff --git a/boost/asio/detail/thread_group.hpp b/boost/asio/detail/thread_group.hpp
new file mode 100644
index 0000000000..2451e8f3b7
--- /dev/null
+++ b/boost/asio/detail/thread_group.hpp
@@ -0,0 +1,91 @@
+//
+// detail/thread_group.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_THREAD_GROUP_HPP
+#define BOOST_ASIO_DETAIL_THREAD_GROUP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/scoped_ptr.hpp>
+#include <boost/asio/detail/thread.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+class thread_group
+{
+public:
+ // Constructor initialises an empty thread group.
+ thread_group()
+ : first_(0)
+ {
+ }
+
+ // Destructor joins any remaining threads in the group.
+ ~thread_group()
+ {
+ join();
+ }
+
+ // Create a new thread in the group.
+ template <typename Function>
+ void create_thread(Function f)
+ {
+ first_ = new item(f, first_);
+ }
+
+ // Create new threads in the group.
+ template <typename Function>
+ void create_threads(Function f, std::size_t num_threads)
+ {
+ for (std::size_t i = 0; i < num_threads; ++i)
+ create_thread(f);
+ }
+
+ // Wait for all threads in the group to exit.
+ void join()
+ {
+ while (first_)
+ {
+ first_->thread_.join();
+ item* tmp = first_;
+ first_ = first_->next_;
+ delete tmp;
+ }
+ }
+
+private:
+ // Structure used to track a single thread in the group.
+ struct item
+ {
+ template <typename Function>
+ explicit item(Function f, item* next)
+ : thread_(f),
+ next_(next)
+ {
+ }
+
+ boost::asio::detail::thread thread_;
+ item* next_;
+ };
+
+ // The first thread in the group.
+ item* first_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#endif // BOOST_ASIO_DETAIL_THREAD_GROUP_HPP
diff --git a/boost/asio/detail/thread_info_base.hpp b/boost/asio/detail/thread_info_base.hpp
index 3baa8ef39f..c0dc322f41 100644
--- a/boost/asio/detail/thread_info_base.hpp
+++ b/boost/asio/detail/thread_info_base.hpp
@@ -42,13 +42,15 @@ public:
static void* allocate(thread_info_base* this_thread, std::size_t size)
{
+ std::size_t chunks = (size + chunk_size - 1) / chunk_size;
+
if (this_thread && this_thread->reusable_memory_)
{
void* const pointer = this_thread->reusable_memory_;
this_thread->reusable_memory_ = 0;
unsigned char* const mem = static_cast<unsigned char*>(pointer);
- if (static_cast<std::size_t>(mem[0]) >= size)
+ if (static_cast<std::size_t>(mem[0]) >= chunks)
{
mem[size] = mem[0];
return pointer;
@@ -57,16 +59,16 @@ public:
::operator delete(pointer);
}
- void* const pointer = ::operator new(size + 1);
+ void* const pointer = ::operator new(chunks * chunk_size + 1);
unsigned char* const mem = static_cast<unsigned char*>(pointer);
- mem[size] = (size <= UCHAR_MAX) ? static_cast<unsigned char>(size) : 0;
+ mem[size] = (chunks <= UCHAR_MAX) ? static_cast<unsigned char>(chunks) : 0;
return pointer;
}
static void deallocate(thread_info_base* this_thread,
void* pointer, std::size_t size)
{
- if (size <= UCHAR_MAX)
+ if (size <= chunk_size * UCHAR_MAX)
{
if (this_thread && this_thread->reusable_memory_ == 0)
{
@@ -81,6 +83,7 @@ public:
}
private:
+ enum { chunk_size = 4 };
void* reusable_memory_;
};
diff --git a/boost/asio/detail/timer_queue.hpp b/boost/asio/detail/timer_queue.hpp
index cb848dfb3a..f8d48babad 100644
--- a/boost/asio/detail/timer_queue.hpp
+++ b/boost/asio/detail/timer_queue.hpp
@@ -47,7 +47,11 @@ public:
class per_timer_data
{
public:
- per_timer_data() : next_(0), prev_(0) {}
+ per_timer_data() :
+ heap_index_((std::numeric_limits<std::size_t>::max)()),
+ next_(0), prev_(0)
+ {
+ }
private:
friend class timer_queue;
@@ -189,6 +193,29 @@ public:
return num_cancelled;
}
+ // Move operations from one timer to another, empty timer.
+ void move_timer(per_timer_data& target, per_timer_data& source)
+ {
+ target.op_queue_.push(source.op_queue_);
+
+ target.heap_index_ = source.heap_index_;
+ source.heap_index_ = (std::numeric_limits<std::size_t>::max)();
+
+ if (target.heap_index_ < heap_.size())
+ heap_[target.heap_index_].timer_ = &target;
+
+ if (timers_ == &source)
+ timers_ = &target;
+ if (source.prev_)
+ source.prev_->next_ = &target;
+ if (source.next_)
+ source.next_->prev_= &target;
+ target.next_ = source.next_;
+ target.prev_ = source.prev_;
+ source.next_ = 0;
+ source.prev_ = 0;
+ }
+
private:
// Move the item at the given index up the heap to its correct position.
void up_heap(std::size_t index)
diff --git a/boost/asio/detail/timer_queue_ptime.hpp b/boost/asio/detail/timer_queue_ptime.hpp
index 0693acca83..d1934f1375 100644
--- a/boost/asio/detail/timer_queue_ptime.hpp
+++ b/boost/asio/detail/timer_queue_ptime.hpp
@@ -15,13 +15,15 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
#include <boost/asio/time_traits.hpp>
#include <boost/asio/detail/timer_queue.hpp>
#include <boost/asio/detail/push_options.hpp>
-#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
-
namespace boost {
namespace asio {
namespace detail {
@@ -76,6 +78,10 @@ public:
per_timer_data& timer, op_queue<operation>& ops,
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
+ // Move operations from one timer to another, empty timer.
+ BOOST_ASIO_DECL void move_timer(per_timer_data& target,
+ per_timer_data& source);
+
private:
timer_queue<forwarding_posix_time_traits> impl_;
};
@@ -84,12 +90,12 @@ private:
} // namespace asio
} // namespace boost
-#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
-
#include <boost/asio/detail/pop_options.hpp>
#if defined(BOOST_ASIO_HEADER_ONLY)
# include <boost/asio/detail/impl/timer_queue_ptime.ipp>
#endif // defined(BOOST_ASIO_HEADER_ONLY)
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
#endif // BOOST_ASIO_DETAIL_TIMER_QUEUE_PTIME_HPP
diff --git a/boost/asio/detail/timer_scheduler.hpp b/boost/asio/detail/timer_scheduler.hpp
index 49dc113d10..290d0b0680 100644
--- a/boost/asio/detail/timer_scheduler.hpp
+++ b/boost/asio/detail/timer_scheduler.hpp
@@ -21,7 +21,7 @@
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
# include <boost/asio/detail/winrt_timer_scheduler.hpp>
#elif defined(BOOST_ASIO_HAS_IOCP)
-# include <boost/asio/detail/win_iocp_io_service.hpp>
+# include <boost/asio/detail/win_iocp_io_context.hpp>
#elif defined(BOOST_ASIO_HAS_EPOLL)
# include <boost/asio/detail/epoll_reactor.hpp>
#elif defined(BOOST_ASIO_HAS_KQUEUE)
diff --git a/boost/asio/detail/timer_scheduler_fwd.hpp b/boost/asio/detail/timer_scheduler_fwd.hpp
index bf732a63d3..de3d3bd350 100644
--- a/boost/asio/detail/timer_scheduler_fwd.hpp
+++ b/boost/asio/detail/timer_scheduler_fwd.hpp
@@ -24,7 +24,7 @@ namespace detail {
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
typedef class winrt_timer_scheduler timer_scheduler;
#elif defined(BOOST_ASIO_HAS_IOCP)
-typedef class win_iocp_io_service timer_scheduler;
+typedef class win_iocp_io_context timer_scheduler;
#elif defined(BOOST_ASIO_HAS_EPOLL)
typedef class epoll_reactor timer_scheduler;
#elif defined(BOOST_ASIO_HAS_KQUEUE)
diff --git a/boost/asio/detail/type_traits.hpp b/boost/asio/detail/type_traits.hpp
index 53a73a0eb1..1556e597e0 100644
--- a/boost/asio/detail/type_traits.hpp
+++ b/boost/asio/detail/type_traits.hpp
@@ -21,6 +21,11 @@
# include <type_traits>
#else // defined(BOOST_ASIO_HAS_TYPE_TRAITS)
# include <boost/type_traits/add_const.hpp>
+# include <boost/type_traits/conditional.hpp>
+# include <boost/type_traits/decay.hpp>
+# include <boost/type_traits/integral_constant.hpp>
+# include <boost/type_traits/is_base_of.hpp>
+# include <boost/type_traits/is_class.hpp>
# include <boost/type_traits/is_const.hpp>
# include <boost/type_traits/is_convertible.hpp>
# include <boost/type_traits/is_function.hpp>
@@ -28,6 +33,7 @@
# include <boost/type_traits/remove_pointer.hpp>
# include <boost/type_traits/remove_reference.hpp>
# include <boost/utility/enable_if.hpp>
+# include <boost/utility/result_of.hpp>
#endif // defined(BOOST_ASIO_HAS_TYPE_TRAITS)
namespace boost {
@@ -35,23 +41,39 @@ namespace asio {
#if defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS)
using std::add_const;
+using std::conditional;
+using std::decay;
using std::enable_if;
+using std::false_type;
+using std::integral_constant;
+using std::is_base_of;
+using std::is_class;
using std::is_const;
using std::is_convertible;
using std::is_function;
using std::is_same;
using std::remove_pointer;
using std::remove_reference;
+using std::result_of;
+using std::true_type;
#else // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS)
using boost::add_const;
template <bool Condition, typename Type = void>
struct enable_if : boost::enable_if_c<Condition, Type> {};
+using boost::conditional;
+using boost::decay;
+using boost::false_type;
+using boost::integral_constant;
+using boost::is_base_of;
+using boost::is_class;
using boost::is_const;
using boost::is_convertible;
using boost::is_function;
using boost::is_same;
using boost::remove_pointer;
using boost::remove_reference;
+using boost::result_of;
+using boost::true_type;
#endif // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS)
} // namespace asio
diff --git a/boost/asio/detail/variadic_templates.hpp b/boost/asio/detail/variadic_templates.hpp
index 6d55bc7a7c..228a6542e9 100644
--- a/boost/asio/detail/variadic_templates.hpp
+++ b/boost/asio/detail/variadic_templates.hpp
@@ -34,27 +34,83 @@
# define BOOST_ASIO_VARIADIC_TARGS(n) BOOST_ASIO_VARIADIC_TARGS_##n
-# define BOOST_ASIO_VARIADIC_TARGS_1 x1
-# define BOOST_ASIO_VARIADIC_TARGS_2 x1, x2
-# define BOOST_ASIO_VARIADIC_TARGS_3 x1, x2, x3
-# define BOOST_ASIO_VARIADIC_TARGS_4 x1, x2, x3, x4
-# define BOOST_ASIO_VARIADIC_TARGS_5 x1, x2, x3, x4, x5
-
-# define BOOST_ASIO_VARIADIC_PARAMS(n) BOOST_ASIO_VARIADIC_PARAMS_##n
-
-# define BOOST_ASIO_VARIADIC_PARAMS_1 T1 x1
-# define BOOST_ASIO_VARIADIC_PARAMS_2 T1 x1, T2 x2
-# define BOOST_ASIO_VARIADIC_PARAMS_3 T1 x1, T2 x2, T3 x3
-# define BOOST_ASIO_VARIADIC_PARAMS_4 T1 x1, T2 x2, T3 x3, T4 x4
-# define BOOST_ASIO_VARIADIC_PARAMS_5 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5
-
-# define BOOST_ASIO_VARIADIC_ARGS(n) BOOST_ASIO_VARIADIC_ARGS_##n
-
-# define BOOST_ASIO_VARIADIC_ARGS_1 x1
-# define BOOST_ASIO_VARIADIC_ARGS_2 x1, x2
-# define BOOST_ASIO_VARIADIC_ARGS_3 x1, x2, x3
-# define BOOST_ASIO_VARIADIC_ARGS_4 x1, x2, x3, x4
-# define BOOST_ASIO_VARIADIC_ARGS_5 x1, x2, x3, x4, x5
+# define BOOST_ASIO_VARIADIC_TARGS_1 T1
+# define BOOST_ASIO_VARIADIC_TARGS_2 T1, T2
+# define BOOST_ASIO_VARIADIC_TARGS_3 T1, T2, T3
+# define BOOST_ASIO_VARIADIC_TARGS_4 T1, T2, T3, T4
+# define BOOST_ASIO_VARIADIC_TARGS_5 T1, T2, T3, T4, T5
+
+# define BOOST_ASIO_VARIADIC_BYVAL_PARAMS(n) \
+ BOOST_ASIO_VARIADIC_BYVAL_PARAMS_##n
+
+# define BOOST_ASIO_VARIADIC_BYVAL_PARAMS_1 T1 x1
+# define BOOST_ASIO_VARIADIC_BYVAL_PARAMS_2 T1 x1, T2 x2
+# define BOOST_ASIO_VARIADIC_BYVAL_PARAMS_3 T1 x1, T2 x2, T3 x3
+# define BOOST_ASIO_VARIADIC_BYVAL_PARAMS_4 T1 x1, T2 x2, T3 x3, T4 x4
+# define BOOST_ASIO_VARIADIC_BYVAL_PARAMS_5 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5
+
+# define BOOST_ASIO_VARIADIC_BYVAL_ARGS(n) \
+ BOOST_ASIO_VARIADIC_BYVAL_ARGS_##n
+
+# define BOOST_ASIO_VARIADIC_BYVAL_ARGS_1 x1
+# define BOOST_ASIO_VARIADIC_BYVAL_ARGS_2 x1, x2
+# define BOOST_ASIO_VARIADIC_BYVAL_ARGS_3 x1, x2, x3
+# define BOOST_ASIO_VARIADIC_BYVAL_ARGS_4 x1, x2, x3, x4
+# define BOOST_ASIO_VARIADIC_BYVAL_ARGS_5 x1, x2, x3, x4, x5
+
+# define BOOST_ASIO_VARIADIC_MOVE_PARAMS(n) \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS_##n
+
+# define BOOST_ASIO_VARIADIC_MOVE_PARAMS_1 \
+ BOOST_ASIO_MOVE_ARG(T1) x1
+# define BOOST_ASIO_VARIADIC_MOVE_PARAMS_2 \
+ BOOST_ASIO_MOVE_ARG(T1) x1, BOOST_ASIO_MOVE_ARG(T2) x2
+# define BOOST_ASIO_VARIADIC_MOVE_PARAMS_3 \
+ BOOST_ASIO_MOVE_ARG(T1) x1, BOOST_ASIO_MOVE_ARG(T2) x2, \
+ BOOST_ASIO_MOVE_ARG(T3) x3
+# define BOOST_ASIO_VARIADIC_MOVE_PARAMS_4 \
+ BOOST_ASIO_MOVE_ARG(T1) x1, BOOST_ASIO_MOVE_ARG(T2) x2, \
+ BOOST_ASIO_MOVE_ARG(T3) x3, BOOST_ASIO_MOVE_ARG(T4) x4
+# define BOOST_ASIO_VARIADIC_MOVE_PARAMS_5 \
+ BOOST_ASIO_MOVE_ARG(T1) x1, BOOST_ASIO_MOVE_ARG(T2) x2, \
+ BOOST_ASIO_MOVE_ARG(T3) x3, BOOST_ASIO_MOVE_ARG(T4) x4, \
+ BOOST_ASIO_MOVE_ARG(T5) x5
+
+# define BOOST_ASIO_VARIADIC_MOVE_ARGS(n) \
+ BOOST_ASIO_VARIADIC_MOVE_ARGS_##n
+
+# define BOOST_ASIO_VARIADIC_MOVE_ARGS_1 \
+ BOOST_ASIO_MOVE_CAST(T1)(x1)
+# define BOOST_ASIO_VARIADIC_MOVE_ARGS_2 \
+ BOOST_ASIO_MOVE_CAST(T1)(x1), BOOST_ASIO_MOVE_CAST(T2)(x2)
+# define BOOST_ASIO_VARIADIC_MOVE_ARGS_3 \
+ BOOST_ASIO_MOVE_CAST(T1)(x1), BOOST_ASIO_MOVE_CAST(T2)(x2), \
+ BOOST_ASIO_MOVE_CAST(T3)(x3)
+# define BOOST_ASIO_VARIADIC_MOVE_ARGS_4 \
+ BOOST_ASIO_MOVE_CAST(T1)(x1), BOOST_ASIO_MOVE_CAST(T2)(x2), \
+ BOOST_ASIO_MOVE_CAST(T3)(x3), BOOST_ASIO_MOVE_CAST(T4)(x4)
+# define BOOST_ASIO_VARIADIC_MOVE_ARGS_5 \
+ BOOST_ASIO_MOVE_CAST(T1)(x1), BOOST_ASIO_MOVE_CAST(T2)(x2), \
+ BOOST_ASIO_MOVE_CAST(T3)(x3), BOOST_ASIO_MOVE_CAST(T4)(x4), \
+ BOOST_ASIO_MOVE_CAST(T5)(x5)
+
+# define BOOST_ASIO_VARIADIC_DECAY(n) \
+ BOOST_ASIO_VARIADIC_DECAY_##n
+
+# define BOOST_ASIO_VARIADIC_DECAY_1 \
+ typename decay<T1>::type
+# define BOOST_ASIO_VARIADIC_DECAY_2 \
+ typename decay<T1>::type, typename decay<T2>::type
+# define BOOST_ASIO_VARIADIC_DECAY_3 \
+ typename decay<T1>::type, typename decay<T2>::type, \
+ typename decay<T3>::type
+# define BOOST_ASIO_VARIADIC_DECAY_4 \
+ typename decay<T1>::type, typename decay<T2>::type, \
+ typename decay<T3>::type, typename decay<T4>::type
+# define BOOST_ASIO_VARIADIC_DECAY_5 \
+ typename decay<T1>::type, typename decay<T2>::type, \
+ typename decay<T3>::type, typename decay<T4>::type, \
+ typename decay<T5>::type
# define BOOST_ASIO_VARIADIC_GENERATE(m) m(1) m(2) m(3) m(4) m(5)
diff --git a/boost/asio/detail/wait_handler.hpp b/boost/asio/detail/wait_handler.hpp
index 440dae1f18..5d520e8fb1 100644
--- a/boost/asio/detail/wait_handler.hpp
+++ b/boost/asio/detail/wait_handler.hpp
@@ -16,12 +16,12 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/wait_op.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -39,17 +39,19 @@ public:
: wait_op(&wait_handler::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(h))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& /*ec*/,
std::size_t /*bytes_transferred*/)
{
// Take ownership of the handler object.
wait_handler* h(static_cast<wait_handler*>(base));
ptr p = { boost::asio::detail::addressof(h->handler_), h, h };
+ handler_work<Handler> w(h->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((h));
+ BOOST_ASIO_HANDLER_COMPLETION((*h));
// 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
@@ -67,7 +69,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/weak_ptr.hpp b/boost/asio/detail/weak_ptr.hpp
deleted file mode 100644
index 1870c0e0e8..0000000000
--- a/boost/asio/detail/weak_ptr.hpp
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// detail/weak_ptr.hpp
-// ~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_DETAIL_WEAK_PTR_HPP
-#define BOOST_ASIO_DETAIL_WEAK_PTR_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-
-#if defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-# include <memory>
-#else // defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-# include <boost/weak_ptr.hpp>
-#endif // defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-
-namespace boost {
-namespace asio {
-namespace detail {
-
-#if defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-using std::weak_ptr;
-#else // defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-using boost::weak_ptr;
-#endif // defined(BOOST_ASIO_HAS_STD_SHARED_PTR)
-
-} // namespace detail
-} // namespace asio
-} // namespace boost
-
-#endif // BOOST_ASIO_DETAIL_WEAK_PTR_HPP
diff --git a/boost/asio/detail/win_event.hpp b/boost/asio/detail/win_event.hpp
index 7a7d54fac6..4c00068010 100644
--- a/boost/asio/detail/win_event.hpp
+++ b/boost/asio/detail/win_event.hpp
@@ -112,6 +112,27 @@ public:
}
}
+ // Timed wait for the event to become signalled.
+ template <typename Lock>
+ bool wait_for_usec(Lock& lock, long usec)
+ {
+ BOOST_ASIO_ASSERT(lock.locked());
+ if ((state_ & 1) == 0)
+ {
+ state_ += 2;
+ lock.unlock();
+ DWORD msec = usec > 0 ? (usec < 1000 ? 1 : usec / 1000) : 0;
+#if defined(BOOST_ASIO_WINDOWS_APP)
+ ::WaitForMultipleObjectsEx(2, events_, false, msec, false);
+#else // defined(BOOST_ASIO_WINDOWS_APP)
+ ::WaitForMultipleObjects(2, events_, false, msec);
+#endif // defined(BOOST_ASIO_WINDOWS_APP)
+ lock.lock();
+ state_ -= 2;
+ }
+ return (state_ & 1) != 0;
+ }
+
private:
HANDLE events_[2];
std::size_t state_;
diff --git a/boost/asio/detail/win_fenced_block.hpp b/boost/asio/detail/win_fenced_block.hpp
index dba1d5355d..c6e5601361 100644
--- a/boost/asio/detail/win_fenced_block.hpp
+++ b/boost/asio/detail/win_fenced_block.hpp
@@ -20,6 +20,7 @@
#if defined(BOOST_ASIO_WINDOWS) && !defined(UNDER_CE)
#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/push_options.hpp>
diff --git a/boost/asio/detail/win_global.hpp b/boost/asio/detail/win_global.hpp
new file mode 100644
index 0000000000..5a43902a7c
--- /dev/null
+++ b/boost/asio/detail/win_global.hpp
@@ -0,0 +1,75 @@
+//
+// detail/win_global.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_GLOBAL_HPP
+#define BOOST_ASIO_DETAIL_WIN_GLOBAL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/static_mutex.hpp>
+#include <boost/asio/detail/tss_ptr.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename T>
+struct win_global_impl
+{
+ // Destructor automatically cleans up the global.
+ ~win_global_impl()
+ {
+ delete ptr_;
+ }
+
+ static win_global_impl instance_;
+ static static_mutex mutex_;
+ static T* ptr_;
+ static tss_ptr<T> tss_ptr_;
+};
+
+template <typename T>
+win_global_impl<T> win_global_impl<T>::instance_ = { 0 };
+
+template <typename T>
+static_mutex win_global_impl<T>::mutex_ = BOOST_ASIO_STATIC_MUTEX_INIT;
+
+template <typename T>
+T* win_global_impl<T>::ptr_ = 0;
+
+template <typename T>
+tss_ptr<T> win_global_impl<T>::tss_ptr_;
+
+template <typename T>
+T& win_global()
+{
+ if (static_cast<T*>(win_global_impl<T>::tss_ptr_) == 0)
+ {
+ win_global_impl<T>::mutex_.init();
+ static_mutex::scoped_lock lock(win_global_impl<T>::mutex_);
+ win_global_impl<T>::ptr_ = new T;
+ win_global_impl<T>::tss_ptr_ = win_global_impl<T>::ptr_;
+ }
+
+ return *win_global_impl<T>::tss_ptr_;
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WIN_GLOBAL_HPP
diff --git a/boost/asio/detail/win_iocp_handle_read_op.hpp b/boost/asio/detail/win_iocp_handle_read_op.hpp
index fda3cc1e77..67d0ccc296 100644
--- a/boost/asio/detail/win_iocp_handle_read_op.hpp
+++ b/boost/asio/detail/win_iocp_handle_read_op.hpp
@@ -21,12 +21,12 @@
#if defined(BOOST_ASIO_HAS_IOCP)
#include <boost/asio/error.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -47,9 +47,10 @@ public:
buffers_(buffers),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& result_ec,
std::size_t bytes_transferred)
{
@@ -58,8 +59,9 @@ public:
// Take ownership of the operation object.
win_iocp_handle_read_op* o(static_cast<win_iocp_handle_read_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
if (owner)
@@ -90,7 +92,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/win_iocp_handle_service.hpp b/boost/asio/detail/win_iocp_handle_service.hpp
index 29f24f90c5..876fb68cb8 100644
--- a/boost/asio/detail/win_iocp_handle_service.hpp
+++ b/boost/asio/detail/win_iocp_handle_service.hpp
@@ -21,16 +21,16 @@
#if defined(BOOST_ASIO_HAS_IOCP)
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/cstdint.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/win_iocp_handle_read_op.hpp>
#include <boost/asio/detail/win_iocp_handle_write_op.hpp>
-#include <boost/asio/detail/win_iocp_io_service.hpp>
+#include <boost/asio/detail/win_iocp_io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -38,7 +38,8 @@ namespace boost {
namespace asio {
namespace detail {
-class win_iocp_handle_service
+class win_iocp_handle_service :
+ public service_base<win_iocp_handle_service>
{
public:
// The native type of a stream handle.
@@ -75,10 +76,10 @@ public:
implementation_type* prev_;
};
- BOOST_ASIO_DECL win_iocp_handle_service(boost::asio::io_service& io_service);
+ BOOST_ASIO_DECL win_iocp_handle_service(boost::asio::io_context& io_context);
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Construct a new handle implementation.
BOOST_ASIO_DECL void construct(implementation_type& impl);
@@ -149,11 +150,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_handle_write_op<ConstBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_write_some"));
+ BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
+ reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some"));
start_write_op(impl, 0,
buffer_sequence_adapter<boost::asio::const_buffer,
@@ -170,11 +171,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_handle_write_op<ConstBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_write_some_at"));
+ BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
+ reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some_at"));
start_write_op(impl, offset,
buffer_sequence_adapter<boost::asio::const_buffer,
@@ -211,11 +212,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_handle_read_op<MutableBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_read_some"));
+ BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
+ reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some"));
start_read_op(impl, 0,
buffer_sequence_adapter<boost::asio::mutable_buffer,
@@ -233,11 +234,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_handle_read_op<MutableBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "handle", &impl, "async_read_some_at"));
+ BOOST_ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,
+ reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some_at"));
start_read_op(impl, offset,
buffer_sequence_adapter<boost::asio::mutable_buffer,
@@ -300,7 +301,7 @@ private:
// The IOCP service used for running asynchronous operations and dispatching
// handlers.
- win_iocp_io_service& iocp_service_;
+ win_iocp_io_context& iocp_service_;
// Mutex to protect access to the linked list of implementations.
mutex mutex_;
diff --git a/boost/asio/detail/win_iocp_handle_write_op.hpp b/boost/asio/detail/win_iocp_handle_write_op.hpp
index a53db910a8..b6b1483265 100644
--- a/boost/asio/detail/win_iocp_handle_write_op.hpp
+++ b/boost/asio/detail/win_iocp_handle_write_op.hpp
@@ -21,12 +21,12 @@
#if defined(BOOST_ASIO_HAS_IOCP)
#include <boost/asio/error.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -46,16 +46,18 @@ public:
buffers_(buffers),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& ec, std::size_t bytes_transferred)
{
// Take ownership of the operation object.
win_iocp_handle_write_op* o(static_cast<win_iocp_handle_write_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
if (owner)
@@ -82,7 +84,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/win_iocp_io_service.hpp b/boost/asio/detail/win_iocp_io_context.hpp
index 0abb9fe89a..c53b9eb9c3 100644
--- a/boost/asio/detail/win_iocp_io_service.hpp
+++ b/boost/asio/detail/win_iocp_io_context.hpp
@@ -1,5 +1,5 @@
//
-// detail/win_iocp_io_service.hpp
+// detail/win_iocp_io_context.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
@@ -8,8 +8,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP
-#define BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP
+#ifndef BOOST_ASIO_DETAIL_WIN_IOCP_IO_CONTEXT_HPP
+#define BOOST_ASIO_DETAIL_WIN_IOCP_IO_CONTEXT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
@@ -19,19 +19,19 @@
#if defined(BOOST_ASIO_HAS_IOCP)
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/call_stack.hpp>
#include <boost/asio/detail/limits.hpp>
#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/op_queue.hpp>
#include <boost/asio/detail/scoped_ptr.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/thread.hpp>
+#include <boost/asio/detail/thread_context.hpp>
#include <boost/asio/detail/timer_queue_base.hpp>
#include <boost/asio/detail/timer_queue_set.hpp>
#include <boost/asio/detail/wait_op.hpp>
#include <boost/asio/detail/win_iocp_operation.hpp>
#include <boost/asio/detail/win_iocp_thread_info.hpp>
+#include <boost/asio/execution_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -41,18 +41,18 @@ namespace detail {
class wait_op;
-class win_iocp_io_service
- : public boost::asio::detail::service_base<win_iocp_io_service>
+class win_iocp_io_context
+ : public execution_context_service_base<win_iocp_io_context>,
+ public thread_context
{
public:
-
// Constructor. Specifies a concurrency hint that is passed through to the
// underlying I/O completion port.
- BOOST_ASIO_DECL win_iocp_io_service(boost::asio::io_service& io_service,
- size_t concurrency_hint = 0);
+ BOOST_ASIO_DECL win_iocp_io_context(boost::asio::execution_context& ctx,
+ int concurrency_hint = -1);
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Initialise the task. Nothing to do here.
void init_task()
@@ -69,6 +69,9 @@ public:
// Run until stopped or one operation is performed.
BOOST_ASIO_DECL size_t run_one(boost::system::error_code& ec);
+ // Run until timeout, interrupted, or one operation is performed.
+ BOOST_ASIO_DECL size_t wait_one(long usec, boost::system::error_code& ec);
+
// Poll for operations without blocking.
BOOST_ASIO_DECL size_t poll(boost::system::error_code& ec);
@@ -78,14 +81,14 @@ public:
// Stop the event processing loop.
BOOST_ASIO_DECL void stop();
- // Determine whether the io_service is stopped.
+ // Determine whether the io_context is stopped.
bool stopped() const
{
return ::InterlockedExchangeAdd(&stopped_, 0) != 0;
}
- // Reset in preparation for a subsequent run invocation.
- void reset()
+ // Restart in preparation for a subsequent run invocation.
+ void restart()
{
::InterlockedExchange(&stopped_, 0);
}
@@ -109,14 +112,6 @@ public:
return thread_call_stack::contains(this) != 0;
}
- // Request invocation of the given handler.
- template <typename Handler>
- void dispatch(Handler& handler);
-
- // Request invocation of the given handler and return immediately.
- template <typename Handler>
- void post(Handler& handler);
-
// Request invocation of the given operation and return immediately. Assumes
// that work_started() has not yet been called for the operation.
void post_immediate_completion(win_iocp_operation* op, bool)
@@ -150,8 +145,15 @@ public:
post_deferred_completion(op);
}
- // Process unfinished operations as part of a shutdown_service operation.
- // Assumes that work_started() was previously called for the operations.
+ // Enqueue the given operation following a failed attempt to dispatch the
+ // operation for immediate invocation.
+ void do_dispatch(operation* op)
+ {
+ post_immediate_completion(op, false);
+ }
+
+ // Process unfinished operations as part of a shutdown operation. Assumes
+ // that work_started() was previously called for the operations.
BOOST_ASIO_DECL void abandon_operations(op_queue<operation>& ops);
// Called after starting an overlapped I/O operation that did not complete
@@ -193,6 +195,18 @@ public:
typename timer_queue<Time_Traits>::per_timer_data& timer,
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
+ // 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& to,
+ typename timer_queue<Time_Traits>::per_timer_data& from);
+
+ // Get the concurrency hint that was used to initialise the io_context.
+ int concurrency_hint() const
+ {
+ return concurrency_hint_;
+ }
+
private:
#if defined(WINVER) && (WINVER < 0x0500)
typedef DWORD dword_ptr_t;
@@ -205,7 +219,7 @@ private:
// Dequeues at most one operation from the I/O completion port, and then
// executes it. Returns the number of operations that were dequeued (i.e.
// either 0 or 1).
- BOOST_ASIO_DECL size_t do_one(bool block, boost::system::error_code& ec);
+ BOOST_ASIO_DECL size_t do_one(DWORD msec, boost::system::error_code& ec);
// Helper to calculate the GetQueuedCompletionStatus timeout.
BOOST_ASIO_DECL static DWORD get_gqcs_timeout();
@@ -296,9 +310,8 @@ private:
// The operations that are ready to dispatch.
op_queue<win_iocp_operation> completed_ops_;
- // Per-thread call stack to track the state of each thread in the io_service.
- typedef call_stack<win_iocp_io_service,
- win_iocp_thread_info> thread_call_stack;
+ // The concurrency hint used to initialise the io_context.
+ const int concurrency_hint_;
};
} // namespace detail
@@ -307,11 +320,11 @@ private:
#include <boost/asio/detail/pop_options.hpp>
-#include <boost/asio/detail/impl/win_iocp_io_service.hpp>
+#include <boost/asio/detail/impl/win_iocp_io_context.hpp>
#if defined(BOOST_ASIO_HEADER_ONLY)
-# include <boost/asio/detail/impl/win_iocp_io_service.ipp>
+# include <boost/asio/detail/impl/win_iocp_io_context.ipp>
#endif // defined(BOOST_ASIO_HEADER_ONLY)
#endif // defined(BOOST_ASIO_HAS_IOCP)
-#endif // BOOST_ASIO_DETAIL_WIN_IOCP_IO_SERVICE_HPP
+#endif // BOOST_ASIO_DETAIL_WIN_IOCP_IO_CONTEXT_HPP
diff --git a/boost/asio/detail/win_iocp_null_buffers_op.hpp b/boost/asio/detail/win_iocp_null_buffers_op.hpp
index 905d7a664e..318331a125 100644
--- a/boost/asio/detail/win_iocp_null_buffers_op.hpp
+++ b/boost/asio/detail/win_iocp_null_buffers_op.hpp
@@ -19,12 +19,12 @@
#if defined(BOOST_ASIO_HAS_IOCP)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/error.hpp>
@@ -48,14 +48,15 @@ public:
cancel_token_(cancel_token),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static bool do_perform(reactor_op*)
+ static status do_perform(reactor_op*)
{
- return true;
+ return done;
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& result_ec,
std::size_t bytes_transferred)
{
@@ -64,8 +65,9 @@ public:
// Take ownership of the operation object.
win_iocp_null_buffers_op* o(static_cast<win_iocp_null_buffers_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// The reactor may have stored a result in the operation object.
if (o->ec_)
@@ -100,7 +102,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/win_iocp_operation.hpp b/boost/asio/detail/win_iocp_operation.hpp
index 232930344b..fcb79a933b 100644
--- a/boost/asio/detail/win_iocp_operation.hpp
+++ b/boost/asio/detail/win_iocp_operation.hpp
@@ -30,7 +30,7 @@ namespace boost {
namespace asio {
namespace detail {
-class win_iocp_io_service;
+class win_iocp_io_context;
// Base class for all operations. A function pointer is used instead of virtual
// functions to avoid the associated overhead.
@@ -39,11 +39,12 @@ class win_iocp_operation
BOOST_ASIO_ALSO_INHERIT_TRACKED_HANDLER
{
public:
- void complete(win_iocp_io_service& owner,
- const boost::system::error_code& ec,
+ typedef win_iocp_operation operation_type;
+
+ void complete(void* owner, const boost::system::error_code& ec,
std::size_t bytes_transferred)
{
- func_(&owner, this, ec, bytes_transferred);
+ func_(owner, this, ec, bytes_transferred);
}
void destroy()
@@ -53,7 +54,7 @@ public:
protected:
typedef void (*func_type)(
- win_iocp_io_service*, win_iocp_operation*,
+ void*, win_iocp_operation*,
const boost::system::error_code&, std::size_t);
win_iocp_operation(func_type func)
@@ -80,7 +81,7 @@ protected:
private:
friend class op_queue_access;
- friend class win_iocp_io_service;
+ friend class win_iocp_io_context;
win_iocp_operation* next_;
func_type func_;
long ready_;
diff --git a/boost/asio/detail/win_iocp_overlapped_op.hpp b/boost/asio/detail/win_iocp_overlapped_op.hpp
index 6d0e4bfcc2..4b26db3f43 100644
--- a/boost/asio/detail/win_iocp_overlapped_op.hpp
+++ b/boost/asio/detail/win_iocp_overlapped_op.hpp
@@ -20,11 +20,11 @@
#if defined(BOOST_ASIO_HAS_IOCP)
#include <boost/asio/error.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -43,16 +43,18 @@ public:
: operation(&win_iocp_overlapped_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& ec, std::size_t bytes_transferred)
{
// Take ownership of the operation object.
win_iocp_overlapped_op* o(static_cast<win_iocp_overlapped_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -70,7 +72,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/win_iocp_overlapped_ptr.hpp b/boost/asio/detail/win_iocp_overlapped_ptr.hpp
index 5d252c6fb1..fc51fd6c59 100644
--- a/boost/asio/detail/win_iocp_overlapped_ptr.hpp
+++ b/boost/asio/detail/win_iocp_overlapped_ptr.hpp
@@ -19,12 +19,12 @@
#if defined(BOOST_ASIO_HAS_IOCP)
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/win_iocp_overlapped_op.hpp>
-#include <boost/asio/detail/win_iocp_io_service.hpp>
+#include <boost/asio/detail/win_iocp_io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -47,11 +47,11 @@ public:
// Construct an win_iocp_overlapped_ptr to contain the specified handler.
template <typename Handler>
explicit win_iocp_overlapped_ptr(
- boost::asio::io_service& io_service, BOOST_ASIO_MOVE_ARG(Handler) handler)
+ boost::asio::io_context& io_context, BOOST_ASIO_MOVE_ARG(Handler) handler)
: ptr_(0),
iocp_service_(0)
{
- this->reset(io_service, BOOST_ASIO_MOVE_CAST(Handler)(handler));
+ this->reset(io_context, BOOST_ASIO_MOVE_CAST(Handler)(handler));
}
// Destructor automatically frees the OVERLAPPED object unless released.
@@ -75,22 +75,21 @@ public:
// Reset to contain the specified handler, freeing any current OVERLAPPED
// object.
template <typename Handler>
- void reset(boost::asio::io_service& io_service, Handler handler)
+ void reset(boost::asio::io_context& io_context, Handler handler)
{
typedef win_iocp_overlapped_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "io_service",
- &io_service.impl_, "overlapped"));
+ BOOST_ASIO_HANDLER_CREATION((io_context, *p.p,
+ "io_context", &io_context.impl_, 0, "overlapped"));
- io_service.impl_.work_started();
+ io_context.impl_.work_started();
reset();
ptr_ = p.p;
p.v = p.p = 0;
- iocp_service_ = &io_service.impl_;
+ iocp_service_ = &io_context.impl_;
}
// Get the contained OVERLAPPED object.
@@ -132,7 +131,7 @@ public:
private:
win_iocp_operation* ptr_;
- win_iocp_io_service* iocp_service_;
+ win_iocp_io_context* iocp_service_;
};
} // namespace detail
diff --git a/boost/asio/detail/win_iocp_serial_port_service.hpp b/boost/asio/detail/win_iocp_serial_port_service.hpp
index 6b21f96535..4b641f0c73 100644
--- a/boost/asio/detail/win_iocp_serial_port_service.hpp
+++ b/boost/asio/detail/win_iocp_serial_port_service.hpp
@@ -22,7 +22,7 @@
#include <string>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/win_iocp_handle_service.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -32,7 +32,8 @@ namespace asio {
namespace detail {
// Extend win_iocp_handle_service to provide serial port support.
-class win_iocp_serial_port_service
+class win_iocp_serial_port_service :
+ public service_base<win_iocp_serial_port_service>
{
public:
// The native type of a serial port.
@@ -43,10 +44,10 @@ public:
// Constructor.
BOOST_ASIO_DECL win_iocp_serial_port_service(
- boost::asio::io_service& io_service);
+ boost::asio::io_context& io_context);
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Construct a new serial port implementation.
void construct(implementation_type& impl)
@@ -185,8 +186,8 @@ private:
static boost::system::error_code store_option(const void* option,
::DCB& storage, boost::system::error_code& ec)
{
- return static_cast<const SettableSerialPortOption*>(option)->store(
- storage, ec);
+ static_cast<const SettableSerialPortOption*>(option)->store(storage, ec);
+ return ec;
}
// Helper function to set a serial port option.
@@ -203,7 +204,8 @@ private:
static boost::system::error_code load_option(void* option,
const ::DCB& storage, boost::system::error_code& ec)
{
- return static_cast<GettableSerialPortOption*>(option)->load(storage, ec);
+ static_cast<GettableSerialPortOption*>(option)->load(storage, ec);
+ return ec;
}
// Helper function to get a serial port option.
diff --git a/boost/asio/detail/win_iocp_socket_accept_op.hpp b/boost/asio/detail/win_iocp_socket_accept_op.hpp
index d296103c54..f05be5465d 100644
--- a/boost/asio/detail/win_iocp_socket_accept_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_accept_op.hpp
@@ -19,12 +19,12 @@
#if defined(BOOST_ASIO_HAS_IOCP)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/win_iocp_socket_service_base.hpp>
@@ -55,6 +55,7 @@ public:
enable_connection_aborted_(enable_connection_aborted),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
socket_holder& new_socket()
@@ -72,7 +73,7 @@ public:
return sizeof(sockaddr_storage_type) + 16;
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& result_ec,
std::size_t /*bytes_transferred*/)
{
@@ -81,6 +82,7 @@ public:
// Take ownership of the operation object.
win_iocp_socket_accept_op* o(static_cast<win_iocp_socket_accept_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
if (owner)
{
@@ -121,7 +123,7 @@ public:
*o->peer_endpoint_ = peer_endpoint;
}
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -139,7 +141,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
@@ -156,6 +158,136 @@ private:
Handler handler_;
};
+#if defined(BOOST_ASIO_HAS_MOVE)
+
+template <typename Protocol, typename Handler>
+class win_iocp_socket_move_accept_op : public operation
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_move_accept_op);
+
+ win_iocp_socket_move_accept_op(
+ win_iocp_socket_service_base& socket_service, socket_type socket,
+ const Protocol& protocol, boost::asio::io_context& peer_io_context,
+ typename Protocol::endpoint* peer_endpoint,
+ bool enable_connection_aborted, Handler& handler)
+ : operation(&win_iocp_socket_move_accept_op::do_complete),
+ socket_service_(socket_service),
+ socket_(socket),
+ peer_(peer_io_context),
+ protocol_(protocol),
+ peer_endpoint_(peer_endpoint),
+ enable_connection_aborted_(enable_connection_aborted),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ handler_work<Handler>::start(handler_);
+ }
+
+ socket_holder& new_socket()
+ {
+ return new_socket_;
+ }
+
+ void* output_buffer()
+ {
+ return output_buffer_;
+ }
+
+ DWORD address_length()
+ {
+ return sizeof(sockaddr_storage_type) + 16;
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& result_ec,
+ std::size_t /*bytes_transferred*/)
+ {
+ boost::system::error_code ec(result_ec);
+
+ // Take ownership of the operation object.
+ win_iocp_socket_move_accept_op* o(
+ static_cast<win_iocp_socket_move_accept_op*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
+
+ if (owner)
+ {
+ typename Protocol::endpoint peer_endpoint;
+ std::size_t addr_len = peer_endpoint.capacity();
+ socket_ops::complete_iocp_accept(o->socket_,
+ o->output_buffer(), o->address_length(),
+ peer_endpoint.data(), &addr_len,
+ o->new_socket_.get(), ec);
+
+ // Restart the accept operation if we got the connection_aborted error
+ // and the enable_connection_aborted socket option is not set.
+ if (ec == boost::asio::error::connection_aborted
+ && !o->enable_connection_aborted_)
+ {
+ o->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);
+ p.v = p.p = 0;
+ return;
+ }
+
+ // If the socket was successfully accepted, transfer ownership of the
+ // socket to the peer object.
+ if (!ec)
+ {
+ o->peer_.assign(o->protocol_,
+ typename Protocol::socket::native_handle_type(
+ o->new_socket_.get(), peer_endpoint), ec);
+ if (!ec)
+ o->new_socket_.release();
+ }
+
+ // Pass endpoint back to caller.
+ if (o->peer_endpoint_)
+ *o->peer_endpoint_ = peer_endpoint;
+ }
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // 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,
+ boost::system::error_code, typename Protocol::socket>
+ handler(0, BOOST_ASIO_MOVE_CAST(Handler)(o->handler_), ec,
+ BOOST_ASIO_MOVE_CAST(typename Protocol::socket)(o->peer_));
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ win_iocp_socket_service_base& socket_service_;
+ socket_type socket_;
+ socket_holder new_socket_;
+ typename Protocol::socket peer_;
+ Protocol protocol_;
+ typename Protocol::endpoint* peer_endpoint_;
+ unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];
+ bool enable_connection_aborted_;
+ Handler handler_;
+};
+
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
} // namespace detail
} // namespace asio
} // namespace boost
diff --git a/boost/asio/detail/win_iocp_socket_connect_op.hpp b/boost/asio/detail/win_iocp_socket_connect_op.hpp
index e987c6b6c4..829597ae9c 100644
--- a/boost/asio/detail/win_iocp_socket_connect_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_connect_op.hpp
@@ -19,11 +19,11 @@
#if defined(BOOST_ASIO_HAS_IOCP)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/reactor_op.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/error.hpp>
@@ -44,12 +44,13 @@ public:
{
}
- static bool do_perform(reactor_op* base)
+ static status do_perform(reactor_op* base)
{
win_iocp_socket_connect_op_base* o(
static_cast<win_iocp_socket_connect_op_base*>(base));
- return socket_ops::non_blocking_connect(o->socket_, o->ec_);
+ return socket_ops::non_blocking_connect(
+ o->socket_, o->ec_) ? done : not_done;
}
socket_type socket_;
@@ -67,9 +68,10 @@ public:
&win_iocp_socket_connect_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& result_ec,
std::size_t /*bytes_transferred*/)
{
@@ -79,6 +81,7 @@ public:
win_iocp_socket_connect_op* o(
static_cast<win_iocp_socket_connect_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
if (owner)
{
@@ -88,7 +91,7 @@ public:
ec = o->ec_;
}
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -106,7 +109,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/win_iocp_socket_recv_op.hpp b/boost/asio/detail/win_iocp_socket_recv_op.hpp
index 4202822d17..46f5dcd3f5 100644
--- a/boost/asio/detail/win_iocp_socket_recv_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_recv_op.hpp
@@ -19,12 +19,12 @@
#if defined(BOOST_ASIO_HAS_IOCP)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/error.hpp>
@@ -50,9 +50,10 @@ public:
buffers_(buffers),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& result_ec,
std::size_t bytes_transferred)
{
@@ -61,8 +62,9 @@ public:
// Take ownership of the operation object.
win_iocp_socket_recv_op* o(static_cast<win_iocp_socket_recv_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
// Check whether buffers are still valid.
@@ -94,7 +96,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp b/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp
index 21ca4fb331..b9437c3a60 100644
--- a/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_recvfrom_op.hpp
@@ -19,12 +19,12 @@
#if defined(BOOST_ASIO_HAS_IOCP)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/error.hpp>
@@ -51,6 +51,7 @@ public:
buffers_(buffers),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
int& endpoint_size()
@@ -58,7 +59,7 @@ public:
return endpoint_size_;
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& result_ec,
std::size_t bytes_transferred)
{
@@ -68,8 +69,9 @@ public:
win_iocp_socket_recvfrom_op* o(
static_cast<win_iocp_socket_recvfrom_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
// Check whether buffers are still valid.
@@ -101,7 +103,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp b/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp
index 5179bb2945..51747c55e8 100644
--- a/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_recvmsg_op.hpp
@@ -19,12 +19,12 @@
#if defined(BOOST_ASIO_HAS_IOCP)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/error.hpp>
@@ -52,9 +52,10 @@ public:
out_flags_(out_flags),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& result_ec,
std::size_t bytes_transferred)
{
@@ -64,8 +65,9 @@ public:
win_iocp_socket_recvmsg_op* o(
static_cast<win_iocp_socket_recvmsg_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
// Check whether buffers are still valid.
@@ -95,7 +97,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/win_iocp_socket_send_op.hpp b/boost/asio/detail/win_iocp_socket_send_op.hpp
index c9abc0e664..48951c2508 100644
--- a/boost/asio/detail/win_iocp_socket_send_op.hpp
+++ b/boost/asio/detail/win_iocp_socket_send_op.hpp
@@ -19,12 +19,12 @@
#if defined(BOOST_ASIO_HAS_IOCP)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/operation.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/error.hpp>
@@ -48,9 +48,10 @@ public:
buffers_(buffers),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code& result_ec,
std::size_t bytes_transferred)
{
@@ -59,8 +60,9 @@ public:
// Take ownership of the operation object.
win_iocp_socket_send_op* o(static_cast<win_iocp_socket_send_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
// Check whether buffers are still valid.
@@ -89,7 +91,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/win_iocp_socket_service.hpp b/boost/asio/detail/win_iocp_socket_service.hpp
index 179798c8d9..ed1cd1edd5 100644
--- a/boost/asio/detail/win_iocp_socket_service.hpp
+++ b/boost/asio/detail/win_iocp_socket_service.hpp
@@ -21,22 +21,22 @@
#include <cstring>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/socket_base.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/operation.hpp>
-#include <boost/asio/detail/reactor.hpp>
#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/select_reactor.hpp>
#include <boost/asio/detail/socket_holder.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/win_iocp_io_service.hpp>
+#include <boost/asio/detail/win_iocp_io_context.hpp>
#include <boost/asio/detail/win_iocp_null_buffers_op.hpp>
#include <boost/asio/detail/win_iocp_socket_accept_op.hpp>
#include <boost/asio/detail/win_iocp_socket_connect_op.hpp>
@@ -51,7 +51,9 @@ namespace asio {
namespace detail {
template <typename Protocol>
-class win_iocp_socket_service : public win_iocp_socket_service_base
+class win_iocp_socket_service :
+ public service_base<win_iocp_socket_service<Protocol> >,
+ public win_iocp_socket_service_base
{
public:
// The protocol type.
@@ -128,11 +130,18 @@ public:
};
// Constructor.
- win_iocp_socket_service(boost::asio::io_service& io_service)
- : win_iocp_socket_service_base(io_service)
+ win_iocp_socket_service(boost::asio::io_context& io_context)
+ : service_base<win_iocp_socket_service<Protocol> >(io_context),
+ win_iocp_socket_service_base(io_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)
@@ -279,6 +288,14 @@ public:
return endpoint;
}
+ // Disable sends or receives on the socket.
+ boost::system::error_code shutdown(base_implementation_type& impl,
+ socket_base::shutdown_type what, boost::system::error_code& ec)
+ {
+ socket_ops::shutdown(impl.socket_, what, ec);
+ return ec;
+ }
+
// Send a datagram to the specified endpoint. Returns the number of bytes
// sent.
template <typename ConstBufferSequence>
@@ -300,7 +317,7 @@ public:
boost::system::error_code& ec)
{
// Wait for socket to become ready.
- socket_ops::poll_write(impl.socket_, impl.state_, ec);
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
return 0;
}
@@ -315,11 +332,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send_to"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_send_to"));
buffer_sequence_adapter<boost::asio::const_buffer,
ConstBufferSequence> bufs(buffers);
@@ -338,14 +355,13 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.cancel_token_, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_send_to(null_buffers)"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_send_to(null_buffers)"));
- start_reactor_op(impl, reactor::write_op, p.p);
+ start_reactor_op(impl, select_reactor::write_op, p.p);
p.v = p.p = 0;
}
@@ -377,7 +393,7 @@ public:
socket_base::message_flags, boost::system::error_code& ec)
{
// Wait for socket to become ready.
- socket_ops::poll_read(impl.socket_, impl.state_, ec);
+ 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();
@@ -397,11 +413,11 @@ public:
typedef win_iocp_socket_recvfrom_op<
MutableBufferSequence, endpoint_type, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(sender_endp, impl.cancel_token_, buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive_from"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_receive_from"));
buffer_sequence_adapter<boost::asio::mutable_buffer,
MutableBufferSequence> bufs(buffers);
@@ -420,12 +436,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.cancel_token_, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl,
- "async_receive_from(null_buffers)"));
+ BOOST_ASIO_HANDLER_CREATION((io_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();
@@ -456,13 +471,42 @@ public:
{
if (peer_endpoint)
peer_endpoint->resize(addr_len);
- if (!peer.assign(impl.protocol_, new_socket.get(), ec))
+ peer.assign(impl.protocol_, new_socket.get(), ec);
+ if (!ec)
new_socket.release();
}
return ec;
}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ // Accept a new connection.
+ typename Protocol::socket accept(implementation_type& impl,
+ io_context* peer_io_context, endpoint_type* peer_endpoint,
+ boost::system::error_code& ec)
+ {
+ typename Protocol::socket peer(
+ peer_io_context ? *peer_io_context : io_context_);
+
+ 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();
+ }
+
+ return peer;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
// 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>
@@ -472,14 +516,14 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_socket_accept_op<Socket, protocol_type, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ 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_,
peer_endpoint, enable_connection_aborted, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_accept"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_accept"));
start_accept_op(impl, peer.is_open(), p.p->new_socket(),
impl.protocol_.family(), impl.protocol_.type(),
@@ -488,6 +532,35 @@ public:
p.v = p.p = 0;
}
+#if defined(BOOST_ASIO_HAS_MOVE)
+ // Start an asynchronous accept. The peer and peer_endpoint objects
+ // must be valid until the accept's handler is invoked.
+ template <typename Handler>
+ void async_accept(implementation_type& impl,
+ boost::asio::io_context* peer_io_context,
+ endpoint_type* peer_endpoint, Handler& handler)
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef win_iocp_socket_move_accept_op<protocol_type, Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ 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_,
+ peer_io_context ? *peer_io_context : io_context_,
+ peer_endpoint, enable_connection_aborted, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_accept"));
+
+ 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.v = p.p = 0;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
// Connect the socket to the specified endpoint.
boost::system::error_code connect(implementation_type& impl,
const endpoint_type& peer_endpoint, boost::system::error_code& ec)
@@ -505,11 +578,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_socket_connect_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.socket_, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
+ BOOST_ASIO_HANDLER_CREATION((io_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);
diff --git a/boost/asio/detail/win_iocp_socket_service_base.hpp b/boost/asio/detail/win_iocp_socket_service_base.hpp
index 8ecf219598..2af1546712 100644
--- a/boost/asio/detail/win_iocp_socket_service_base.hpp
+++ b/boost/asio/detail/win_iocp_socket_service_base.hpp
@@ -20,27 +20,28 @@
#if defined(BOOST_ASIO_HAS_IOCP)
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/socket_base.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/mutex.hpp>
#include <boost/asio/detail/operation.hpp>
-#include <boost/asio/detail/reactor.hpp>
#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/select_reactor.hpp>
#include <boost/asio/detail/socket_holder.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/socket_types.hpp>
-#include <boost/asio/detail/win_iocp_io_service.hpp>
+#include <boost/asio/detail/win_iocp_io_context.hpp>
#include <boost/asio/detail/win_iocp_null_buffers_op.hpp>
#include <boost/asio/detail/win_iocp_socket_connect_op.hpp>
#include <boost/asio/detail/win_iocp_socket_send_op.hpp>
#include <boost/asio/detail/win_iocp_socket_recv_op.hpp>
#include <boost/asio/detail/win_iocp_socket_recvmsg_op.hpp>
+#include <boost/asio/detail/win_iocp_wait_op.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -69,7 +70,7 @@ public:
socket_ops::shared_cancel_token_type cancel_token_;
// Per-descriptor data used by the reactor.
- reactor::per_descriptor_data reactor_data_;
+ select_reactor::per_descriptor_data reactor_data_;
#if defined(BOOST_ASIO_ENABLE_CANCELIO)
// The ID of the thread from which it is safe to cancel asynchronous
@@ -86,10 +87,10 @@ public:
// Constructor.
BOOST_ASIO_DECL win_iocp_socket_service_base(
- boost::asio::io_service& io_service);
+ boost::asio::io_context& io_context);
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void base_shutdown();
// Construct a new socket implementation.
BOOST_ASIO_DECL void construct(base_implementation_type& impl);
@@ -116,6 +117,10 @@ public:
BOOST_ASIO_DECL boost::system::error_code close(
base_implementation_type& impl, boost::system::error_code& ec);
+ // Release ownership of the socket.
+ BOOST_ASIO_DECL socket_type release(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
// Cancel all operations associated with the socket.
BOOST_ASIO_DECL boost::system::error_code cancel(
base_implementation_type& impl, boost::system::error_code& ec);
@@ -180,14 +185,68 @@ public:
return ec;
}
- // Disable sends or receives on the socket.
- boost::system::error_code shutdown(base_implementation_type& impl,
- socket_base::shutdown_type what, boost::system::error_code& ec)
+ // Wait for the socket to become ready to read, ready to write, or to have
+ // pending error conditions.
+ boost::system::error_code wait(base_implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
{
- socket_ops::shutdown(impl.socket_, what, 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 = boost::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>
+ void async_wait(base_implementation_type& impl,
+ socket_base::wait_type w, Handler& handler)
+ {
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef win_iocp_wait_op<Handler> op;
+ typename op::ptr p = { boost::asio::detail::addressof(handler),
+ op::ptr::allocate(handler), 0 };
+ p.p = new (p.v) op(impl.cancel_token_, handler);
+
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_wait"));
+
+ switch (w)
+ {
+ case socket_base::wait_read:
+ start_null_buffers_receive_op(impl, 0, p.p);
+ break;
+ case socket_base::wait_write:
+ start_reactor_op(impl, select_reactor::write_op, p.p);
+ break;
+ case socket_base::wait_error:
+ start_reactor_op(impl, select_reactor::except_op, p.p);
+ break;
+ default:
+ p.p->ec_ = boost::asio::error::invalid_argument;
+ iocp_service_.post_immediate_completion(p.p, is_continuation);
+ break;
+ }
+
+ p.v = p.p = 0;
+ }
+
// Send the given data to the peer. Returns the number of bytes sent.
template <typename ConstBufferSequence>
size_t send(base_implementation_type& impl,
@@ -206,7 +265,7 @@ public:
socket_base::message_flags, boost::system::error_code& ec)
{
// Wait for socket to become ready.
- socket_ops::poll_write(impl.socket_, impl.state_, ec);
+ socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);
return 0;
}
@@ -221,11 +280,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_socket_send_op<ConstBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.cancel_token_, buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_send"));
buffer_sequence_adapter<boost::asio::const_buffer,
ConstBufferSequence> bufs(buffers);
@@ -244,14 +303,13 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.cancel_token_, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_send(null_buffers)"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_send(null_buffers)"));
- start_reactor_op(impl, reactor::write_op, p.p);
+ start_reactor_op(impl, select_reactor::write_op, p.p);
p.v = p.p = 0;
}
@@ -273,7 +331,7 @@ public:
socket_base::message_flags, boost::system::error_code& ec)
{
// Wait for socket to become ready.
- socket_ops::poll_read(impl.socket_, impl.state_, ec);
+ socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);
return 0;
}
@@ -288,11 +346,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_socket_recv_op<MutableBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.state_, impl.cancel_token_, buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_receive"));
buffer_sequence_adapter<boost::asio::mutable_buffer,
MutableBufferSequence> bufs(buffers);
@@ -311,12 +369,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.cancel_token_, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_receive(null_buffers)"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_receive(null_buffers)"));
start_null_buffers_receive_op(impl, flags, p.p);
p.v = p.p = 0;
@@ -343,7 +400,7 @@ public:
socket_base::message_flags& out_flags, boost::system::error_code& ec)
{
// Wait for socket to become ready.
- socket_ops::poll_read(impl.socket_, impl.state_, ec);
+ 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.
@@ -362,12 +419,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_socket_recvmsg_op<MutableBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.cancel_token_, buffers, out_flags, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket",
- &impl, "async_receive_with_flags"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_receive_with_flags"));
buffer_sequence_adapter<boost::asio::mutable_buffer,
MutableBufferSequence> bufs(buffers);
@@ -385,12 +441,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef win_iocp_null_buffers_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(impl.cancel_token_, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl,
- "async_receive_with_flags(null_buffers)"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_, *p.p, "socket",
+ &impl, impl.socket_, "async_receive_with_flags(null_buffers)"));
// Reset out_flags since it can be given no sensible value at this time.
out_flags = 0;
@@ -464,9 +519,9 @@ protected:
base_implementation_type& impl);
// Helper function to get the reactor. If no reactor has been created yet, a
- // new one is obtained from the io_service and a pointer to it is cached in
+ // new one is obtained from the io_context and a pointer to it is cached in
// this service.
- BOOST_ASIO_DECL reactor& get_reactor();
+ BOOST_ASIO_DECL select_reactor& get_reactor();
// The type of a ConnectEx function pointer, as old SDKs may not provide it.
typedef BOOL (PASCAL *connect_ex_fn)(SOCKET,
@@ -478,6 +533,15 @@ protected:
BOOST_ASIO_DECL connect_ex_fn get_connect_ex(
base_implementation_type& impl, int type);
+ // 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.
+ BOOST_ASIO_DECL nt_set_info_fn get_nt_set_info();
+
// Helper function to emulate InterlockedCompareExchangePointer functionality
// for:
// - very old Platform SDKs; and
@@ -490,20 +554,23 @@ protected:
// - platform SDKs where MSVC's /Wp64 option causes spurious warnings.
BOOST_ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val);
- // The io_service used to obtain the reactor, if required.
- boost::asio::io_service& io_service_;
+ // The io_context used to obtain the reactor, if required.
+ boost::asio::io_context& io_context_;
// The IOCP service used for running asynchronous operations and dispatching
// handlers.
- win_iocp_io_service& iocp_service_;
+ win_iocp_io_context& iocp_service_;
// The reactor used for performing connect operations. This object is created
// only if needed.
- reactor* reactor_;
+ select_reactor* reactor_;
// Pointer to ConnectEx implementation.
void* connect_ex_;
+ // Pointer to NtSetInformationFile implementation.
+ void* nt_set_info_;
+
// Mutex to protect access to the linked list of implementations.
boost::asio::detail::mutex mutex_;
diff --git a/boost/asio/detail/win_iocp_wait_op.hpp b/boost/asio/detail/win_iocp_wait_op.hpp
new file mode 100644
index 0000000000..c5bc4a273f
--- /dev/null
+++ b/boost/asio/detail/win_iocp_wait_op.hpp
@@ -0,0 +1,123 @@
+//
+// detail/win_iocp_wait_op.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WIN_IOCP_WAIT_OP_HPP
+#define BOOST_ASIO_DETAIL_WIN_IOCP_WAIT_OP_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+
+#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/reactor_op.hpp>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/error.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class win_iocp_wait_op : public reactor_op
+{
+public:
+ BOOST_ASIO_DEFINE_HANDLER_PTR(win_iocp_wait_op);
+
+ win_iocp_wait_op(socket_ops::weak_cancel_token_type cancel_token,
+ Handler& handler)
+ : reactor_op(&win_iocp_wait_op::do_perform,
+ &win_iocp_wait_op::do_complete),
+ cancel_token_(cancel_token),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ handler_work<Handler>::start(handler_);
+ }
+
+ static status do_perform(reactor_op*)
+ {
+ return done;
+ }
+
+ static void do_complete(void* owner, operation* base,
+ const boost::system::error_code& result_ec,
+ std::size_t /*bytes_transferred*/)
+ {
+ boost::system::error_code ec(result_ec);
+
+ // Take ownership of the operation object.
+ win_iocp_wait_op* o(static_cast<win_iocp_wait_op*>(base));
+ ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
+
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
+
+ // The reactor may have stored a result in the operation object.
+ if (o->ec_)
+ ec = o->ec_;
+
+ // Map non-portable errors to their portable counterparts.
+ if (ec.value() == ERROR_NETNAME_DELETED)
+ {
+ if (o->cancel_token_.expired())
+ ec = boost::asio::error::operation_aborted;
+ else
+ ec = boost::asio::error::connection_reset;
+ }
+ else if (ec.value() == ERROR_PORT_UNREACHABLE)
+ {
+ ec = boost::asio::error::connection_refused;
+ }
+
+ // 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, boost::system::error_code>
+ handler(o->handler_, ec);
+ p.h = boost::asio::detail::addressof(handler.handler_);
+ p.reset();
+
+ // Make the upcall if required.
+ if (owner)
+ {
+ fenced_block b(fenced_block::half);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
+ w.complete(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_END;
+ }
+ }
+
+private:
+ socket_ops::weak_cancel_token_type cancel_token_;
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_IOCP)
+
+#endif // BOOST_ASIO_DETAIL_WIN_IOCP_WAIT_OP_HPP
diff --git a/boost/asio/detail/win_object_handle_service.hpp b/boost/asio/detail/win_object_handle_service.hpp
index 3383657304..1e94a304eb 100644
--- a/boost/asio/detail/win_object_handle_service.hpp
+++ b/boost/asio/detail/win_object_handle_service.hpp
@@ -20,11 +20,11 @@
#if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/wait_handler.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -32,7 +32,8 @@ namespace boost {
namespace asio {
namespace detail {
-class win_object_handle_service
+class win_object_handle_service :
+ public service_base<win_object_handle_service>
{
public:
// The native type of an object handle.
@@ -80,10 +81,10 @@ public:
// Constructor.
BOOST_ASIO_DECL win_object_handle_service(
- boost::asio::io_service& io_service);
+ boost::asio::io_context& io_context);
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Construct a new handle implementation.
BOOST_ASIO_DECL void construct(implementation_type& impl);
@@ -135,11 +136,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef wait_handler<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "object_handle", &impl, "async_wait"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_.context(), *p.p, "object_handle",
+ &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "async_wait"));
start_wait_op(impl, p.p);
p.v = p.p = 0;
@@ -157,8 +158,8 @@ private:
static BOOST_ASIO_DECL VOID CALLBACK wait_callback(
PVOID param, BOOLEAN timeout);
- // The io_service implementation used to post completions.
- io_service_impl& io_service_;
+ // The io_context implementation used to post completions.
+ io_context_impl& io_context_;
// Mutex to protect access to internal state.
mutex mutex_;
diff --git a/boost/asio/detail/win_thread.hpp b/boost/asio/detail/win_thread.hpp
index a138d92ee8..f063330e1d 100644
--- a/boost/asio/detail/win_thread.hpp
+++ b/boost/asio/detail/win_thread.hpp
@@ -21,6 +21,7 @@
&& !defined(BOOST_ASIO_WINDOWS_APP) \
&& !defined(UNDER_CE)
+#include <cstddef>
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/socket_types.hpp>
@@ -79,6 +80,9 @@ public:
// Wait for the thread to exit.
BOOST_ASIO_DECL void join();
+ // Get number of CPUs.
+ BOOST_ASIO_DECL static std::size_t hardware_concurrency();
+
private:
friend BOOST_ASIO_DECL unsigned int __stdcall win_thread_function(void* arg);
diff --git a/boost/asio/detail/winapi_thread.hpp b/boost/asio/detail/winapp_thread.hpp
index 79aba9b519..4b57d228f6 100644
--- a/boost/asio/detail/winapi_thread.hpp
+++ b/boost/asio/detail/winapp_thread.hpp
@@ -1,5 +1,5 @@
//
-// detail/winapi_thread.hpp
+// detail/winapp_thread.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
@@ -8,8 +8,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_ASIO_DETAIL_WINAPI_THREAD_HPP
-#define BOOST_ASIO_DETAIL_WINAPI_THREAD_HPP
+#ifndef BOOST_ASIO_DETAIL_WINAPP_THREAD_HPP
+#define BOOST_ASIO_DETAIL_WINAPP_THREAD_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
@@ -17,8 +17,7 @@
#include <boost/asio/detail/config.hpp>
-#if defined(BOOST_ASIO_WINDOWS)
-#if defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE)
+#if defined(BOOST_ASIO_WINDOWS) && defined(BOOST_ASIO_WINDOWS_APP)
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/scoped_ptr.hpp>
@@ -32,19 +31,19 @@ namespace boost {
namespace asio {
namespace detail {
-DWORD WINAPI winapi_thread_function(LPVOID arg);
+DWORD WINAPI winapp_thread_function(LPVOID arg);
-class winapi_thread
+class winapp_thread
: private noncopyable
{
public:
// Constructor.
template <typename Function>
- winapi_thread(Function f, unsigned int = 0)
+ winapp_thread(Function f, unsigned int = 0)
{
scoped_ptr<func_base> arg(new func<Function>(f));
DWORD thread_id = 0;
- thread_ = ::CreateThread(0, 0, winapi_thread_function,
+ thread_ = ::CreateThread(0, 0, winapp_thread_function,
arg.get(), 0, &thread_id);
if (!thread_)
{
@@ -57,7 +56,7 @@ public:
}
// Destructor.
- ~winapi_thread()
+ ~winapp_thread()
{
::CloseHandle(thread_);
}
@@ -65,15 +64,19 @@ public:
// Wait for the thread to exit.
void join()
{
-#if defined(BOOST_ASIO_WINDOWS_APP)
::WaitForSingleObjectEx(thread_, INFINITE, false);
-#else // defined(BOOST_ASIO_WINDOWS_APP)
- ::WaitForSingleObject(thread_, INFINITE);
-#endif // defined(BOOST_ASIO_WINDOWS_APP)
+ }
+
+ // Get number of CPUs.
+ static std::size_t hardware_concurrency()
+ {
+ SYSTEM_INFO system_info;
+ ::GetNativeSystemInfo(&system_info);
+ return system_info.dwNumberOfProcessors;
}
private:
- friend DWORD WINAPI winapi_thread_function(LPVOID arg);
+ friend DWORD WINAPI winapp_thread_function(LPVOID arg);
class func_base
{
@@ -104,10 +107,10 @@ private:
::HANDLE thread_;
};
-inline DWORD WINAPI winapi_thread_function(LPVOID arg)
+inline DWORD WINAPI winapp_thread_function(LPVOID arg)
{
- scoped_ptr<winapi_thread::func_base> func(
- static_cast<winapi_thread::func_base*>(arg));
+ scoped_ptr<winapp_thread::func_base> func(
+ static_cast<winapp_thread::func_base*>(arg));
func->run();
return 0;
}
@@ -118,7 +121,6 @@ inline DWORD WINAPI winapi_thread_function(LPVOID arg)
#include <boost/asio/detail/pop_options.hpp>
-#endif // defined(BOOST_ASIO_WINDOWS_APP) || defined(UNDER_CE)
-#endif // defined(BOOST_ASIO_WINDOWS)
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(BOOST_ASIO_WINDOWS_APP)
-#endif // BOOST_ASIO_DETAIL_WINAPI_THREAD_HPP
+#endif // BOOST_ASIO_DETAIL_WINAPP_THREAD_HPP
diff --git a/boost/asio/detail/wince_thread.hpp b/boost/asio/detail/wince_thread.hpp
new file mode 100644
index 0000000000..bc14d71207
--- /dev/null
+++ b/boost/asio/detail/wince_thread.hpp
@@ -0,0 +1,126 @@
+//
+// detail/wince_thread.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WINCE_THREAD_HPP
+#define BOOST_ASIO_DETAIL_WINCE_THREAD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/scoped_ptr.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/error.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+DWORD WINAPI wince_thread_function(LPVOID arg);
+
+class wince_thread
+ : private noncopyable
+{
+public:
+ // Constructor.
+ template <typename Function>
+ wince_thread(Function f, unsigned int = 0)
+ {
+ scoped_ptr<func_base> arg(new func<Function>(f));
+ DWORD thread_id = 0;
+ thread_ = ::CreateThread(0, 0, wince_thread_function,
+ arg.get(), 0, &thread_id);
+ if (!thread_)
+ {
+ DWORD last_error = ::GetLastError();
+ boost::system::error_code ec(last_error,
+ boost::asio::error::get_system_category());
+ boost::asio::detail::throw_error(ec, "thread");
+ }
+ arg.release();
+ }
+
+ // Destructor.
+ ~wince_thread()
+ {
+ ::CloseHandle(thread_);
+ }
+
+ // Wait for the thread to exit.
+ void join()
+ {
+ ::WaitForSingleObject(thread_, INFINITE);
+ }
+
+ // Get number of CPUs.
+ static std::size_t hardware_concurrency()
+ {
+ SYSTEM_INFO system_info;
+ ::GetSystemInfo(&system_info);
+ return system_info.dwNumberOfProcessors;
+ }
+
+private:
+ friend DWORD WINAPI wince_thread_function(LPVOID arg);
+
+ class func_base
+ {
+ public:
+ virtual ~func_base() {}
+ virtual void run() = 0;
+ };
+
+ template <typename Function>
+ class func
+ : public func_base
+ {
+ public:
+ func(Function f)
+ : f_(f)
+ {
+ }
+
+ virtual void run()
+ {
+ f_();
+ }
+
+ private:
+ Function f_;
+ };
+
+ ::HANDLE thread_;
+};
+
+inline DWORD WINAPI wince_thread_function(LPVOID arg)
+{
+ scoped_ptr<wince_thread::func_base> func(
+ static_cast<wince_thread::func_base*>(arg));
+ func->run();
+ return 0;
+}
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_WINDOWS) && defined(UNDER_CE)
+
+#endif // BOOST_ASIO_DETAIL_WINCE_THREAD_HPP
diff --git a/boost/asio/detail/winrt_async_manager.hpp b/boost/asio/detail/winrt_async_manager.hpp
index d6d823d689..7af5357633 100644
--- a/boost/asio/detail/winrt_async_manager.hpp
+++ b/boost/asio/detail/winrt_async_manager.hpp
@@ -23,7 +23,7 @@
#include <boost/asio/detail/atomic_count.hpp>
#include <boost/asio/detail/winrt_async_op.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -36,9 +36,9 @@ class winrt_async_manager
{
public:
// Constructor.
- winrt_async_manager(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<winrt_async_manager>(io_service),
- io_service_(use_service<io_service_impl>(io_service)),
+ winrt_async_manager(boost::asio::io_context& io_context)
+ : boost::asio::detail::service_base<winrt_async_manager>(io_context),
+ io_context_(use_service<io_context_impl>(io_context)),
outstanding_ops_(1)
{
}
@@ -49,7 +49,7 @@ public:
}
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
if (--outstanding_ops_ > 0)
{
@@ -186,12 +186,12 @@ public:
boost::system::system_category());
break;
}
- io_service_.post_deferred_completion(handler);
+ io_context_.post_deferred_completion(handler);
if (--outstanding_ops_ == 0)
promise_.set_value();
});
- io_service_.work_started();
+ io_context_.work_started();
++outstanding_ops_;
action->Completed = on_completed;
}
@@ -223,12 +223,12 @@ public:
boost::system::system_category());
break;
}
- io_service_.post_deferred_completion(handler);
+ io_context_.post_deferred_completion(handler);
if (--outstanding_ops_ == 0)
promise_.set_value();
});
- io_service_.work_started();
+ io_context_.work_started();
++outstanding_ops_;
operation->Completed = on_completed;
}
@@ -264,19 +264,19 @@ public:
boost::system::system_category());
break;
}
- io_service_.post_deferred_completion(handler);
+ io_context_.post_deferred_completion(handler);
if (--outstanding_ops_ == 0)
promise_.set_value();
});
- io_service_.work_started();
+ io_context_.work_started();
++outstanding_ops_;
operation->Completed = on_completed;
}
private:
- // The io_service implementation used to post completed handlers.
- io_service_impl& io_service_;
+ // The io_context implementation used to post completed handlers.
+ io_context_impl& io_context_;
// Count of outstanding operations.
atomic_count outstanding_ops_;
diff --git a/boost/asio/detail/winrt_resolve_op.hpp b/boost/asio/detail/winrt_resolve_op.hpp
index 12d56933b1..7a98345a09 100644
--- a/boost/asio/detail/winrt_resolve_op.hpp
+++ b/boost/asio/detail/winrt_resolve_op.hpp
@@ -19,13 +19,13 @@
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/winrt_async_op.hpp>
-#include <boost/asio/ip/basic_resolver_iterator.hpp>
+#include <boost/asio/ip/basic_resolver_results.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -45,7 +45,7 @@ public:
typedef typename Protocol::endpoint endpoint_type;
typedef boost::asio::ip::basic_resolver_query<Protocol> query_type;
- typedef boost::asio::ip::basic_resolver_iterator<Protocol> iterator_type;
+ typedef boost::asio::ip::basic_resolver_results<Protocol> results_type;
winrt_resolve_op(const query_type& query, Handler& handler)
: winrt_async_op<
@@ -55,24 +55,25 @@ public:
query_(query),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code&, std::size_t)
{
// Take ownership of the operation object.
winrt_resolve_op* o(static_cast<winrt_resolve_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
- iterator_type iterator = iterator_type();
+ results_type results = results_type();
if (!o->ec_)
{
try
{
- iterator = iterator_type::create(
- o->result_, o->query_.hints(),
+ results = results_type::create(o->result_, o->query_.hints(),
o->query_.host_name(), o->query_.service_name());
}
catch (Platform::Exception^ e)
@@ -88,8 +89,8 @@ public:
// 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, boost::system::error_code, iterator_type>
- handler(o->handler_, o->ec_, iterator);
+ detail::binder2<Handler, boost::system::error_code, results_type>
+ handler(o->handler_, o->ec_, results);
p.h = boost::asio::detail::addressof(handler.handler_);
p.reset();
@@ -97,8 +98,8 @@ public:
if (owner)
{
fenced_block b(fenced_block::half);
- BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/winrt_resolver_service.hpp b/boost/asio/detail/winrt_resolver_service.hpp
index dfd1dddeb2..30e50e4f00 100644
--- a/boost/asio/detail/winrt_resolver_service.hpp
+++ b/boost/asio/detail/winrt_resolver_service.hpp
@@ -19,10 +19,10 @@
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
-#include <boost/asio/ip/basic_resolver_iterator.hpp>
#include <boost/asio/ip/basic_resolver_query.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/ip/basic_resolver_results.hpp>
#include <boost/asio/detail/bind_handler.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/winrt_async_manager.hpp>
#include <boost/asio/detail/winrt_resolve_op.hpp>
@@ -35,7 +35,8 @@ namespace asio {
namespace detail {
template <typename Protocol>
-class winrt_resolver_service
+class winrt_resolver_service :
+ public service_base<winrt_resolver_service<Protocol> >
{
public:
// The implementation type of the resolver. A cancellation token is used to
@@ -49,13 +50,14 @@ public:
// The query type.
typedef boost::asio::ip::basic_resolver_query<Protocol> query_type;
- // The iterator type.
- typedef boost::asio::ip::basic_resolver_iterator<Protocol> iterator_type;
+ // The results type.
+ typedef boost::asio::ip::basic_resolver_results<Protocol> results_type;
// Constructor.
- winrt_resolver_service(boost::asio::io_service& io_service)
- : io_service_(use_service<io_service_impl>(io_service)),
- async_manager_(use_service<winrt_async_manager>(io_service))
+ winrt_resolver_service(boost::asio::io_context& io_context)
+ : service_base<winrt_resolver_service<Protocol> >(io_context),
+ io_context_(use_service<io_context_impl>(io_context)),
+ async_manager_(use_service<winrt_async_manager>(io_context))
{
}
@@ -65,12 +67,12 @@ public:
}
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
}
// Perform any fork-related housekeeping.
- void fork_service(boost::asio::io_service::fork_event)
+ void notify_fork(boost::asio::io_context::fork_event)
{
}
@@ -79,6 +81,18 @@ public:
{
}
+ // Move-construct a new resolver implementation.
+ void move_construct(implementation_type&,
+ implementation_type&)
+ {
+ }
+
+ // Move-assign from another resolver implementation.
+ void move_assign(implementation_type&,
+ winrt_resolver_service&, implementation_type&)
+ {
+ }
+
// Destroy a resolver implementation.
void destroy(implementation_type&)
{
@@ -90,7 +104,7 @@ public:
}
// Resolve a query to a list of entries.
- iterator_type resolve(implementation_type&,
+ results_type resolve(implementation_type&,
const query_type& query, boost::system::error_code& ec)
{
try
@@ -102,9 +116,9 @@ public:
winrt_utils::string(query.service_name())), ec);
if (ec)
- return iterator_type();
+ return results_type();
- return iterator_type::create(
+ return results_type::create(
endpoint_pairs, query.hints(),
query.host_name(), query.service_name());
}
@@ -112,13 +126,13 @@ public:
{
ec = boost::system::error_code(e->HResult,
boost::system::system_category());
- return iterator_type();
+ return results_type();
}
}
// Asynchronously resolve a query to a list of entries.
template <typename Handler>
- void async_resolve(implementation_type&,
+ void async_resolve(implementation_type& impl,
const query_type& query, Handler& handler)
{
bool is_continuation =
@@ -127,11 +141,12 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef winrt_resolve_op<Protocol, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(query, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "resolver", &impl, "async_resolve"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_.context(),
+ *p.p, "resolver", &impl, 0, "async_resolve"));
+ (void)impl;
try
{
@@ -145,17 +160,17 @@ public:
{
p.p->ec_ = boost::system::error_code(
e->HResult, boost::system::system_category());
- io_service_.post_immediate_completion(p.p, is_continuation);
+ io_context_.post_immediate_completion(p.p, is_continuation);
p.v = p.p = 0;
}
}
// Resolve an endpoint to a list of entries.
- iterator_type resolve(implementation_type&,
+ results_type resolve(implementation_type&,
const endpoint_type&, boost::system::error_code& ec)
{
ec = boost::asio::error::operation_not_supported;
- return iterator_type();
+ return results_type();
}
// Asynchronously resolve an endpoint to a list of entries.
@@ -164,13 +179,13 @@ public:
const endpoint_type&, Handler& handler)
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
- const iterator_type iterator;
- io_service_.get_io_service().post(
- detail::bind_handler(handler, ec, iterator));
+ const results_type results;
+ io_context_.get_io_context().post(
+ detail::bind_handler(handler, ec, results));
}
private:
- io_service_impl& io_service_;
+ io_context_impl& io_context_;
winrt_async_manager& async_manager_;
};
diff --git a/boost/asio/detail/winrt_socket_connect_op.hpp b/boost/asio/detail/winrt_socket_connect_op.hpp
index 548f7d631a..6fc1ab0c7f 100644
--- a/boost/asio/detail/winrt_socket_connect_op.hpp
+++ b/boost/asio/detail/winrt_socket_connect_op.hpp
@@ -19,12 +19,12 @@
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/winrt_async_op.hpp>
#include <boost/asio/error.hpp>
@@ -45,16 +45,18 @@ public:
: winrt_async_op<void>(&winrt_socket_connect_op::do_complete),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code&, std::size_t)
{
// Take ownership of the operation object.
winrt_socket_connect_op* o(static_cast<winrt_socket_connect_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
// 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
@@ -71,8 +73,8 @@ public:
if (owner)
{
fenced_block b(fenced_block::half);
- BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/winrt_socket_recv_op.hpp b/boost/asio/detail/winrt_socket_recv_op.hpp
index 2cbbb3c8d8..137ed5a118 100644
--- a/boost/asio/detail/winrt_socket_recv_op.hpp
+++ b/boost/asio/detail/winrt_socket_recv_op.hpp
@@ -19,12 +19,12 @@
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/winrt_async_op.hpp>
#include <boost/asio/error.hpp>
@@ -47,16 +47,18 @@ public:
buffers_(buffers),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code&, std::size_t)
{
// Take ownership of the operation object.
winrt_socket_recv_op* o(static_cast<winrt_socket_recv_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
// Check whether buffers are still valid.
@@ -91,7 +93,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/winrt_socket_send_op.hpp b/boost/asio/detail/winrt_socket_send_op.hpp
index 591d9536c3..301c4127a6 100644
--- a/boost/asio/detail/winrt_socket_send_op.hpp
+++ b/boost/asio/detail/winrt_socket_send_op.hpp
@@ -19,12 +19,12 @@
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/bind_handler.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
#include <boost/asio/detail/fenced_block.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/winrt_async_op.hpp>
#include <boost/asio/error.hpp>
@@ -46,16 +46,18 @@ public:
buffers_(buffers),
handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
+ handler_work<Handler>::start(handler_);
}
- static void do_complete(io_service_impl* owner, operation* base,
+ static void do_complete(void* owner, operation* base,
const boost::system::error_code&, std::size_t)
{
// Take ownership of the operation object.
winrt_socket_send_op* o(static_cast<winrt_socket_send_op*>(base));
ptr p = { boost::asio::detail::addressof(o->handler_), o, o };
+ handler_work<Handler> w(o->handler_);
- BOOST_ASIO_HANDLER_COMPLETION((o));
+ BOOST_ASIO_HANDLER_COMPLETION((*o));
#if defined(BOOST_ASIO_ENABLE_BUFFER_DEBUGGING)
// Check whether buffers are still valid.
@@ -82,7 +84,7 @@ public:
{
fenced_block b(fenced_block::half);
BOOST_ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));
- boost_asio_handler_invoke_helpers::invoke(handler, handler.handler_);
+ w.complete(handler, handler.handler_);
BOOST_ASIO_HANDLER_INVOCATION_END;
}
}
diff --git a/boost/asio/detail/winrt_ssocket_service.hpp b/boost/asio/detail/winrt_ssocket_service.hpp
index b9b1910e78..a1e15db545 100644
--- a/boost/asio/detail/winrt_ssocket_service.hpp
+++ b/boost/asio/detail/winrt_ssocket_service.hpp
@@ -20,8 +20,8 @@
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/winrt_socket_connect_op.hpp>
#include <boost/asio/detail/winrt_ssocket_service_base.hpp>
#include <boost/asio/detail/winrt_utils.hpp>
@@ -34,6 +34,7 @@ namespace detail {
template <typename Protocol>
class winrt_ssocket_service :
+ public service_base<winrt_ssocket_service<Protocol> >,
public winrt_ssocket_service_base
{
public:
@@ -61,11 +62,18 @@ public:
};
// Constructor.
- winrt_ssocket_service(boost::asio::io_service& io_service)
- : winrt_ssocket_service_base(io_service)
+ winrt_ssocket_service(boost::asio::io_context& io_context)
+ : service_base<winrt_ssocket_service<Protocol> >(io_context),
+ winrt_ssocket_service_base(io_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)
@@ -213,11 +221,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef winrt_socket_connect_op<Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_connect"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_.context(),
+ *p.p, "socket", &impl, 0, "async_connect"));
start_connect_op(impl, peer_endpoint.data(), p.p, is_continuation);
p.v = p.p = 0;
diff --git a/boost/asio/detail/winrt_ssocket_service_base.hpp b/boost/asio/detail/winrt_ssocket_service_base.hpp
index 88e5674576..c18722466f 100644
--- a/boost/asio/detail/winrt_ssocket_service_base.hpp
+++ b/boost/asio/detail/winrt_ssocket_service_base.hpp
@@ -21,10 +21,10 @@
#include <boost/asio/buffer.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/socket_base.hpp>
-#include <boost/asio/detail/addressof.hpp>
#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/detail/winrt_async_manager.hpp>
#include <boost/asio/detail/winrt_socket_recv_op.hpp>
@@ -63,10 +63,10 @@ public:
// Constructor.
BOOST_ASIO_DECL winrt_ssocket_service_base(
- boost::asio::io_service& io_service);
+ boost::asio::io_context& io_context);
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void base_shutdown();
// Construct a new socket implementation.
BOOST_ASIO_DECL void construct(base_implementation_type&);
@@ -93,6 +93,10 @@ public:
BOOST_ASIO_DECL boost::system::error_code close(
base_implementation_type& impl, boost::system::error_code& ec);
+ // Release ownership of the socket.
+ BOOST_ASIO_DECL native_handle_type release(
+ base_implementation_type& impl, boost::system::error_code& ec);
+
// Get the native socket representation.
native_handle_type native_handle(base_implementation_type& impl)
{
@@ -200,11 +204,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef winrt_socket_send_op<ConstBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_send"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_.context(),
+ *p.p, "socket", &impl, 0, "async_send"));
start_send_op(impl,
buffer_sequence_adapter<boost::asio::const_buffer,
@@ -220,7 +224,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.get_io_service().post(
+ io_context_.get_io_context().post(
detail::bind_handler(handler, ec, bytes_transferred));
}
@@ -256,11 +260,11 @@ public:
// Allocate and construct an operation to wrap the handler.
typedef winrt_socket_recv_op<MutableBufferSequence, Handler> op;
typename op::ptr p = { boost::asio::detail::addressof(handler),
- boost_asio_handler_alloc_helpers::allocate(
- sizeof(op), handler), 0 };
+ op::ptr::allocate(handler), 0 };
p.p = new (p.v) op(buffers, handler);
- BOOST_ASIO_HANDLER_CREATION((p.p, "socket", &impl, "async_receive"));
+ BOOST_ASIO_HANDLER_CREATION((io_context_.context(),
+ *p.p, "socket", &impl, 0, "async_receive"));
start_receive_op(impl,
buffer_sequence_adapter<boost::asio::mutable_buffer,
@@ -276,7 +280,7 @@ public:
{
boost::system::error_code ec = boost::asio::error::operation_not_supported;
const std::size_t bytes_transferred = 0;
- io_service_.get_io_service().post(
+ io_context_.get_io_context().post(
detail::bind_handler(handler, ec, bytes_transferred));
}
@@ -329,8 +333,8 @@ protected:
winrt_async_op<Windows::Storage::Streams::IBuffer^>* op,
bool is_continuation);
- // The io_service implementation used for delivering completions.
- io_service_impl& io_service_;
+ // The io_context implementation used for delivering completions.
+ io_context_impl& io_context_;
// The manager that keeps track of outstanding operations.
winrt_async_manager& async_manager_;
diff --git a/boost/asio/detail/winrt_timer_scheduler.hpp b/boost/asio/detail/winrt_timer_scheduler.hpp
index 8b119b2724..9dd9d050ce 100644
--- a/boost/asio/detail/winrt_timer_scheduler.hpp
+++ b/boost/asio/detail/winrt_timer_scheduler.hpp
@@ -28,7 +28,7 @@
#include <boost/asio/detail/timer_queue_base.hpp>
#include <boost/asio/detail/timer_queue_set.hpp>
#include <boost/asio/detail/wait_op.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#if defined(BOOST_ASIO_HAS_IOCP)
# include <boost/asio/detail/thread.hpp>
@@ -45,17 +45,17 @@ class winrt_timer_scheduler
{
public:
// Constructor.
- BOOST_ASIO_DECL winrt_timer_scheduler(boost::asio::io_service& io_service);
+ BOOST_ASIO_DECL winrt_timer_scheduler(boost::asio::io_context& io_context);
// Destructor.
BOOST_ASIO_DECL ~winrt_timer_scheduler();
// Destroy all user-defined handler objects owned by the service.
- BOOST_ASIO_DECL void shutdown_service();
+ BOOST_ASIO_DECL void shutdown();
// Recreate internal descriptors following a fork.
- BOOST_ASIO_DECL void fork_service(
- boost::asio::io_service::fork_event fork_ev);
+ BOOST_ASIO_DECL void notify_fork(
+ boost::asio::io_context::fork_event fork_ev);
// Initialise the task. No effect as this class uses its own thread.
BOOST_ASIO_DECL void init_task();
@@ -82,6 +82,12 @@ public:
typename timer_queue<Time_Traits>::per_timer_data& timer,
std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());
+ // 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& to,
+ typename timer_queue<Time_Traits>::per_timer_data& from);
+
private:
// Run the select loop in the thread.
BOOST_ASIO_DECL void run_thread();
@@ -95,8 +101,8 @@ private:
// Helper function to remove a timer queue.
BOOST_ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);
- // The io_service implementation used to post completions.
- io_service_impl& io_service_;
+ // The io_context implementation used to post completions.
+ io_context_impl& io_context_;
// Mutex used to protect internal variables.
boost::asio::detail::mutex mutex_;
diff --git a/boost/asio/detail/winrt_utils.hpp b/boost/asio/detail/winrt_utils.hpp
index 351aa62f23..0aebacbbb9 100644
--- a/boost/asio/detail/winrt_utils.hpp
+++ b/boost/asio/detail/winrt_utils.hpp
@@ -23,13 +23,12 @@
#include <cstdlib>
#include <future>
#include <locale>
-#include <memory>
#include <robuffer.h>
#include <windows.storage.streams.h>
#include <wrl/implements.h>
#include <boost/asio/buffer.hpp>
#include <boost/system/error_code.hpp>
-#include <boost/asio/detail/addressof.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -84,7 +83,8 @@ inline Windows::Storage::Streams::IBuffer^ buffer_dup(
const ConstBufferSequence& buffers)
{
using Microsoft::WRL::ComPtr;
- std::size_t size = boost::asio::buffer_size(buffers);
+ using boost::asio::buffer_size;
+ std::size_t size = buffer_size(buffers);
auto b = ref new Windows::Storage::Streams::Buffer(size);
ComPtr<IInspectable> insp = reinterpret_cast<IInspectable*>(b);
ComPtr<Windows::Storage::Streams::IBufferByteAccess> bacc;
diff --git a/boost/asio/detail/work_dispatcher.hpp b/boost/asio/detail/work_dispatcher.hpp
new file mode 100644
index 0000000000..7ccacd5546
--- /dev/null
+++ b/boost/asio/detail/work_dispatcher.hpp
@@ -0,0 +1,74 @@
+//
+// detail/work_dispatcher.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DETAIL_WORK_DISPATCHER_HPP
+#define BOOST_ASIO_DETAIL_WORK_DISPATCHER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/executor_work_guard.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace detail {
+
+template <typename Handler>
+class work_dispatcher
+{
+public:
+ work_dispatcher(Handler& handler)
+ : work_((get_associated_executor)(handler)),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ work_dispatcher(const work_dispatcher& other)
+ : work_(other.work_),
+ handler_(other.handler_)
+ {
+ }
+
+ work_dispatcher(work_dispatcher&& other)
+ : work_(BOOST_ASIO_MOVE_CAST(executor_work_guard<
+ typename associated_executor<Handler>::type>)(other.work_)),
+ handler_(BOOST_ASIO_MOVE_CAST(Handler)(other.handler_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ void operator()()
+ {
+ typename associated_allocator<Handler>::type alloc(
+ (get_associated_allocator)(handler_));
+ work_.get_executor().dispatch(
+ BOOST_ASIO_MOVE_CAST(Handler)(handler_), alloc);
+ work_.reset();
+ }
+
+private:
+ executor_work_guard<typename associated_executor<Handler>::type> work_;
+ Handler handler_;
+};
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_DETAIL_WORK_DISPATCHER_HPP
diff --git a/boost/asio/dispatch.hpp b/boost/asio/dispatch.hpp
new file mode 100644
index 0000000000..c2ea0c8999
--- /dev/null
+++ b/boost/asio/dispatch.hpp
@@ -0,0 +1,110 @@
+//
+// dispatch.hpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_DISPATCH_HPP
+#define BOOST_ASIO_DISPATCH_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/is_executor.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Submits a completion token or function object for execution.
+/**
+ * This function submits an object for execution using the object's associated
+ * executor. The function object is queued for execution, and is never called
+ * from the current thread prior to returning from <tt>dispatch()</tt>.
+ *
+ * This function has the following effects:
+ *
+ * @li Constructs a function object handler of type @c Handler, initialized
+ * with <tt>handler(forward<CompletionToken>(token))</tt>.
+ *
+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,
+ * initializing the object as <tt>result(handler)</tt>.
+ *
+ * @li Obtains the handler's associated executor object @c ex by performing
+ * <tt>get_associated_executor(handler)</tt>.
+ *
+ * @li Obtains the handler's associated allocator object @c alloc by performing
+ * <tt>get_associated_allocator(handler)</tt>.
+ *
+ * @li Performs <tt>ex.dispatch(std::move(handler), alloc)</tt>.
+ *
+ * @li Returns <tt>result.get()</tt>.
+ */
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
+ BOOST_ASIO_MOVE_ARG(CompletionToken) token);
+
+/// Submits a completion token or function object for execution.
+/**
+ * This function submits an object for execution using the specified executor.
+ * The function object is queued for execution, and is never called from the
+ * current thread prior to returning from <tt>dispatch()</tt>.
+ *
+ * This function has the following effects:
+ *
+ * @li Constructs a function object handler of type @c Handler, initialized
+ * with <tt>handler(forward<CompletionToken>(token))</tt>.
+ *
+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,
+ * initializing the object as <tt>result(handler)</tt>.
+ *
+ * @li Obtains the handler's associated executor object @c ex1 by performing
+ * <tt>get_associated_executor(handler)</tt>.
+ *
+ * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.
+ *
+ * @li Obtains the handler's associated allocator object @c alloc by performing
+ * <tt>get_associated_allocator(handler)</tt>.
+ *
+ * @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 Performs <tt>Executor(ex).dispatch(std::move(f), alloc)</tt>.
+ *
+ * @li Returns <tt>result.get()</tt>.
+ */
+template <typename Executor, typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
+ const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_executor<Executor>::value>::type* = 0);
+
+/// Submits a completion token or function object for execution.
+/**
+ * @returns <tt>dispatch(ctx.get_executor(),
+ * forward<CompletionToken>(token))</tt>.
+ */
+template <typename ExecutionContext, typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
+ ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_convertible<
+ ExecutionContext&, execution_context&>::value>::type* = 0);
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/impl/dispatch.hpp>
+
+#endif // BOOST_ASIO_DISPATCH_HPP
diff --git a/boost/asio/error.hpp b/boost/asio/error.hpp
index dd338fb156..8f1f74cb91 100644
--- a/boost/asio/error.hpp
+++ b/boost/asio/error.hpp
@@ -327,6 +327,22 @@ inline boost::system::error_code make_error_code(misc_errors e)
}
} // namespace error
+namespace stream_errc {
+ // Simulates the proposed stream_errc scoped enum.
+ using error::eof;
+ using error::not_found;
+} // namespace stream_errc
+namespace socket_errc {
+ // Simulates the proposed socket_errc scoped enum.
+ using error::already_open;
+ using error::not_found;
+} // namespace socket_errc
+namespace resolver_errc {
+ // Simulates the proposed resolver_errc scoped enum.
+ using error::host_not_found;
+ const error::netdb_errors try_again = error::host_not_found_try_again;
+ using error::service_not_found;
+} // namespace resolver_errc
} // namespace asio
} // namespace boost
diff --git a/boost/asio/execution_context.hpp b/boost/asio/execution_context.hpp
new file mode 100644
index 0000000000..9feb30c45d
--- /dev/null
+++ b/boost/asio/execution_context.hpp
@@ -0,0 +1,413 @@
+//
+// execution_context.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_EXECUTION_CONTEXT_HPP
+#define BOOST_ASIO_EXECUTION_CONTEXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <stdexcept>
+#include <typeinfo>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/variadic_templates.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+class execution_context;
+class io_context;
+
+#if !defined(GENERATING_DOCUMENTATION)
+template <typename Service> Service& use_service(execution_context&);
+template <typename Service> Service& use_service(io_context&);
+template <typename Service> void add_service(execution_context&, Service*);
+template <typename Service> bool has_service(execution_context&);
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+namespace detail { class service_registry; }
+
+/// A context for function object execution.
+/**
+ * An execution context represents a place where function objects will be
+ * executed. An @c io_context is an example of an execution context.
+ *
+ * @par The execution_context class and services
+ *
+ * Class execution_context implements an extensible, type-safe, polymorphic set
+ * of services, indexed by service type.
+ *
+ * Services exist to manage the resources that are shared across an execution
+ * context. For example, timers may be implemented in terms of a single timer
+ * queue, and this queue would be stored in a service.
+ *
+ * Access to the services of an execution_context is via three function
+ * templates, use_service(), add_service() and has_service().
+ *
+ * In a call to @c use_service<Service>(), the type argument chooses a service,
+ * making available all members of the named type. If @c Service is not present
+ * in an execution_context, an object of type @c Service is created and added
+ * to the execution_context. A C++ program can check if an execution_context
+ * implements a particular service with the function template @c
+ * has_service<Service>().
+ *
+ * Service objects may be explicitly added to an execution_context using the
+ * function template @c add_service<Service>(). If the @c Service is already
+ * present, the service_already_exists exception is thrown. If the owner of the
+ * service is not the same object as the execution_context parameter, the
+ * invalid_service_owner exception is thrown.
+ *
+ * Once a service reference is obtained from an execution_context object by
+ * calling use_service(), that reference remains usable as long as the owning
+ * execution_context object exists.
+ *
+ * All service implementations have execution_context::service as a public base
+ * class. Custom services may be implemented by deriving from this class and
+ * then added to an execution_context using the facilities described above.
+ *
+ * @par The execution_context as a base class
+ *
+ * Class execution_context may be used only as a base class for concrete
+ * execution context types. The @c io_context is an example of such a derived
+ * type.
+ *
+ * On destruction, a class that is derived from execution_context must perform
+ * <tt>execution_context::shutdown()</tt> followed by
+ * <tt>execution_context::destroy()</tt>.
+ *
+ * This destruction sequence permits programs to simplify their resource
+ * management by using @c shared_ptr<>. Where an object's lifetime is tied to
+ * the lifetime of a connection (or some other sequence of asynchronous
+ * operations), a @c shared_ptr to the object would be bound into the handlers
+ * for all asynchronous operations associated with it. This works as follows:
+ *
+ * @li When a single connection ends, all associated asynchronous operations
+ * complete. The corresponding handler objects are destroyed, and all @c
+ * shared_ptr references to the objects are destroyed.
+ *
+ * @li To shut down the whole program, the io_context function stop() is called
+ * to terminate any run() calls as soon as possible. The io_context destructor
+ * calls @c shutdown() and @c destroy() to destroy all pending handlers,
+ * causing all @c shared_ptr references to all connection objects to be
+ * destroyed.
+ */
+class execution_context
+ : private noncopyable
+{
+public:
+ class id;
+ class service;
+
+protected:
+ /// Constructor.
+ BOOST_ASIO_DECL execution_context();
+
+ /// Destructor.
+ BOOST_ASIO_DECL ~execution_context();
+
+ /// Shuts down all services in the context.
+ /**
+ * This function is implemented as follows:
+ *
+ * @li For each service object @c svc in the execution_context set, in
+ * reverse order of the beginning of service object lifetime, performs @c
+ * svc->shutdown().
+ */
+ BOOST_ASIO_DECL void shutdown();
+
+ /// Destroys all services in the context.
+ /**
+ * This function is implemented as follows:
+ *
+ * @li For each service object @c svc in the execution_context set, in
+ * reverse order * of the beginning of service object lifetime, performs
+ * <tt>delete static_cast<execution_context::service*>(svc)</tt>.
+ */
+ BOOST_ASIO_DECL void destroy();
+
+public:
+ /// Fork-related event notifications.
+ enum fork_event
+ {
+ /// Notify the context that the process is about to fork.
+ fork_prepare,
+
+ /// Notify the context that the process has forked and is the parent.
+ fork_parent,
+
+ /// Notify the context that the process has forked and is the child.
+ fork_child
+ };
+
+ /// Notify the execution_context of a fork-related event.
+ /**
+ * This function is used to inform the execution_context that the process is
+ * about to fork, or has just forked. This allows the execution_context, and
+ * the services it contains, to perform any necessary housekeeping to ensure
+ * correct operation following a fork.
+ *
+ * This function must not be called while any other execution_context
+ * function, or any function associated with the execution_context's derived
+ * class, is being called in another thread. It is, however, safe to call
+ * this function from within a completion handler, provided no other thread
+ * is accessing the execution_context or its derived class.
+ *
+ * @param event A fork-related event.
+ *
+ * @throws boost::system::system_error Thrown on failure. If the notification
+ * fails the execution_context object should no longer be used and should be
+ * destroyed.
+ *
+ * @par Example
+ * The following code illustrates how to incorporate the notify_fork()
+ * function:
+ * @code my_execution_context.notify_fork(execution_context::fork_prepare);
+ * if (fork() == 0)
+ * {
+ * // This is the child process.
+ * my_execution_context.notify_fork(execution_context::fork_child);
+ * }
+ * else
+ * {
+ * // This is the parent process.
+ * my_execution_context.notify_fork(execution_context::fork_parent);
+ * } @endcode
+ *
+ * @note For each service object @c svc in the execution_context set,
+ * performs <tt>svc->notify_fork();</tt>. When processing the fork_prepare
+ * event, services are visited in reverse order of the beginning of service
+ * object lifetime. Otherwise, services are visited in order of the beginning
+ * of service object lifetime.
+ */
+ BOOST_ASIO_DECL void notify_fork(fork_event event);
+
+ /// Obtain the service object corresponding to the given type.
+ /**
+ * This function is used to locate a service object that corresponds to the
+ * given service type. If there is no existing implementation of the service,
+ * then the execution_context will create a new instance of the service.
+ *
+ * @param e The execution_context object that owns the service.
+ *
+ * @return The service interface implementing the specified service type.
+ * Ownership of the service interface is not transferred to the caller.
+ */
+ template <typename Service>
+ friend Service& use_service(execution_context& e);
+
+ /// Obtain the service object corresponding to the given type.
+ /**
+ * This function is used to locate a service object that corresponds to the
+ * given service type. If there is no existing implementation of the service,
+ * then the io_context will create a new instance of the service.
+ *
+ * @param ioc The io_context object that owns the service.
+ *
+ * @return The service interface implementing the specified service type.
+ * Ownership of the service interface is not transferred to the caller.
+ *
+ * @note This overload is preserved for backwards compatibility with services
+ * that inherit from io_context::service.
+ */
+ template <typename Service>
+ friend Service& use_service(io_context& ioc);
+
+#if defined(GENERATING_DOCUMENTATION)
+
+ /// Creates a service object and adds it to the execution_context.
+ /**
+ * This function is used to add a service to the execution_context.
+ *
+ * @param e The execution_context object that owns the service.
+ *
+ * @param args Zero or more arguments to be passed to the service
+ * constructor.
+ *
+ * @throws boost::asio::service_already_exists Thrown if a service of the
+ * given type is already present in the execution_context.
+ */
+ template <typename Service, typename... Args>
+ friend Service& make_service(execution_context& e, Args&&... args);
+
+#elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Service, typename... Args>
+ friend Service& make_service(execution_context& e,
+ BOOST_ASIO_MOVE_ARG(Args)... args);
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename Service>
+ friend Service& make_service(execution_context& e);
+
+#define BOOST_ASIO_PRIVATE_MAKE_SERVICE_DEF(n) \
+ template <typename Service, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ friend Service& make_service(execution_context& e, \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)); \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_MAKE_SERVICE_DEF)
+#undef BOOST_ASIO_PRIVATE_MAKE_SERVICE_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ /// (Deprecated: Use make_service().) Add a service object to the
+ /// execution_context.
+ /**
+ * This function is used to add a service to the execution_context.
+ *
+ * @param e The execution_context object that owns the service.
+ *
+ * @param svc The service object. On success, ownership of the service object
+ * is transferred to the execution_context. When the execution_context object
+ * is destroyed, it will destroy the service object by performing: @code
+ * delete static_cast<execution_context::service*>(svc) @endcode
+ *
+ * @throws boost::asio::service_already_exists Thrown if a service of the
+ * given type is already present in the execution_context.
+ *
+ * @throws boost::asio::invalid_service_owner Thrown if the service's owning
+ * execution_context is not the execution_context object specified by the
+ * @c e parameter.
+ */
+ template <typename Service>
+ friend void add_service(execution_context& e, Service* svc);
+
+ /// Determine if an execution_context contains a specified service type.
+ /**
+ * This function is used to determine whether the execution_context contains a
+ * service object corresponding to the given service type.
+ *
+ * @param e The execution_context object that owns the service.
+ *
+ * @return A boolean indicating whether the execution_context contains the
+ * service.
+ */
+ template <typename Service>
+ friend bool has_service(execution_context& e);
+
+private:
+ // The service registry.
+ boost::asio::detail::service_registry* service_registry_;
+};
+
+/// Class used to uniquely identify a service.
+class execution_context::id
+ : private noncopyable
+{
+public:
+ /// Constructor.
+ id() {}
+};
+
+/// Base class for all io_context services.
+class execution_context::service
+ : private noncopyable
+{
+public:
+ /// Get the context object that owns the service.
+ execution_context& context();
+
+protected:
+ /// Constructor.
+ /**
+ * @param owner The execution_context object that owns the service.
+ */
+ BOOST_ASIO_DECL service(execution_context& owner);
+
+ /// Destructor.
+ BOOST_ASIO_DECL virtual ~service();
+
+private:
+ /// Destroy all user-defined handler objects owned by the service.
+ virtual void shutdown() = 0;
+
+ /// Handle notification of a fork-related event to perform any necessary
+ /// housekeeping.
+ /**
+ * This function is not a pure virtual so that services only have to
+ * implement it if necessary. The default implementation does nothing.
+ */
+ BOOST_ASIO_DECL virtual void notify_fork(
+ execution_context::fork_event event);
+
+ friend class boost::asio::detail::service_registry;
+ struct key
+ {
+ key() : type_info_(0), id_(0) {}
+ const std::type_info* type_info_;
+ const execution_context::id* id_;
+ } key_;
+
+ execution_context& owner_;
+ service* next_;
+};
+
+/// Exception thrown when trying to add a duplicate service to an
+/// execution_context.
+class service_already_exists
+ : public std::logic_error
+{
+public:
+ BOOST_ASIO_DECL service_already_exists();
+};
+
+/// Exception thrown when trying to add a service object to an
+/// execution_context where the service has a different owner.
+class invalid_service_owner
+ : public std::logic_error
+{
+public:
+ BOOST_ASIO_DECL invalid_service_owner();
+};
+
+namespace detail {
+
+// Special derived service id type to keep classes header-file only.
+template <typename Type>
+class service_id
+ : public execution_context::id
+{
+};
+
+// Special service base class to keep classes header-file only.
+template <typename Type>
+class execution_context_service_base
+ : public execution_context::service
+{
+public:
+ static service_id<Type> id;
+
+ // Constructor.
+ execution_context_service_base(execution_context& e)
+ : execution_context::service(e)
+ {
+ }
+};
+
+template <typename Type>
+service_id<Type> execution_context_service_base<Type>::id;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/impl/execution_context.hpp>
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/impl/execution_context.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_ASIO_EXECUTION_CONTEXT_HPP
diff --git a/boost/asio/executor.hpp b/boost/asio/executor.hpp
new file mode 100644
index 0000000000..f519842361
--- /dev/null
+++ b/boost/asio/executor.hpp
@@ -0,0 +1,343 @@
+//
+// executor.hpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_EXECUTOR_HPP
+#define BOOST_ASIO_EXECUTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <typeinfo>
+#include <boost/asio/detail/cstddef.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/throw_exception.hpp>
+#include <boost/asio/execution_context.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Exception thrown when trying to access an empty polymorphic executor.
+class bad_executor
+ : public std::exception
+{
+public:
+ /// Constructor.
+ BOOST_ASIO_DECL bad_executor() BOOST_ASIO_NOEXCEPT;
+
+ /// Obtain message associated with exception.
+ BOOST_ASIO_DECL virtual const char* what() const
+ BOOST_ASIO_NOEXCEPT_OR_NOTHROW;
+};
+
+/// Polymorphic wrapper for executors.
+class executor
+{
+public:
+ /// Default constructor.
+ executor() BOOST_ASIO_NOEXCEPT
+ : impl_(0)
+ {
+ }
+
+ /// Construct from nullptr.
+ executor(nullptr_t) BOOST_ASIO_NOEXCEPT
+ : impl_(0)
+ {
+ }
+
+ /// Copy constructor.
+ executor(const executor& other) BOOST_ASIO_NOEXCEPT
+ : impl_(other.clone())
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move constructor.
+ executor(executor&& other) BOOST_ASIO_NOEXCEPT
+ : impl_(other.impl_)
+ {
+ other.impl_ = 0;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Construct a polymorphic wrapper for the specified executor.
+ template <typename Executor>
+ executor(Executor e);
+
+ /// Allocator-aware constructor to create a polymorphic wrapper for the
+ /// specified executor.
+ template <typename Executor, typename Allocator>
+ executor(allocator_arg_t, const Allocator& a, Executor e);
+
+ /// Destructor.
+ ~executor()
+ {
+ destroy();
+ }
+
+ /// Assignment operator.
+ executor& operator=(const executor& other) BOOST_ASIO_NOEXCEPT
+ {
+ destroy();
+ impl_ = other.clone();
+ return *this;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ // Move assignment operator.
+ executor& operator=(executor&& other) BOOST_ASIO_NOEXCEPT
+ {
+ destroy();
+ impl_ = other.impl_;
+ other.impl_ = 0;
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Assignment operator for nullptr_t.
+ executor& operator=(nullptr_t) BOOST_ASIO_NOEXCEPT
+ {
+ destroy();
+ impl_ = 0;
+ return *this;
+ }
+
+ /// Assignment operator to create a polymorphic wrapper for the specified
+ /// executor.
+ template <typename Executor>
+ executor& operator=(BOOST_ASIO_MOVE_ARG(Executor) e) BOOST_ASIO_NOEXCEPT
+ {
+ executor tmp(BOOST_ASIO_MOVE_CAST(Executor)(e));
+ destroy();
+ impl_ = tmp.impl_;
+ tmp.impl_ = 0;
+ return *this;
+ }
+
+ /// Obtain the underlying execution context.
+ execution_context& context() const BOOST_ASIO_NOEXCEPT
+ {
+ return get_impl()->context();
+ }
+
+ /// Inform the executor that it has some outstanding work to do.
+ void on_work_started() const BOOST_ASIO_NOEXCEPT
+ {
+ get_impl()->on_work_started();
+ }
+
+ /// Inform the executor that some work is no longer outstanding.
+ void on_work_finished() const BOOST_ASIO_NOEXCEPT
+ {
+ get_impl()->on_work_finished();
+ }
+
+ /// Request the executor to invoke the given function object.
+ /**
+ * This function is used to ask the executor to execute the given function
+ * object. The function object is executed according to the rules of the
+ * target executor object.
+ *
+ * @param f The function object to be called. The executor will make a copy
+ * of the handler object as required. The function signature of the function
+ * object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ /// Request the executor to invoke the given function object.
+ /**
+ * This function is used to ask the executor to execute the given function
+ * object. The function object is executed according to the rules of the
+ * target executor object.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void post(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ /// Request the executor to invoke the given function object.
+ /**
+ * This function is used to ask the executor to execute the given function
+ * object. The function object is executed according to the rules of the
+ * target executor object.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void defer(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ struct unspecified_bool_type_t {};
+ typedef void (*unspecified_bool_type)(unspecified_bool_type_t);
+ static void unspecified_bool_true(unspecified_bool_type_t) {}
+
+ /// Operator to test if the executor contains a valid target.
+ operator unspecified_bool_type() const BOOST_ASIO_NOEXCEPT
+ {
+ return impl_ ? &executor::unspecified_bool_true : 0;
+ }
+
+ /// Obtain type information for the target executor object.
+ /**
+ * @returns If @c *this has a target type of type @c T, <tt>typeid(T)</tt>;
+ * otherwise, <tt>typeid(void)</tt>.
+ */
+#if !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
+ const std::type_info& target_type() const BOOST_ASIO_NOEXCEPT
+ {
+ return impl_ ? impl_->target_type() : typeid(void);
+ }
+#else // !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
+ const void* target_type() const BOOST_ASIO_NOEXCEPT
+ {
+ return impl_ ? impl_->target_type() : 0;
+ }
+#endif // !defined(BOOST_ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)
+
+ /// Obtain a pointer to the target executor object.
+ /**
+ * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored
+ * executor target; otherwise, a null pointer.
+ */
+ template <typename Executor>
+ Executor* target() BOOST_ASIO_NOEXCEPT;
+
+ /// Obtain a pointer to the target executor object.
+ /**
+ * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored
+ * executor target; otherwise, a null pointer.
+ */
+ template <typename Executor>
+ const Executor* target() const BOOST_ASIO_NOEXCEPT;
+
+ /// Compare two executors for equality.
+ friend bool operator==(const executor& a,
+ const executor& b) BOOST_ASIO_NOEXCEPT
+ {
+ if (a.impl_ == b.impl_)
+ return true;
+ if (!a.impl_ || !b.impl_)
+ return false;
+ return a.impl_->equals(b.impl_);
+ }
+
+ /// Compare two executors for inequality.
+ friend bool operator!=(const executor& a,
+ const executor& b) BOOST_ASIO_NOEXCEPT
+ {
+ return !(a == b);
+ }
+
+private:
+#if !defined(GENERATING_DOCUMENTATION)
+ class function;
+ template <typename, typename> class impl;
+
+#if !defined(BOOST_ASIO_NO_TYPEID)
+ typedef const std::type_info& type_id_result_type;
+#else // !defined(BOOST_ASIO_NO_TYPEID)
+ typedef const void* type_id_result_type;
+#endif // !defined(BOOST_ASIO_NO_TYPEID)
+
+ template <typename T>
+ static type_id_result_type type_id()
+ {
+#if !defined(BOOST_ASIO_NO_TYPEID)
+ return typeid(T);
+#else // !defined(BOOST_ASIO_NO_TYPEID)
+ static int unique_id;
+ return &unique_id;
+#endif // !defined(BOOST_ASIO_NO_TYPEID)
+ }
+
+ // Base class for all polymorphic executor implementations.
+ class impl_base
+ {
+ public:
+ virtual impl_base* clone() const BOOST_ASIO_NOEXCEPT = 0;
+ virtual void destroy() BOOST_ASIO_NOEXCEPT = 0;
+ virtual execution_context& context() BOOST_ASIO_NOEXCEPT = 0;
+ virtual void on_work_started() BOOST_ASIO_NOEXCEPT = 0;
+ virtual void on_work_finished() BOOST_ASIO_NOEXCEPT = 0;
+ virtual void dispatch(BOOST_ASIO_MOVE_ARG(function)) = 0;
+ virtual void post(BOOST_ASIO_MOVE_ARG(function)) = 0;
+ virtual void defer(BOOST_ASIO_MOVE_ARG(function)) = 0;
+ virtual type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT = 0;
+ virtual void* target() BOOST_ASIO_NOEXCEPT = 0;
+ virtual const void* target() const BOOST_ASIO_NOEXCEPT = 0;
+ virtual bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT = 0;
+
+ protected:
+ impl_base(bool fast_dispatch) : fast_dispatch_(fast_dispatch) {}
+ virtual ~impl_base() {}
+
+ private:
+ friend class executor;
+ const bool fast_dispatch_;
+ };
+
+ // Helper function to check and return the implementation pointer.
+ impl_base* get_impl() const
+ {
+ if (!impl_)
+ {
+ bad_executor ex;
+ boost::asio::detail::throw_exception(ex);
+ }
+ return impl_;
+ }
+
+ // Helper function to clone another implementation.
+ impl_base* clone() const BOOST_ASIO_NOEXCEPT
+ {
+ return impl_ ? impl_->clone() : 0;
+ }
+
+ // Helper function to destroy an implementation.
+ void destroy() BOOST_ASIO_NOEXCEPT
+ {
+ if (impl_)
+ impl_->destroy();
+ }
+
+ impl_base* impl_;
+#endif // !defined(GENERATING_DOCUMENTATION)
+};
+
+} // namespace asio
+} // namespace boost
+
+BOOST_ASIO_USES_ALLOCATOR(boost::asio::executor)
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/impl/executor.hpp>
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/impl/executor.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_ASIO_EXECUTOR_HPP
diff --git a/boost/asio/executor_work_guard.hpp b/boost/asio/executor_work_guard.hpp
new file mode 100644
index 0000000000..a5e2276b88
--- /dev/null
+++ b/boost/asio/executor_work_guard.hpp
@@ -0,0 +1,171 @@
+//
+// executor_work_guard.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_EXECUTOR_WORK_GUARD_HPP
+#define BOOST_ASIO_EXECUTOR_WORK_GUARD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/is_executor.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// An object of type @c executor_work_guard controls ownership of executor work
+/// within a scope.
+template <typename Executor>
+class executor_work_guard
+{
+public:
+ /// The underlying executor type.
+ typedef Executor executor_type;
+
+ /// Constructs a @c executor_work_guard object for the specified executor.
+ /**
+ * Stores a copy of @c e and calls <tt>on_work_started()</tt> on it.
+ */
+ explicit executor_work_guard(const executor_type& e) BOOST_ASIO_NOEXCEPT
+ : executor_(e),
+ owns_(true)
+ {
+ executor_.on_work_started();
+ }
+
+ /// Copy constructor.
+ executor_work_guard(const executor_work_guard& other) BOOST_ASIO_NOEXCEPT
+ : executor_(other.executor_),
+ owns_(other.owns_)
+ {
+ if (owns_)
+ executor_.on_work_started();
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move constructor.
+ executor_work_guard(executor_work_guard&& other)
+ : executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_)),
+ owns_(other.owns_)
+ {
+ other.owns_ = false;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// 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 BOOST_ASIO_NOEXCEPT
+ {
+ return executor_;
+ }
+
+ /// Whether the executor_work_guard object owns some outstanding work.
+ bool owns_work() const BOOST_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() BOOST_ASIO_NOEXCEPT
+ {
+ if (owns_)
+ {
+ executor_.on_work_finished();
+ owns_ = false;
+ }
+ }
+
+private:
+ // Disallow assignment.
+ executor_work_guard& operator=(const executor_work_guard&);
+
+ executor_type executor_;
+ bool owns_;
+};
+
+/// Create an @ref executor_work_guard object.
+template <typename Executor>
+inline executor_work_guard<Executor> make_work_guard(const Executor& ex,
+ typename enable_if<is_executor<Executor>::value>::type* = 0)
+{
+ return executor_work_guard<Executor>(ex);
+}
+
+/// Create an @ref executor_work_guard object.
+template <typename ExecutionContext>
+inline executor_work_guard<typename ExecutionContext::executor_type>
+make_work_guard(ExecutionContext& ctx,
+ typename enable_if<
+ is_convertible<ExecutionContext&, execution_context&>::value>::type* = 0)
+{
+ return executor_work_guard<typename ExecutionContext::executor_type>(
+ ctx.get_executor());
+}
+
+/// Create an @ref executor_work_guard object.
+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 &&
+ !is_convertible<T&, execution_context&>::value>::type* = 0)
+{
+ return executor_work_guard<typename associated_executor<T>::type>(
+ associated_executor<T>::get(t));
+}
+
+/// Create an @ref executor_work_guard object.
+template <typename T, typename Executor>
+inline executor_work_guard<typename associated_executor<T, Executor>::type>
+make_work_guard(const T& t, const Executor& ex,
+ typename enable_if<is_executor<Executor>::value>::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.
+template <typename T, typename ExecutionContext>
+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 &&
+ !is_convertible<T&, execution_context&>::value>::type* = 0)
+{
+ return executor_work_guard<typename associated_executor<T,
+ typename ExecutionContext::executor_type>::type>(
+ associated_executor<T, typename ExecutionContext::executor_type>::get(
+ t, ctx.get_executor()));
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_EXECUTOR_WORK_GUARD_HPP
diff --git a/boost/asio/generic/detail/impl/endpoint.ipp b/boost/asio/generic/detail/impl/endpoint.ipp
index 3c2da4a608..7fa67628d1 100644
--- a/boost/asio/generic/detail/impl/endpoint.ipp
+++ b/boost/asio/generic/detail/impl/endpoint.ipp
@@ -95,7 +95,8 @@ void endpoint::init(const void* sock_addr,
using namespace std; // For memset and memcpy.
memset(&data_.generic, 0, sizeof(boost::asio::detail::sockaddr_storage_type));
- memcpy(&data_.generic, sock_addr, sock_addr_size);
+ if (sock_addr_size > 0)
+ memcpy(&data_.generic, sock_addr, sock_addr_size);
size_ = sock_addr_size;
protocol_ = sock_protocol;
diff --git a/boost/asio/handler_invoke_hook.hpp b/boost/asio/handler_invoke_hook.hpp
index 6605d87499..f698c2f863 100644
--- a/boost/asio/handler_invoke_hook.hpp
+++ b/boost/asio/handler_invoke_hook.hpp
@@ -27,12 +27,12 @@ namespace asio {
* @brief Default invoke function for handlers.
*
* Completion handlers for asynchronous operations are invoked by the
- * io_service associated with the corresponding object (e.g. a socket or
+ * io_context associated with the corresponding object (e.g. a socket or
* deadline_timer). Certain guarantees are made on when the handler may be
* invoked, in particular that a handler can only be invoked from a thread that
- * is currently calling @c run() on the corresponding io_service object.
+ * is currently calling @c run() on the corresponding io_context object.
* Handlers may subsequently be invoked through other objects (such as
- * io_service::strand objects) that provide additional guarantees.
+ * io_context::strand objects) that provide additional guarantees.
*
* When asynchronous operations are composed from other asynchronous
* operations, all intermediate handlers should be invoked using the same
diff --git a/boost/asio/handler_type.hpp b/boost/asio/handler_type.hpp
index 11e97e3ea0..97187574b6 100644
--- a/boost/asio/handler_type.hpp
+++ b/boost/asio/handler_type.hpp
@@ -16,99 +16,37 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
-/// Default handler type traits provided for all handlers.
+/// (Deprecated: Use two-parameter version of async_result.) Default handler
+/// type traits provided for all completion token types.
/**
* The handler_type traits class is used for determining the concrete handler
* type to be used for an asynchronous operation. It allows the handler type to
* be determined at the point where the specific completion handler signature
* is known.
*
- * This template may be specialised for user-defined handler types.
+ * This template may be specialised for user-defined completion token types.
*/
-template <typename Handler, typename Signature>
+template <typename CompletionToken, typename Signature, typename = void>
struct handler_type
{
/// The handler type for the specific signature.
- typedef Handler type;
+ typedef typename conditional<
+ is_same<CompletionToken, typename decay<CompletionToken>::type>::value,
+ decay<CompletionToken>,
+ handler_type<typename decay<CompletionToken>::type, Signature>
+ >::type::type type;
};
-#if !defined(GENERATING_DOCUMENTATION)
-
-template <typename Handler, typename Signature>
-struct handler_type<const Handler, Signature>
- : handler_type<Handler, Signature> {};
-
-template <typename Handler, typename Signature>
-struct handler_type<volatile Handler, Signature>
- : handler_type<Handler, Signature> {};
-
-template <typename Handler, typename Signature>
-struct handler_type<const volatile Handler, Signature>
- : handler_type<Handler, Signature> {};
-
-template <typename Handler, typename Signature>
-struct handler_type<const Handler&, Signature>
- : handler_type<Handler, Signature> {};
-
-template <typename Handler, typename Signature>
-struct handler_type<volatile Handler&, Signature>
- : handler_type<Handler, Signature> {};
-
-template <typename Handler, typename Signature>
-struct handler_type<const volatile Handler&, Signature>
- : handler_type<Handler, Signature> {};
-
-template <typename Handler, typename Signature>
-struct handler_type<Handler&, Signature>
- : handler_type<Handler, Signature> {};
-
-#if defined(BOOST_ASIO_HAS_MOVE)
-template <typename Handler, typename Signature>
-struct handler_type<Handler&&, Signature>
- : handler_type<Handler, Signature> {};
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
-template <typename ReturnType, typename Signature>
-struct handler_type<ReturnType(), Signature>
- : handler_type<ReturnType(*)(), Signature> {};
-
-template <typename ReturnType, typename Arg1, typename Signature>
-struct handler_type<ReturnType(Arg1), Signature>
- : handler_type<ReturnType(*)(Arg1), Signature> {};
-
-template <typename ReturnType, typename Arg1, typename Arg2, typename Signature>
-struct handler_type<ReturnType(Arg1, Arg2), Signature>
- : handler_type<ReturnType(*)(Arg1, Arg2), Signature> {};
-
-template <typename ReturnType, typename Arg1, typename Arg2, typename Arg3,
- typename Signature>
-struct handler_type<ReturnType(Arg1, Arg2, Arg3), Signature>
- : handler_type<ReturnType(*)(Arg1, Arg2, Arg3), Signature> {};
-
-template <typename ReturnType, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4, typename Signature>
-struct handler_type<ReturnType(Arg1, Arg2, Arg3, Arg4), Signature>
- : handler_type<ReturnType(*)(Arg1, Arg2, Arg3, Arg4), Signature> {};
-
-template <typename ReturnType, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4, typename Arg5, typename Signature>
-struct handler_type<ReturnType(Arg1, Arg2, Arg3, Arg4, Arg5), Signature>
- : handler_type<ReturnType(*)(Arg1, Arg2, Arg3, Arg4, Arg5), Signature> {};
-
-#endif // !defined(GENERATING_DOCUMENTATION)
-
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
-#define BOOST_ASIO_HANDLER_TYPE(h, sig) \
- typename handler_type<h, sig>::type
-
#endif // BOOST_ASIO_HANDLER_TYPE_HPP
diff --git a/boost/asio/high_resolution_timer.hpp b/boost/asio/high_resolution_timer.hpp
index 5d6cef0296..3cd57714ee 100644
--- a/boost/asio/high_resolution_timer.hpp
+++ b/boost/asio/high_resolution_timer.hpp
@@ -17,22 +17,14 @@
#include <boost/asio/detail/config.hpp>
-#if defined(BOOST_ASIO_HAS_STD_CHRONO) \
- || defined(BOOST_ASIO_HAS_BOOST_CHRONO) \
- || defined(GENERATING_DOCUMENTATION)
-
-#if defined(BOOST_ASIO_HAS_STD_CHRONO)
-# include <chrono>
-#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
-# include <boost/chrono/system_clocks.hpp>
-#endif
+#if defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)
#include <boost/asio/basic_waitable_timer.hpp>
+#include <boost/asio/detail/chrono.hpp>
namespace boost {
namespace asio {
-#if defined(GENERATING_DOCUMENTATION)
/// Typedef for a timer based on the high resolution clock.
/**
* This typedef uses the C++11 @c &lt;chrono&gt; standard library facility, if
@@ -45,21 +37,10 @@ namespace asio {
typedef basic_waitable_timer<
chrono::high_resolution_clock>
high_resolution_timer;
-#elif defined(BOOST_ASIO_HAS_STD_CHRONO)
-typedef basic_waitable_timer<
- std::chrono::high_resolution_clock>
- high_resolution_timer;
-#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
-typedef basic_waitable_timer<
- boost::chrono::high_resolution_clock>
- high_resolution_timer;
-#endif
} // namespace asio
} // namespace boost
-#endif // defined(BOOST_ASIO_HAS_STD_CHRONO)
- // || defined(BOOST_ASIO_HAS_BOOST_CHRONO)
- // || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)
#endif // BOOST_ASIO_HIGH_RESOLUTION_TIMER_HPP
diff --git a/boost/asio/impl/buffered_read_stream.hpp b/boost/asio/impl/buffered_read_stream.hpp
index 082ed0338b..0813db4fce 100644
--- a/boost/asio/impl/buffered_read_stream.hpp
+++ b/boost/asio/impl/buffered_read_stream.hpp
@@ -15,6 +15,8 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
@@ -138,6 +140,36 @@ namespace detail
}
} // namespace detail
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::buffered_fill_handler<ReadHandler>, Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(const detail::buffered_fill_handler<ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+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()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
template <typename Stream>
template <typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
@@ -149,9 +181,8 @@ buffered_read_stream<Stream>::async_fill(
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
std::size_t previous_size = storage_.size();
storage_.resize(storage_.capacity());
@@ -161,7 +192,7 @@ buffered_read_stream<Stream>::async_fill(
storage_.size() - previous_size),
detail::buffered_fill_handler<BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void (boost::system::error_code, std::size_t))>(
- storage_, previous_size, init.handler));
+ storage_, previous_size, init.completion_handler));
return init.result.get();
}
@@ -171,7 +202,8 @@ template <typename MutableBufferSequence>
std::size_t buffered_read_stream<Stream>::read_some(
const MutableBufferSequence& buffers)
{
- if (boost::asio::buffer_size(buffers) == 0)
+ using boost::asio::buffer_size;
+ if (buffer_size(buffers) == 0)
return 0;
if (storage_.empty())
@@ -187,7 +219,8 @@ std::size_t buffered_read_stream<Stream>::read_some(
{
ec = boost::system::error_code();
- if (boost::asio::buffer_size(buffers) == 0)
+ using boost::asio::buffer_size;
+ if (buffer_size(buffers) == 0)
return 0;
if (storage_.empty() && !this->fill(ec))
@@ -206,7 +239,7 @@ namespace detail
const MutableBufferSequence& buffers, ReadHandler& handler)
: storage_(storage),
buffers_(buffers),
- handler_(handler)
+ handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
{
}
@@ -296,6 +329,44 @@ namespace detail
}
} // namespace detail
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename MutableBufferSequence,
+ typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(
+ const detail::buffered_read_some_handler<
+ MutableBufferSequence, ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+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<
+ MutableBufferSequence, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
template <typename Stream>
template <typename MutableBufferSequence, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
@@ -308,24 +379,24 @@ buffered_read_stream<Stream>::async_read_some(
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- if (boost::asio::buffer_size(buffers) == 0 || !storage_.empty())
+ using boost::asio::buffer_size;
+ if (buffer_size(buffers) == 0 || !storage_.empty())
{
- next_layer_.async_read_some(boost::asio::mutable_buffers_1(0, 0),
+ next_layer_.async_read_some(BOOST_ASIO_MUTABLE_BUFFER(0, 0),
detail::buffered_read_some_handler<
MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void (boost::system::error_code, std::size_t))>(
- storage_, buffers, init.handler));
+ storage_, buffers, init.completion_handler));
}
else
{
this->async_fill(detail::buffered_read_some_handler<
MutableBufferSequence, BOOST_ASIO_HANDLER_TYPE(
ReadHandler, void (boost::system::error_code, std::size_t))>(
- storage_, buffers, init.handler));
+ storage_, buffers, init.completion_handler));
}
return init.result.get();
diff --git a/boost/asio/impl/buffered_write_stream.hpp b/boost/asio/impl/buffered_write_stream.hpp
index 22585eb6ce..baaa694538 100644
--- a/boost/asio/impl/buffered_write_stream.hpp
+++ b/boost/asio/impl/buffered_write_stream.hpp
@@ -15,6 +15,8 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
@@ -53,7 +55,7 @@ namespace detail
buffered_flush_handler(detail::buffered_stream_storage& storage,
WriteHandler& handler)
: storage_(storage),
- handler_(handler)
+ handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
{
}
@@ -122,7 +124,37 @@ namespace detail
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
-}
+} // namespace detail
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename WriteHandler, typename Allocator>
+struct associated_allocator<
+ detail::buffered_flush_handler<WriteHandler>, Allocator>
+{
+ typedef typename associated_allocator<WriteHandler, Allocator>::type type;
+
+ static type get(const detail::buffered_flush_handler<WriteHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+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()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
template <typename Stream>
template <typename WriteHandler>
@@ -135,14 +167,13 @@ buffered_write_stream<Stream>::async_flush(
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
async_write(next_layer_, buffer(storage_.data(), storage_.size()),
detail::buffered_flush_handler<BOOST_ASIO_HANDLER_TYPE(
WriteHandler, void (boost::system::error_code, std::size_t))>(
- storage_, init.handler));
+ storage_, init.completion_handler));
return init.result.get();
}
@@ -152,7 +183,8 @@ template <typename ConstBufferSequence>
std::size_t buffered_write_stream<Stream>::write_some(
const ConstBufferSequence& buffers)
{
- if (boost::asio::buffer_size(buffers) == 0)
+ using boost::asio::buffer_size;
+ if (buffer_size(buffers) == 0)
return 0;
if (storage_.size() == storage_.capacity())
@@ -168,7 +200,8 @@ std::size_t buffered_write_stream<Stream>::write_some(
{
ec = boost::system::error_code();
- if (boost::asio::buffer_size(buffers) == 0)
+ using boost::asio::buffer_size;
+ if (buffer_size(buffers) == 0)
return 0;
if (storage_.size() == storage_.capacity() && !flush(ec))
@@ -187,7 +220,7 @@ namespace detail
const ConstBufferSequence& buffers, WriteHandler& handler)
: storage_(storage),
buffers_(buffers),
- handler_(handler)
+ handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
{
}
@@ -216,9 +249,10 @@ namespace detail
}
else
{
+ using boost::asio::buffer_size;
std::size_t orig_size = storage_.size();
std::size_t space_avail = storage_.capacity() - orig_size;
- std::size_t bytes_avail = boost::asio::buffer_size(buffers_);
+ std::size_t bytes_avail = buffer_size(buffers_);
std::size_t length = bytes_avail < space_avail
? bytes_avail : space_avail;
storage_.resize(orig_size + length);
@@ -282,6 +316,44 @@ namespace detail
}
} // namespace detail
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename ConstBufferSequence,
+ typename WriteHandler, typename Allocator>
+struct associated_allocator<
+ detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<WriteHandler, Allocator>::type type;
+
+ static type get(
+ const detail::buffered_write_some_handler<
+ ConstBufferSequence, WriteHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+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<
+ ConstBufferSequence, WriteHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
template <typename Stream>
template <typename ConstBufferSequence, typename WriteHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
@@ -294,25 +366,25 @@ buffered_write_stream<Stream>::async_write_some(
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- if (boost::asio::buffer_size(buffers) == 0
+ using boost::asio::buffer_size;
+ if (buffer_size(buffers) == 0
|| storage_.size() < storage_.capacity())
{
- next_layer_.async_write_some(boost::asio::const_buffers_1(0, 0),
+ next_layer_.async_write_some(BOOST_ASIO_CONST_BUFFER(0, 0),
detail::buffered_write_some_handler<
ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE(
WriteHandler, void (boost::system::error_code, std::size_t))>(
- storage_, buffers, init.handler));
+ storage_, buffers, init.completion_handler));
}
else
{
this->async_flush(detail::buffered_write_some_handler<
ConstBufferSequence, BOOST_ASIO_HANDLER_TYPE(
WriteHandler, void (boost::system::error_code, std::size_t))>(
- storage_, buffers, init.handler));
+ storage_, buffers, init.completion_handler));
}
return init.result.get();
@@ -323,9 +395,10 @@ template <typename ConstBufferSequence>
std::size_t buffered_write_stream<Stream>::copy(
const ConstBufferSequence& buffers)
{
+ using boost::asio::buffer_size;
std::size_t orig_size = storage_.size();
std::size_t space_avail = storage_.capacity() - orig_size;
- std::size_t bytes_avail = boost::asio::buffer_size(buffers);
+ std::size_t bytes_avail = buffer_size(buffers);
std::size_t length = bytes_avail < space_avail ? bytes_avail : space_avail;
storage_.resize(orig_size + length);
return boost::asio::buffer_copy(
diff --git a/boost/asio/impl/connect.hpp b/boost/asio/impl/connect.hpp
index ba587eca02..50f1809797 100644
--- a/boost/asio/impl/connect.hpp
+++ b/boost/asio/impl/connect.hpp
@@ -15,14 +15,17 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+#include <algorithm>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
#include <boost/asio/detail/bind_handler.hpp>
-#include <boost/asio/detail/consuming_buffers.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
+#include <boost/asio/post.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -33,16 +36,100 @@ namespace detail
{
struct default_connect_condition
{
- template <typename Iterator>
- Iterator operator()(const boost::system::error_code&, Iterator next)
+ template <typename Endpoint>
+ bool operator()(const boost::system::error_code&, const Endpoint&)
{
- return next;
+ return true;
}
};
+
+ template <typename Protocol, typename Iterator>
+ inline typename Protocol::endpoint deref_connect_result(
+ Iterator iter, boost::system::error_code& ec)
+ {
+ return ec ? typename Protocol::endpoint() : *iter;
+ }
+
+ template <typename T, typename Iterator>
+ struct legacy_connect_condition_helper : T
+ {
+ typedef char (*fallback_func_type)(...);
+ operator fallback_func_type() const;
+ };
+
+ template <typename R, typename Arg1, typename Arg2, typename Iterator>
+ struct legacy_connect_condition_helper<R (*)(Arg1, Arg2), Iterator>
+ {
+ R operator()(Arg1, Arg2) const;
+ char operator()(...) const;
+ };
+
+ template <typename T, typename Iterator>
+ struct is_legacy_connect_condition
+ {
+ static char asio_connect_condition_check(char);
+ static char (&asio_connect_condition_check(Iterator))[2];
+
+ static const bool value =
+ sizeof(asio_connect_condition_check(
+ (*static_cast<legacy_connect_condition_helper<T, Iterator>*>(0))(
+ *static_cast<const boost::system::error_code*>(0),
+ *static_cast<const Iterator*>(0)))) != 1;
+ };
+
+ template <typename ConnectCondition, typename Iterator>
+ inline Iterator call_connect_condition(ConnectCondition& connect_condition,
+ const boost::system::error_code& ec, Iterator next, Iterator end,
+ typename enable_if<is_legacy_connect_condition<
+ ConnectCondition, Iterator>::value>::type* = 0)
+ {
+ if (next != end)
+ return connect_condition(ec, next);
+ return end;
+ }
+
+ template <typename ConnectCondition, typename Iterator>
+ inline Iterator call_connect_condition(ConnectCondition& connect_condition,
+ const boost::system::error_code& ec, Iterator next, Iterator end,
+ typename enable_if<!is_legacy_connect_condition<
+ ConnectCondition, Iterator>::value>::type* = 0)
+ {
+ for (;next != end; ++next)
+ if (connect_condition(ec, *next))
+ return next;
+ return end;
+ }
+}
+
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence>
+typename Protocol::endpoint connect(
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type*)
+{
+ boost::system::error_code ec;
+ typename Protocol::endpoint result = connect(s, endpoints, ec);
+ boost::asio::detail::throw_error(ec, "connect");
+ return result;
}
-template <typename Protocol, typename SocketService, typename Iterator>
-Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin)
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence>
+typename Protocol::endpoint connect(
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints, boost::system::error_code& ec,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type*)
+{
+ return detail::deref_connect_result<Protocol>(
+ connect(s, endpoints.begin(), endpoints.end(),
+ detail::default_connect_condition(), ec), ec);
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s, Iterator begin,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
boost::system::error_code ec;
Iterator result = connect(s, begin, ec);
@@ -50,15 +137,17 @@ Iterator connect(basic_socket<Protocol, SocketService>& s, Iterator begin)
return result;
}
-template <typename Protocol, typename SocketService, typename Iterator>
-inline Iterator connect(basic_socket<Protocol, SocketService>& s,
- Iterator begin, boost::system::error_code& ec)
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
+inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ Iterator begin, boost::system::error_code& ec,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
return connect(s, begin, Iterator(), detail::default_connect_condition(), ec);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol, typename SocketService, typename Iterator>
-Iterator connect(basic_socket<Protocol, SocketService>& s,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, Iterator end)
{
boost::system::error_code ec;
@@ -67,17 +156,48 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
return result;
}
-template <typename Protocol, typename SocketService, typename Iterator>
-inline Iterator connect(basic_socket<Protocol, SocketService>& s,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator>
+inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, boost::system::error_code& ec)
{
return connect(s, begin, end, detail::default_connect_condition(), ec);
}
-template <typename Protocol, typename SocketService,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename ConnectCondition>
+typename Protocol::endpoint connect(
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints, ConnectCondition connect_condition,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type*)
+{
+ boost::system::error_code ec;
+ typename Protocol::endpoint result = connect(
+ s, endpoints, connect_condition, ec);
+ boost::asio::detail::throw_error(ec, "connect");
+ return result;
+}
+
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename ConnectCondition>
+typename Protocol::endpoint connect(
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints, ConnectCondition connect_condition,
+ boost::system::error_code& ec,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type*)
+{
+ return detail::deref_connect_result<Protocol>(
+ connect(s, endpoints.begin(), endpoints.end(),
+ connect_condition, ec), ec);
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition>
-Iterator connect(basic_socket<Protocol, SocketService>& s,
- Iterator begin, ConnectCondition connect_condition)
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ Iterator begin, ConnectCondition connect_condition,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
boost::system::error_code ec;
Iterator result = connect(s, begin, connect_condition, ec);
@@ -85,18 +205,20 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
return result;
}
-template <typename Protocol, typename SocketService,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition>
-inline Iterator connect(basic_socket<Protocol, SocketService>& s,
+inline Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, ConnectCondition connect_condition,
- boost::system::error_code& ec)
+ boost::system::error_code& ec,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
return connect(s, begin, Iterator(), connect_condition, ec);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol, typename SocketService,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition>
-Iterator connect(basic_socket<Protocol, SocketService>& s,
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition)
{
boost::system::error_code ec;
@@ -105,9 +227,9 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
return result;
}
-template <typename Protocol, typename SocketService,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
typename Iterator, typename ConnectCondition>
-Iterator connect(basic_socket<Protocol, SocketService>& s,
+Iterator connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition,
boost::system::error_code& ec)
{
@@ -115,7 +237,7 @@ Iterator connect(basic_socket<Protocol, SocketService>& s,
for (Iterator iter = begin; iter != end; ++iter)
{
- iter = connect_condition(ec, iter);
+ iter = (detail::call_connect_condition(connect_condition, ec, iter, end));
if (iter != end)
{
s.close(ec);
@@ -150,8 +272,7 @@ namespace detail
void check_condition(const boost::system::error_code& ec,
Iterator& iter, Iterator& end)
{
- if (iter != end)
- iter = connect_condition_(ec, static_cast<const Iterator&>(iter));
+ iter = detail::call_connect_condition(connect_condition_, ec, iter, end);
}
private:
@@ -174,26 +295,186 @@ namespace detail
}
};
- template <typename Protocol, typename SocketService, typename Iterator,
- typename ConnectCondition, typename ComposedConnectHandler>
- class connect_op : base_from_connect_condition<ConnectCondition>
+ template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename ConnectCondition,
+ typename RangeConnectHandler>
+ class range_connect_op : base_from_connect_condition<ConnectCondition>
+ {
+ public:
+ range_connect_op(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& sock,
+ const EndpointSequence& endpoints,
+ const ConnectCondition& connect_condition,
+ RangeConnectHandler& handler)
+ : base_from_connect_condition<ConnectCondition>(connect_condition),
+ socket_(sock),
+ endpoints_(endpoints),
+ index_(0),
+ start_(0),
+ handler_(BOOST_ASIO_MOVE_CAST(RangeConnectHandler)(handler))
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ range_connect_op(const range_connect_op& other)
+ : base_from_connect_condition<ConnectCondition>(other),
+ socket_(other.socket_),
+ endpoints_(other.endpoints_),
+ index_(other.index_),
+ start_(other.start_),
+ handler_(other.handler_)
+ {
+ }
+
+ range_connect_op(range_connect_op&& other)
+ : base_from_connect_condition<ConnectCondition>(other),
+ socket_(other.socket_),
+ endpoints_(other.endpoints_),
+ index_(other.index_),
+ start_(other.start_),
+ handler_(BOOST_ASIO_MOVE_CAST(RangeConnectHandler)(other.handler_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ void operator()(boost::system::error_code ec, int start = 0)
+ {
+ typename EndpointSequence::const_iterator begin = endpoints_.begin();
+ typename EndpointSequence::const_iterator iter = begin;
+ std::advance(iter, index_);
+ typename EndpointSequence::const_iterator end = endpoints_.end();
+
+ switch (start_ = start)
+ {
+ case 1:
+ for (;;)
+ {
+ this->check_condition(ec, iter, end);
+ index_ = std::distance(begin, iter);
+
+ if (iter != end)
+ {
+ socket_.close(ec);
+ socket_.async_connect(*iter,
+ BOOST_ASIO_MOVE_CAST(range_connect_op)(*this));
+ return;
+ }
+
+ if (start)
+ {
+ ec = boost::asio::error::not_found;
+ boost::asio::post(socket_.get_executor(),
+ detail::bind_handler(
+ BOOST_ASIO_MOVE_CAST(range_connect_op)(*this), ec));
+ return;
+ }
+
+ default:
+
+ if (iter == end)
+ break;
+
+ if (!socket_.is_open())
+ {
+ ec = boost::asio::error::operation_aborted;
+ break;
+ }
+
+ if (!ec)
+ break;
+
+ ++iter;
+ ++index_;
+ }
+
+ handler_(static_cast<const boost::system::error_code&>(ec),
+ static_cast<const typename Protocol::endpoint&>(
+ ec || iter == end ? typename Protocol::endpoint() : *iter));
+ }
+ }
+
+ //private:
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket_;
+ EndpointSequence endpoints_;
+ std::size_t index_;
+ int start_;
+ RangeConnectHandler handler_;
+ };
+
+ template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename ConnectCondition,
+ typename RangeConnectHandler>
+ inline void* asio_handler_allocate(std::size_t size,
+ range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ ConnectCondition, RangeConnectHandler>* this_handler)
+ {
+ return boost_asio_handler_alloc_helpers::allocate(
+ size, this_handler->handler_);
+ }
+
+ template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename ConnectCondition,
+ typename RangeConnectHandler>
+ inline void asio_handler_deallocate(void* pointer, std::size_t size,
+ range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ ConnectCondition, RangeConnectHandler>* this_handler)
+ {
+ boost_asio_handler_alloc_helpers::deallocate(
+ pointer, size, this_handler->handler_);
+ }
+
+ template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename ConnectCondition,
+ typename RangeConnectHandler>
+ inline bool asio_handler_is_continuation(
+ range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ ConnectCondition, RangeConnectHandler>* this_handler)
+ {
+ return boost_asio_handler_cont_helpers::is_continuation(
+ this_handler->handler_);
+ }
+
+ template <typename Function, typename Protocol
+ BOOST_ASIO_SVC_TPARAM, typename EndpointSequence,
+ typename ConnectCondition, typename RangeConnectHandler>
+ inline void asio_handler_invoke(Function& function,
+ range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ ConnectCondition, RangeConnectHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ template <typename Function, typename Protocol
+ BOOST_ASIO_SVC_TPARAM, typename EndpointSequence,
+ typename ConnectCondition, typename RangeConnectHandler>
+ inline void asio_handler_invoke(const Function& function,
+ range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ ConnectCondition, RangeConnectHandler>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->handler_);
+ }
+
+ template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler>
+ class iterator_connect_op : base_from_connect_condition<ConnectCondition>
{
public:
- connect_op(basic_socket<Protocol, SocketService>& sock,
+ iterator_connect_op(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& sock,
const Iterator& begin, const Iterator& end,
const ConnectCondition& connect_condition,
- ComposedConnectHandler& handler)
+ IteratorConnectHandler& handler)
: base_from_connect_condition<ConnectCondition>(connect_condition),
socket_(sock),
iter_(begin),
end_(end),
start_(0),
- handler_(BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler))
+ handler_(BOOST_ASIO_MOVE_CAST(IteratorConnectHandler)(handler))
{
}
#if defined(BOOST_ASIO_HAS_MOVE)
- connect_op(const connect_op& other)
+ iterator_connect_op(const iterator_connect_op& other)
: base_from_connect_condition<ConnectCondition>(other),
socket_(other.socket_),
iter_(other.iter_),
@@ -203,13 +484,13 @@ namespace detail
{
}
- connect_op(connect_op&& other)
+ iterator_connect_op(iterator_connect_op&& other)
: base_from_connect_condition<ConnectCondition>(other),
socket_(other.socket_),
iter_(other.iter_),
end_(other.end_),
start_(other.start_),
- handler_(BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(other.handler_))
+ handler_(BOOST_ASIO_MOVE_CAST(IteratorConnectHandler)(other.handler_))
{
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
@@ -227,14 +508,16 @@ namespace detail
{
socket_.close(ec);
socket_.async_connect(*iter_,
- BOOST_ASIO_MOVE_CAST(connect_op)(*this));
+ BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this));
return;
}
if (start)
{
ec = boost::asio::error::not_found;
- socket_.get_io_service().post(detail::bind_handler(*this, ec));
+ boost::asio::post(socket_.get_executor(),
+ detail::bind_handler(
+ BOOST_ASIO_MOVE_CAST(iterator_connect_op)(*this), ec));
return;
}
@@ -261,164 +544,311 @@ namespace detail
}
//private:
- basic_socket<Protocol, SocketService>& socket_;
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket_;
Iterator iter_;
Iterator end_;
int start_;
- ComposedConnectHandler handler_;
+ IteratorConnectHandler handler_;
};
- template <typename Protocol, typename SocketService, typename Iterator,
- typename ConnectCondition, typename ComposedConnectHandler>
+ template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler>
inline void* asio_handler_allocate(std::size_t size,
- connect_op<Protocol, SocketService, Iterator,
- ConnectCondition, ComposedConnectHandler>* this_handler)
+ iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ ConnectCondition, IteratorConnectHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename Protocol, typename SocketService, typename Iterator,
- typename ConnectCondition, typename ComposedConnectHandler>
+ template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- connect_op<Protocol, SocketService, Iterator,
- ConnectCondition, ComposedConnectHandler>* this_handler)
+ iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ ConnectCondition, IteratorConnectHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename Protocol, typename SocketService, typename Iterator,
- typename ConnectCondition, typename ComposedConnectHandler>
+ template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler>
inline bool asio_handler_is_continuation(
- connect_op<Protocol, SocketService, Iterator,
- ConnectCondition, ComposedConnectHandler>* this_handler)
+ iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ ConnectCondition, IteratorConnectHandler>* this_handler)
{
return boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
- template <typename Function, typename Protocol,
- typename SocketService, typename Iterator,
- typename ConnectCondition, typename ComposedConnectHandler>
+ template <typename Function, typename Protocol
+ BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler>
inline void asio_handler_invoke(Function& function,
- connect_op<Protocol, SocketService, Iterator,
- ConnectCondition, ComposedConnectHandler>* this_handler)
+ iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ ConnectCondition, IteratorConnectHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
- template <typename Function, typename Protocol,
- typename SocketService, typename Iterator,
- typename ConnectCondition, typename ComposedConnectHandler>
+ template <typename Function, typename Protocol
+ BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler>
inline void asio_handler_invoke(const Function& function,
- connect_op<Protocol, SocketService, Iterator,
- ConnectCondition, ComposedConnectHandler>* this_handler)
+ iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ ConnectCondition, IteratorConnectHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
-template <typename Protocol, typename SocketService,
- typename Iterator, typename ComposedConnectHandler>
-inline BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler,
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename ConnectCondition,
+ typename RangeConnectHandler, typename Allocator>
+struct associated_allocator<
+ detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG,
+ EndpointSequence, ConnectCondition, RangeConnectHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<
+ RangeConnectHandler, Allocator>::type type;
+
+ static type get(
+ const detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG,
+ EndpointSequence, ConnectCondition, RangeConnectHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<RangeConnectHandler,
+ Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename ConnectCondition,
+ typename RangeConnectHandler, typename Executor>
+struct associated_executor<
+ detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG,
+ EndpointSequence, ConnectCondition, RangeConnectHandler>,
+ Executor>
+{
+ typedef typename associated_executor<
+ RangeConnectHandler, Executor>::type type;
+
+ static type get(
+ const detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG,
+ EndpointSequence, ConnectCondition, RangeConnectHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<RangeConnectHandler,
+ Executor>::get(h.handler_, ex);
+ }
+};
+
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename Iterator, typename ConnectCondition,
+ typename IteratorConnectHandler, typename Allocator>
+struct associated_allocator<
+ detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ ConnectCondition, IteratorConnectHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<
+ IteratorConnectHandler, Allocator>::type type;
+
+ static type get(
+ const detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG,
+ Iterator, ConnectCondition, IteratorConnectHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<IteratorConnectHandler,
+ Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename Iterator, typename ConnectCondition,
+ typename IteratorConnectHandler, typename Executor>
+struct associated_executor<
+ detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
+ ConnectCondition, IteratorConnectHandler>,
+ Executor>
+{
+ typedef typename associated_executor<
+ IteratorConnectHandler, Executor>::type type;
+
+ static type get(
+ const detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG,
+ Iterator, ConnectCondition, IteratorConnectHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<IteratorConnectHandler,
+ Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename EndpointSequence, typename RangeConnectHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
+ void (boost::system::error_code, typename Protocol::endpoint))
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints,
+ BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type*)
+{
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a RangeConnectHandler.
+ BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(
+ RangeConnectHandler, handler, typename Protocol::endpoint) type_check;
+
+ async_completion<RangeConnectHandler,
+ void (boost::system::error_code, typename Protocol::endpoint)>
+ init(handler);
+
+ detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ detail::default_connect_condition,
+ BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
+ void (boost::system::error_code, typename Protocol::endpoint))>(s,
+ endpoints, detail::default_connect_condition(),
+ init.completion_handler)(boost::system::error_code(), 1);
+
+ return init.result.get();
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename Iterator, typename IteratorConnectHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol, SocketService>& s,
- Iterator begin, BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler)
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ Iterator begin, BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
// If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ComposedConnectHandler.
- BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK(
- ComposedConnectHandler, handler, Iterator) type_check;
+ // not meet the documented type requirements for a IteratorConnectHandler.
+ BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
+ IteratorConnectHandler, handler, Iterator) type_check;
- detail::async_result_init<ComposedConnectHandler,
- void (boost::system::error_code, Iterator)> init(
- BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler));
+ async_completion<IteratorConnectHandler,
+ void (boost::system::error_code, Iterator)> init(handler);
- detail::connect_op<Protocol, SocketService, Iterator,
+ detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
detail::default_connect_condition, BOOST_ASIO_HANDLER_TYPE(
- ComposedConnectHandler, void (boost::system::error_code, Iterator))>(s,
- begin, Iterator(), detail::default_connect_condition(), init.handler)(
- boost::system::error_code(), 1);
+ IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s,
+ begin, Iterator(), detail::default_connect_condition(),
+ init.completion_handler)(boost::system::error_code(), 1);
return init.result.get();
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol, typename SocketService,
- typename Iterator, typename ComposedConnectHandler>
-inline BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM,
+ typename Iterator, typename IteratorConnectHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol, SocketService>& s,
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, Iterator end,
- BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler)
+ BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
{
// If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ComposedConnectHandler.
- BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK(
- ComposedConnectHandler, handler, Iterator) type_check;
+ // not meet the documented type requirements for a IteratorConnectHandler.
+ BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
+ IteratorConnectHandler, handler, Iterator) type_check;
- detail::async_result_init<ComposedConnectHandler,
- void (boost::system::error_code, Iterator)> init(
- BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler));
+ async_completion<IteratorConnectHandler,
+ void (boost::system::error_code, Iterator)> init(handler);
- detail::connect_op<Protocol, SocketService, Iterator,
+ detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
detail::default_connect_condition, BOOST_ASIO_HANDLER_TYPE(
- ComposedConnectHandler, void (boost::system::error_code, Iterator))>(s,
- begin, end, detail::default_connect_condition(), init.handler)(
+ IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s,
+ begin, end, detail::default_connect_condition(),
+ init.completion_handler)(boost::system::error_code(), 1);
+
+ return init.result.get();
+}
+
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename EndpointSequence,
+ typename ConnectCondition, typename RangeConnectHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(RangeConnectHandler,
+ void (boost::system::error_code, typename Protocol::endpoint))
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
+ const EndpointSequence& endpoints, ConnectCondition connect_condition,
+ BOOST_ASIO_MOVE_ARG(RangeConnectHandler) handler,
+ typename enable_if<is_endpoint_sequence<
+ EndpointSequence>::value>::type*)
+{
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a RangeConnectHandler.
+ BOOST_ASIO_RANGE_CONNECT_HANDLER_CHECK(
+ RangeConnectHandler, handler, typename Protocol::endpoint) type_check;
+
+ async_completion<RangeConnectHandler,
+ void (boost::system::error_code, typename Protocol::endpoint)>
+ init(handler);
+
+ detail::range_connect_op<Protocol BOOST_ASIO_SVC_TARG, EndpointSequence,
+ ConnectCondition, BOOST_ASIO_HANDLER_TYPE(RangeConnectHandler,
+ void (boost::system::error_code, typename Protocol::endpoint))>(s,
+ endpoints, connect_condition, init.completion_handler)(
boost::system::error_code(), 1);
return init.result.get();
}
-template <typename Protocol, typename SocketService, typename Iterator,
- typename ConnectCondition, typename ComposedConnectHandler>
-inline BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler,
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol, SocketService>& s,
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, ConnectCondition connect_condition,
- BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler)
+ BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler,
+ typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)
{
// If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ComposedConnectHandler.
- BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK(
- ComposedConnectHandler, handler, Iterator) type_check;
+ // not meet the documented type requirements for a IteratorConnectHandler.
+ BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
+ IteratorConnectHandler, handler, Iterator) type_check;
- detail::async_result_init<ComposedConnectHandler,
- void (boost::system::error_code, Iterator)> init(
- BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler));
+ async_completion<IteratorConnectHandler,
+ void (boost::system::error_code, Iterator)> init(handler);
- detail::connect_op<Protocol, SocketService, Iterator,
+ detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
ConnectCondition, BOOST_ASIO_HANDLER_TYPE(
- ComposedConnectHandler, void (boost::system::error_code, Iterator))>(s,
- begin, Iterator(), connect_condition, init.handler)(
+ IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s,
+ begin, Iterator(), connect_condition, init.completion_handler)(
boost::system::error_code(), 1);
return init.result.get();
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
-template <typename Protocol, typename SocketService, typename Iterator,
- typename ConnectCondition, typename ComposedConnectHandler>
-inline BOOST_ASIO_INITFN_RESULT_TYPE(ComposedConnectHandler,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM, typename Iterator,
+ typename ConnectCondition, typename IteratorConnectHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(IteratorConnectHandler,
void (boost::system::error_code, Iterator))
-async_connect(basic_socket<Protocol, SocketService>& s,
+async_connect(basic_socket<Protocol BOOST_ASIO_SVC_TARG>& s,
Iterator begin, Iterator end, ConnectCondition connect_condition,
- BOOST_ASIO_MOVE_ARG(ComposedConnectHandler) handler)
+ BOOST_ASIO_MOVE_ARG(IteratorConnectHandler) handler)
{
// If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ComposedConnectHandler.
- BOOST_ASIO_COMPOSED_CONNECT_HANDLER_CHECK(
- ComposedConnectHandler, handler, Iterator) type_check;
+ // not meet the documented type requirements for a IteratorConnectHandler.
+ BOOST_ASIO_ITERATOR_CONNECT_HANDLER_CHECK(
+ IteratorConnectHandler, handler, Iterator) type_check;
- detail::async_result_init<ComposedConnectHandler,
- void (boost::system::error_code, Iterator)> init(
- BOOST_ASIO_MOVE_CAST(ComposedConnectHandler)(handler));
+ async_completion<IteratorConnectHandler,
+ void (boost::system::error_code, Iterator)> init(handler);
- detail::connect_op<Protocol, SocketService, Iterator,
+ detail::iterator_connect_op<Protocol BOOST_ASIO_SVC_TARG, Iterator,
ConnectCondition, BOOST_ASIO_HANDLER_TYPE(
- ComposedConnectHandler, void (boost::system::error_code, Iterator))>(s,
- begin, end, connect_condition, init.handler)(
+ IteratorConnectHandler, void (boost::system::error_code, Iterator))>(s,
+ begin, end, connect_condition, init.completion_handler)(
boost::system::error_code(), 1);
return init.result.get();
diff --git a/boost/asio/impl/defer.hpp b/boost/asio/impl/defer.hpp
new file mode 100644
index 0000000000..afc29f965b
--- /dev/null
+++ b/boost/asio/impl/defer.hpp
@@ -0,0 +1,79 @@
+//
+// impl/defer.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_DEFER_HPP
+#define BOOST_ASIO_IMPL_DEFER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/detail/work_dispatcher.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
+ BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
+
+ async_completion<CompletionToken, void()> init(token);
+
+ typename associated_executor<handler>::type ex(
+ (get_associated_executor)(init.completion_handler));
+
+ typename associated_allocator<handler>::type alloc(
+ (get_associated_allocator)(init.completion_handler));
+
+ ex.defer(BOOST_ASIO_MOVE_CAST(handler)(init.completion_handler), alloc);
+
+ return init.result.get();
+}
+
+template <typename Executor, typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
+ const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_executor<Executor>::value>::type*)
+{
+ typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
+
+ async_completion<CompletionToken, void()> init(token);
+
+ typename associated_allocator<handler>::type alloc(
+ (get_associated_allocator)(init.completion_handler));
+
+ ex.defer(detail::work_dispatcher<handler>(init.completion_handler), alloc);
+
+ return init.result.get();
+}
+
+template <typename ExecutionContext, typename CompletionToken>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) defer(
+ ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_convertible<
+ ExecutionContext&, execution_context&>::value>::type*)
+{
+ return (defer)(ctx.get_executor(),
+ BOOST_ASIO_MOVE_CAST(CompletionToken)(token));
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_DEFER_HPP
diff --git a/boost/asio/impl/dispatch.hpp b/boost/asio/impl/dispatch.hpp
new file mode 100644
index 0000000000..5589b375e3
--- /dev/null
+++ b/boost/asio/impl/dispatch.hpp
@@ -0,0 +1,80 @@
+//
+// impl/dispatch.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_DISPATCH_HPP
+#define BOOST_ASIO_IMPL_DISPATCH_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/detail/work_dispatcher.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
+ BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
+
+ async_completion<CompletionToken, void()> init(token);
+
+ typename associated_executor<handler>::type ex(
+ (get_associated_executor)(init.completion_handler));
+
+ typename associated_allocator<handler>::type alloc(
+ (get_associated_allocator)(init.completion_handler));
+
+ ex.dispatch(BOOST_ASIO_MOVE_CAST(handler)(init.completion_handler), alloc);
+
+ return init.result.get();
+}
+
+template <typename Executor, typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
+ const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_executor<Executor>::value>::type*)
+{
+ typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
+
+ async_completion<CompletionToken, void()> init(token);
+
+ typename associated_allocator<handler>::type alloc(
+ (get_associated_allocator)(init.completion_handler));
+
+ ex.dispatch(detail::work_dispatcher<handler>(
+ init.completion_handler), alloc);
+
+ return init.result.get();
+}
+
+template <typename ExecutionContext, typename CompletionToken>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) dispatch(
+ ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_convertible<
+ ExecutionContext&, execution_context&>::value>::type*)
+{
+ return (dispatch)(ctx.get_executor(),
+ BOOST_ASIO_MOVE_CAST(CompletionToken)(token));
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_DISPATCH_HPP
diff --git a/boost/asio/impl/execution_context.hpp b/boost/asio/impl/execution_context.hpp
new file mode 100644
index 0000000000..86acfc2d6e
--- /dev/null
+++ b/boost/asio/impl/execution_context.hpp
@@ -0,0 +1,109 @@
+//
+// impl/execution_context.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_EXECUTION_CONTEXT_HPP
+#define BOOST_ASIO_IMPL_EXECUTION_CONTEXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/scoped_ptr.hpp>
+#include <boost/asio/detail/service_registry.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename Service>
+inline Service& use_service(execution_context& e)
+{
+ // Check that Service meets the necessary type requirements.
+ (void)static_cast<execution_context::service*>(static_cast<Service*>(0));
+
+ return e.service_registry_->template use_service<Service>();
+}
+
+#if !defined(GENERATING_DOCUMENTATION)
+# if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename Service, typename... Args>
+Service& make_service(execution_context& e, BOOST_ASIO_MOVE_ARG(Args)... args)
+{
+ detail::scoped_ptr<Service> svc(
+ new Service(e, BOOST_ASIO_MOVE_CAST(Args)(args)...));
+ e.service_registry_->template add_service<Service>(svc.get());
+ Service& result = *svc;
+ svc.release();
+ return result;
+}
+
+# else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename Service>
+Service& make_service(execution_context& e)
+{
+ detail::scoped_ptr<Service> svc(new Service(e));
+ e.service_registry_->template add_service<Service>(svc.get());
+ Service& result = *svc;
+ svc.release();
+ return result;
+}
+
+#define BOOST_ASIO_PRIVATE_MAKE_SERVICE_DEF(n) \
+ template <typename Service, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ Service& make_service(execution_context& e, \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ detail::scoped_ptr<Service> svc( \
+ new Service(e, BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
+ e.service_registry_->template add_service<Service>(svc.get()); \
+ Service& result = *svc; \
+ svc.release(); \
+ return result; \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_MAKE_SERVICE_DEF)
+#undef BOOST_ASIO_PRIVATE_MAKE_SERVICE_DEF
+
+# endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename Service>
+inline void add_service(execution_context& e, Service* svc)
+{
+ // Check that Service meets the necessary type requirements.
+ (void)static_cast<execution_context::service*>(static_cast<Service*>(0));
+
+ e.service_registry_->template add_service<Service>(svc);
+}
+
+template <typename Service>
+inline bool has_service(execution_context& e)
+{
+ // Check that Service meets the necessary type requirements.
+ (void)static_cast<execution_context::service*>(static_cast<Service*>(0));
+
+ return e.service_registry_->template has_service<Service>();
+}
+
+inline execution_context& execution_context::service::context()
+{
+ return owner_;
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_EXECUTION_CONTEXT_HPP
diff --git a/boost/asio/impl/execution_context.ipp b/boost/asio/impl/execution_context.ipp
new file mode 100644
index 0000000000..01e92f6604
--- /dev/null
+++ b/boost/asio/impl/execution_context.ipp
@@ -0,0 +1,84 @@
+//
+// impl/execution_context.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_EXECUTION_CONTEXT_IPP
+#define BOOST_ASIO_IMPL_EXECUTION_CONTEXT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/detail/service_registry.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+execution_context::execution_context()
+ : service_registry_(new boost::asio::detail::service_registry(*this))
+{
+}
+
+execution_context::~execution_context()
+{
+ shutdown();
+ destroy();
+ delete service_registry_;
+}
+
+void execution_context::shutdown()
+{
+ service_registry_->shutdown_services();
+}
+
+void execution_context::destroy()
+{
+ service_registry_->destroy_services();
+}
+
+void execution_context::notify_fork(
+ boost::asio::execution_context::fork_event event)
+{
+ service_registry_->notify_fork(event);
+}
+
+execution_context::service::service(execution_context& owner)
+ : owner_(owner),
+ next_(0)
+{
+}
+
+execution_context::service::~service()
+{
+}
+
+void execution_context::service::notify_fork(execution_context::fork_event)
+{
+}
+
+service_already_exists::service_already_exists()
+ : std::logic_error("Service already exists.")
+{
+}
+
+invalid_service_owner::invalid_service_owner()
+ : std::logic_error("Invalid service owner.")
+{
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_EXECUTION_CONTEXT_IPP
diff --git a/boost/asio/impl/executor.hpp b/boost/asio/impl/executor.hpp
new file mode 100644
index 0000000000..e97a7d57c9
--- /dev/null
+++ b/boost/asio/impl/executor.hpp
@@ -0,0 +1,388 @@
+//
+// impl/executor.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_EXECUTOR_HPP
+#define BOOST_ASIO_IMPL_EXECUTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/atomic_count.hpp>
+#include <boost/asio/detail/executor_op.hpp>
+#include <boost/asio/detail/global.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/recycling_allocator.hpp>
+#include <boost/asio/executor.hpp>
+#include <boost/asio/system_executor.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+
+// Lightweight, move-only function object wrapper.
+class executor::function
+{
+public:
+ template <typename F, typename Alloc>
+ explicit function(F f, const Alloc& a)
+ {
+ // Allocate and construct an operation to wrap the function.
+ typedef detail::executor_op<F, Alloc> op;
+ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
+ op_ = new (p.v) op(BOOST_ASIO_MOVE_CAST(F)(f), a);
+ p.v = 0;
+ }
+
+ function(function&& other)
+ : op_(other.op_)
+ {
+ other.op_ = 0;
+ }
+
+ ~function()
+ {
+ if (op_)
+ op_->destroy();
+ }
+
+ void operator()()
+ {
+ if (op_)
+ {
+ detail::scheduler_operation* op = op_;
+ op_ = 0;
+ op->complete(this, boost::system::error_code(), 0);
+ }
+ }
+
+private:
+ detail::scheduler_operation* op_;
+};
+
+#else // defined(BOOST_ASIO_HAS_MOVE)
+
+// Not so lightweight, copyable function object wrapper.
+class executor::function
+{
+public:
+ template <typename F, typename Alloc>
+ explicit function(const F& f, const Alloc&)
+ : impl_(new impl<F>(f))
+ {
+ }
+
+ void operator()()
+ {
+ impl_->invoke_(impl_.get());
+ }
+
+private:
+ // Base class for polymorphic function implementations.
+ struct impl_base
+ {
+ void (*invoke_)(impl_base*);
+ };
+
+ // Polymorphic function implementation.
+ template <typename F>
+ struct impl : impl_base
+ {
+ impl(const F& f)
+ : function_(f)
+ {
+ invoke_ = &function::invoke<F>;
+ }
+
+ F function_;
+ };
+
+ // Helper to invoke a function.
+ template <typename F>
+ static void invoke(impl_base* i)
+ {
+ static_cast<impl<F>*>(i)->function_();
+ }
+
+ detail::shared_ptr<impl_base> impl_;
+};
+
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+// Default polymorphic allocator implementation.
+template <typename Executor, typename Allocator>
+class executor::impl
+ : public executor::impl_base
+{
+public:
+ typedef BOOST_ASIO_REBIND_ALLOC(Allocator, impl) allocator_type;
+
+ static impl_base* create(const Executor& e, Allocator a = Allocator())
+ {
+ raw_mem mem(a);
+ impl* p = new (mem.ptr_) impl(e, a);
+ mem.ptr_ = 0;
+ return p;
+ }
+
+ impl(const Executor& e, const Allocator& a) BOOST_ASIO_NOEXCEPT
+ : impl_base(false),
+ ref_count_(1),
+ executor_(e),
+ allocator_(a)
+ {
+ }
+
+ impl_base* clone() const BOOST_ASIO_NOEXCEPT
+ {
+ ++ref_count_;
+ return const_cast<impl_base*>(static_cast<const impl_base*>(this));
+ }
+
+ void destroy() BOOST_ASIO_NOEXCEPT
+ {
+ if (--ref_count_ == 0)
+ {
+ allocator_type alloc(allocator_);
+ impl* p = this;
+ p->~impl();
+ alloc.deallocate(p, 1);
+ }
+ }
+
+ void on_work_started() BOOST_ASIO_NOEXCEPT
+ {
+ executor_.on_work_started();
+ }
+
+ void on_work_finished() BOOST_ASIO_NOEXCEPT
+ {
+ executor_.on_work_finished();
+ }
+
+ execution_context& context() BOOST_ASIO_NOEXCEPT
+ {
+ return executor_.context();
+ }
+
+ void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
+ {
+ executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ void post(BOOST_ASIO_MOVE_ARG(function) f)
+ {
+ executor_.post(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ void defer(BOOST_ASIO_MOVE_ARG(function) f)
+ {
+ executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
+ {
+ return type_id<Executor>();
+ }
+
+ void* target() BOOST_ASIO_NOEXCEPT
+ {
+ return &executor_;
+ }
+
+ const void* target() const BOOST_ASIO_NOEXCEPT
+ {
+ return &executor_;
+ }
+
+ bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
+ {
+ if (this == e)
+ return true;
+ if (target_type() != e->target_type())
+ return false;
+ return executor_ == *static_cast<const Executor*>(e->target());
+ }
+
+private:
+ mutable detail::atomic_count ref_count_;
+ Executor executor_;
+ Allocator allocator_;
+
+ struct raw_mem
+ {
+ allocator_type allocator_;
+ impl* ptr_;
+
+ explicit raw_mem(const Allocator& a)
+ : allocator_(a),
+ ptr_(allocator_.allocate(1))
+ {
+ }
+
+ ~raw_mem()
+ {
+ if (ptr_)
+ allocator_.deallocate(ptr_, 1);
+ }
+
+ private:
+ // Disallow copying and assignment.
+ raw_mem(const raw_mem&);
+ raw_mem operator=(const raw_mem&);
+ };
+};
+
+// Polymorphic allocator specialisation for system_executor.
+template <typename Allocator>
+class executor::impl<system_executor, Allocator>
+ : public executor::impl_base
+{
+public:
+ static impl_base* create(const system_executor&,
+ const Allocator& = Allocator())
+ {
+ return &detail::global<impl<system_executor, std::allocator<void> > >();
+ }
+
+ impl()
+ : impl_base(true)
+ {
+ }
+
+ impl_base* clone() const BOOST_ASIO_NOEXCEPT
+ {
+ return const_cast<impl_base*>(static_cast<const impl_base*>(this));
+ }
+
+ void destroy() BOOST_ASIO_NOEXCEPT
+ {
+ }
+
+ void on_work_started() BOOST_ASIO_NOEXCEPT
+ {
+ executor_.on_work_started();
+ }
+
+ void on_work_finished() BOOST_ASIO_NOEXCEPT
+ {
+ executor_.on_work_finished();
+ }
+
+ execution_context& context() BOOST_ASIO_NOEXCEPT
+ {
+ return executor_.context();
+ }
+
+ void dispatch(BOOST_ASIO_MOVE_ARG(function) f)
+ {
+ executor_.dispatch(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ void post(BOOST_ASIO_MOVE_ARG(function) f)
+ {
+ executor_.post(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ void defer(BOOST_ASIO_MOVE_ARG(function) f)
+ {
+ executor_.defer(BOOST_ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ type_id_result_type target_type() const BOOST_ASIO_NOEXCEPT
+ {
+ return type_id<system_executor>();
+ }
+
+ void* target() BOOST_ASIO_NOEXCEPT
+ {
+ return &executor_;
+ }
+
+ const void* target() const BOOST_ASIO_NOEXCEPT
+ {
+ return &executor_;
+ }
+
+ bool equals(const impl_base* e) const BOOST_ASIO_NOEXCEPT
+ {
+ return this == e;
+ }
+
+private:
+ system_executor executor_;
+ Allocator allocator_;
+};
+
+template <typename Executor>
+executor::executor(Executor e)
+ : impl_(impl<Executor, std::allocator<void> >::create(e))
+{
+}
+
+template <typename Executor, typename Allocator>
+executor::executor(allocator_arg_t, const Allocator& a, Executor e)
+ : impl_(impl<Executor, Allocator>::create(e, a))
+{
+}
+
+template <typename Function, typename Allocator>
+void executor::dispatch(BOOST_ASIO_MOVE_ARG(Function) f,
+ const Allocator& a) const
+{
+ impl_base* i = get_impl();
+ if (i->fast_dispatch_)
+ system_executor().dispatch(BOOST_ASIO_MOVE_CAST(Function)(f), a);
+ else
+ i->dispatch(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
+}
+
+template <typename Function, typename Allocator>
+void executor::post(BOOST_ASIO_MOVE_ARG(Function) f,
+ const Allocator& a) const
+{
+ get_impl()->post(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
+}
+
+template <typename Function, typename Allocator>
+void executor::defer(BOOST_ASIO_MOVE_ARG(Function) f,
+ const Allocator& a) const
+{
+ get_impl()->defer(function(BOOST_ASIO_MOVE_CAST(Function)(f), a));
+}
+
+template <typename Executor>
+Executor* executor::target() BOOST_ASIO_NOEXCEPT
+{
+ return impl_ && impl_->target_type() == type_id<Executor>()
+ ? static_cast<Executor*>(impl_->target()) : 0;
+}
+
+template <typename Executor>
+const Executor* executor::target() const BOOST_ASIO_NOEXCEPT
+{
+ return impl_ && impl_->target_type() == type_id<Executor>()
+ ? static_cast<Executor*>(impl_->target()) : 0;
+}
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_EXECUTOR_HPP
diff --git a/boost/asio/ssl/basic_context.hpp b/boost/asio/impl/executor.ipp
index 734398bc29..dbedbc6cf0 100644
--- a/boost/asio/ssl/basic_context.hpp
+++ b/boost/asio/impl/executor.ipp
@@ -1,6 +1,6 @@
//
-// ssl/basic_context.hpp
-// ~~~~~~~~~~~~~~~~~~~~~
+// impl/executor.ipp
+// ~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
@@ -8,35 +8,33 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_ASIO_SSL_BASIC_CONTEXT_HPP
-#define BOOST_ASIO_SSL_BASIC_CONTEXT_HPP
+#ifndef BOOST_ASIO_IMPL_EXECUTOR_IPP
+#define BOOST_ASIO_IMPL_EXECUTOR_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-
-#if defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/ssl/old/basic_context.hpp>
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/executor.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
-namespace ssl {
-
-#if defined(BOOST_ASIO_ENABLE_OLD_SSL)
-using boost::asio::ssl::old::basic_context;
+bad_executor::bad_executor() BOOST_ASIO_NOEXCEPT
+{
+}
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
+const char* bad_executor::what() const BOOST_ASIO_NOEXCEPT_OR_NOTHROW
+{
+ return "bad executor";
+}
-} // namespace ssl
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
-#endif // BOOST_ASIO_SSL_BASIC_CONTEXT_HPP
+#endif // BOOST_ASIO_IMPL_EXECUTOR_IPP
diff --git a/boost/asio/impl/handler_alloc_hook.ipp b/boost/asio/impl/handler_alloc_hook.ipp
index ddc84c75cf..d3e82e8bc2 100644
--- a/boost/asio/impl/handler_alloc_hook.ipp
+++ b/boost/asio/impl/handler_alloc_hook.ipp
@@ -16,38 +16,20 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/call_stack.hpp>
+#include <boost/asio/detail/thread_context.hpp>
+#include <boost/asio/detail/thread_info_base.hpp>
#include <boost/asio/handler_alloc_hook.hpp>
-#if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
-# if defined(BOOST_ASIO_HAS_IOCP)
-# include <boost/asio/detail/win_iocp_thread_info.hpp>
-# else // defined(BOOST_ASIO_HAS_IOCP)
-# include <boost/asio/detail/task_io_service_thread_info.hpp>
-# endif // defined(BOOST_ASIO_HAS_IOCP)
-#endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
-
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
-#if defined(BOOST_ASIO_HAS_IOCP)
-namespace detail { class win_iocp_io_service; }
-#endif // defined(BOOST_ASIO_HAS_IOCP)
-
void* asio_handler_allocate(std::size_t size, ...)
{
#if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
-# if defined(BOOST_ASIO_HAS_IOCP)
- typedef detail::win_iocp_io_service io_service_impl;
- typedef detail::win_iocp_thread_info thread_info;
-# else // defined(BOOST_ASIO_HAS_IOCP)
- typedef detail::task_io_service io_service_impl;
- typedef detail::task_io_service_thread_info thread_info;
-# endif // defined(BOOST_ASIO_HAS_IOCP)
- typedef detail::call_stack<io_service_impl, thread_info> call_stack;
- return thread_info::allocate(call_stack::top(), size);
+ return detail::thread_info_base::allocate(
+ detail::thread_context::thread_call_stack::top(), size);
#else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
return ::operator new(size);
#endif // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
@@ -56,15 +38,8 @@ void* asio_handler_allocate(std::size_t size, ...)
void asio_handler_deallocate(void* pointer, std::size_t size, ...)
{
#if !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
-# if defined(BOOST_ASIO_HAS_IOCP)
- typedef detail::win_iocp_io_service io_service_impl;
- typedef detail::win_iocp_thread_info thread_info;
-# else // defined(BOOST_ASIO_HAS_IOCP)
- typedef detail::task_io_service io_service_impl;
- typedef detail::task_io_service_thread_info thread_info;
-# endif // defined(BOOST_ASIO_HAS_IOCP)
- typedef detail::call_stack<io_service_impl, thread_info> call_stack;
- thread_info::deallocate(call_stack::top(), pointer, size);
+ detail::thread_info_base::deallocate(
+ detail::thread_context::thread_call_stack::top(), pointer, size);
#else // !defined(BOOST_ASIO_DISABLE_SMALL_BLOCK_RECYCLING)
(void)size;
::operator delete(pointer);
diff --git a/boost/asio/impl/io_context.hpp b/boost/asio/impl/io_context.hpp
new file mode 100644
index 0000000000..93e719ed80
--- /dev/null
+++ b/boost/asio/impl/io_context.hpp
@@ -0,0 +1,345 @@
+//
+// impl/io_context.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_IO_CONTEXT_HPP
+#define BOOST_ASIO_IMPL_IO_CONTEXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/completion_handler.hpp>
+#include <boost/asio/detail/executor_op.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/recycling_allocator.hpp>
+#include <boost/asio/detail/service_registry.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename Service>
+inline Service& use_service(io_context& ioc)
+{
+ // Check that Service meets the necessary type requirements.
+ (void)static_cast<execution_context::service*>(static_cast<Service*>(0));
+ (void)static_cast<const execution_context::id*>(&Service::id);
+
+ return ioc.service_registry_->template use_service<Service>(ioc);
+}
+
+template <>
+inline detail::io_context_impl& use_service<detail::io_context_impl>(
+ io_context& ioc)
+{
+ return ioc.impl_;
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_io_context.hpp>
+#else
+# include <boost/asio/detail/scheduler.hpp>
+#endif
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+inline io_context::executor_type
+io_context::get_executor() BOOST_ASIO_NOEXCEPT
+{
+ return executor_type(*this);
+}
+
+#if defined(BOOST_ASIO_HAS_CHRONO)
+
+template <typename Rep, typename Period>
+std::size_t io_context::run_for(
+ const chrono::duration<Rep, Period>& rel_time)
+{
+ return this->run_until(chrono::steady_clock::now() + rel_time);
+}
+
+template <typename Clock, typename Duration>
+std::size_t io_context::run_until(
+ const chrono::time_point<Clock, Duration>& abs_time)
+{
+ std::size_t n = 0;
+ while (this->run_one_until(abs_time))
+ if (n != (std::numeric_limits<std::size_t>::max)())
+ ++n;
+ return n;
+}
+
+template <typename Rep, typename Period>
+std::size_t io_context::run_one_for(
+ const chrono::duration<Rep, Period>& rel_time)
+{
+ return this->run_one_until(chrono::steady_clock::now() + rel_time);
+}
+
+template <typename Clock, typename Duration>
+std::size_t io_context::run_one_until(
+ const chrono::time_point<Clock, Duration>& abs_time)
+{
+ typename Clock::time_point now = Clock::now();
+ while (now < abs_time)
+ {
+ typename Clock::duration rel_time = abs_time - now;
+ if (rel_time > chrono::seconds(1))
+ rel_time = chrono::seconds(1);
+
+ boost::system::error_code ec;
+ std::size_t s = impl_.wait_one(
+ static_cast<long>(chrono::duration_cast<
+ chrono::microseconds>(rel_time).count()), ec);
+ boost::asio::detail::throw_error(ec);
+
+ if (s || impl_.stopped())
+ return s;
+
+ now = Clock::now();
+ }
+
+ return 0;
+}
+
+#endif // defined(BOOST_ASIO_HAS_CHRONO)
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+inline void io_context::reset()
+{
+ restart();
+}
+
+template <typename CompletionHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
+io_context::dispatch(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
+{
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a CompletionHandler.
+ BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
+
+ async_completion<CompletionHandler, void ()> init(handler);
+
+ if (impl_.can_dispatch())
+ {
+ detail::fenced_block b(detail::fenced_block::full);
+ boost_asio_handler_invoke_helpers::invoke(
+ init.completion_handler, init.completion_handler);
+ }
+ else
+ {
+ // Allocate and construct an operation to wrap the handler.
+ typedef detail::completion_handler<
+ typename handler_type<CompletionHandler, void ()>::type> op;
+ typename op::ptr p = { detail::addressof(init.completion_handler),
+ op::ptr::allocate(init.completion_handler), 0 };
+ p.p = new (p.v) op(init.completion_handler);
+
+ BOOST_ASIO_HANDLER_CREATION((*this, *p.p,
+ "io_context", this, 0, "dispatch"));
+
+ impl_.do_dispatch(p.p);
+ p.v = p.p = 0;
+ }
+
+ return init.result.get();
+}
+
+template <typename CompletionHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
+io_context::post(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
+{
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a CompletionHandler.
+ BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
+
+ async_completion<CompletionHandler, void ()> init(handler);
+
+ bool is_continuation =
+ boost_asio_handler_cont_helpers::is_continuation(init.completion_handler);
+
+ // Allocate and construct an operation to wrap the handler.
+ typedef detail::completion_handler<
+ typename handler_type<CompletionHandler, void ()>::type> op;
+ typename op::ptr p = { detail::addressof(init.completion_handler),
+ op::ptr::allocate(init.completion_handler), 0 };
+ p.p = new (p.v) op(init.completion_handler);
+
+ BOOST_ASIO_HANDLER_CREATION((*this, *p.p,
+ "io_context", this, 0, "post"));
+
+ impl_.post_immediate_completion(p.p, is_continuation);
+ p.v = p.p = 0;
+
+ return init.result.get();
+}
+
+template <typename Handler>
+#if defined(GENERATING_DOCUMENTATION)
+unspecified
+#else
+inline detail::wrapped_handler<io_context&, Handler>
+#endif
+io_context::wrap(Handler handler)
+{
+ return detail::wrapped_handler<io_context&, Handler>(*this, handler);
+}
+
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+inline io_context&
+io_context::executor_type::context() const BOOST_ASIO_NOEXCEPT
+{
+ return io_context_;
+}
+
+inline void
+io_context::executor_type::on_work_started() const BOOST_ASIO_NOEXCEPT
+{
+ io_context_.impl_.work_started();
+}
+
+inline void
+io_context::executor_type::on_work_finished() const BOOST_ASIO_NOEXCEPT
+{
+ io_context_.impl_.work_finished();
+}
+
+template <typename Function, typename Allocator>
+void io_context::executor_type::dispatch(
+ BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+{
+ typedef typename decay<Function>::type function_type;
+
+ // Invoke immediately if we are already inside the thread pool.
+ if (io_context_.impl_.can_dispatch())
+ {
+ // Make a local, non-const copy of the function.
+ function_type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
+
+ detail::fenced_block b(detail::fenced_block::full);
+ boost_asio_handler_invoke_helpers::invoke(tmp, tmp);
+ return;
+ }
+
+ // 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(a), op::ptr::allocate(a), 0 };
+ p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
+
+ BOOST_ASIO_HANDLER_CREATION((this->context(), *p.p,
+ "io_context", &this->context(), 0, "post"));
+
+ io_context_.impl_.post_immediate_completion(p.p, false);
+ p.v = p.p = 0;
+}
+
+template <typename Function, typename Allocator>
+void io_context::executor_type::post(
+ BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+{
+ typedef typename decay<Function>::type function_type;
+
+ // 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(a), op::ptr::allocate(a), 0 };
+ p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
+
+ BOOST_ASIO_HANDLER_CREATION((this->context(), *p.p,
+ "io_context", &this->context(), 0, "post"));
+
+ io_context_.impl_.post_immediate_completion(p.p, false);
+ p.v = p.p = 0;
+}
+
+template <typename Function, typename Allocator>
+void io_context::executor_type::defer(
+ BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+{
+ typedef typename decay<Function>::type function_type;
+
+ // 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(a), op::ptr::allocate(a), 0 };
+ p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
+
+ BOOST_ASIO_HANDLER_CREATION((this->context(), *p.p,
+ "io_context", &this->context(), 0, "defer"));
+
+ io_context_.impl_.post_immediate_completion(p.p, true);
+ p.v = p.p = 0;
+}
+
+inline bool
+io_context::executor_type::running_in_this_thread() const BOOST_ASIO_NOEXCEPT
+{
+ return io_context_.impl_.can_dispatch();
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+inline io_context::work::work(boost::asio::io_context& io_context)
+ : io_context_impl_(io_context.impl_)
+{
+ io_context_impl_.work_started();
+}
+
+inline io_context::work::work(const work& other)
+ : io_context_impl_(other.io_context_impl_)
+{
+ io_context_impl_.work_started();
+}
+
+inline io_context::work::~work()
+{
+ io_context_impl_.work_finished();
+}
+
+inline boost::asio::io_context& io_context::work::get_io_context()
+{
+ return static_cast<boost::asio::io_context&>(io_context_impl_.context());
+}
+
+inline boost::asio::io_context& io_context::work::get_io_service()
+{
+ return static_cast<boost::asio::io_context&>(io_context_impl_.context());
+}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+inline boost::asio::io_context& io_context::service::get_io_context()
+{
+ return static_cast<boost::asio::io_context&>(context());
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+inline boost::asio::io_context& io_context::service::get_io_service()
+{
+ return static_cast<boost::asio::io_context&>(context());
+}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_IO_CONTEXT_HPP
diff --git a/boost/asio/impl/io_context.ipp b/boost/asio/impl/io_context.ipp
new file mode 100644
index 0000000000..0dd24713c5
--- /dev/null
+++ b/boost/asio/impl/io_context.ipp
@@ -0,0 +1,176 @@
+//
+// impl/io_context.ipp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_IO_CONTEXT_IPP
+#define BOOST_ASIO_IMPL_IO_CONTEXT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/detail/concurrency_hint.hpp>
+#include <boost/asio/detail/limits.hpp>
+#include <boost/asio/detail/scoped_ptr.hpp>
+#include <boost/asio/detail/service_registry.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+
+#if defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_io_context.hpp>
+#else
+# include <boost/asio/detail/scheduler.hpp>
+#endif
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+io_context::io_context()
+ : impl_(add_impl(new impl_type(*this, BOOST_ASIO_CONCURRENCY_HINT_DEFAULT)))
+{
+}
+
+io_context::io_context(int concurrency_hint)
+ : impl_(add_impl(new impl_type(*this, concurrency_hint == 1
+ ? BOOST_ASIO_CONCURRENCY_HINT_1 : concurrency_hint)))
+{
+}
+
+io_context::impl_type& io_context::add_impl(io_context::impl_type* impl)
+{
+ boost::asio::detail::scoped_ptr<impl_type> scoped_impl(impl);
+ boost::asio::add_service<impl_type>(*this, scoped_impl.get());
+ return *scoped_impl.release();
+}
+
+io_context::~io_context()
+{
+}
+
+io_context::count_type io_context::run()
+{
+ boost::system::error_code ec;
+ count_type s = impl_.run(ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+io_context::count_type io_context::run(boost::system::error_code& ec)
+{
+ return impl_.run(ec);
+}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+io_context::count_type io_context::run_one()
+{
+ boost::system::error_code ec;
+ count_type s = impl_.run_one(ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+io_context::count_type io_context::run_one(boost::system::error_code& ec)
+{
+ return impl_.run_one(ec);
+}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+io_context::count_type io_context::poll()
+{
+ boost::system::error_code ec;
+ count_type s = impl_.poll(ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+io_context::count_type io_context::poll(boost::system::error_code& ec)
+{
+ return impl_.poll(ec);
+}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+io_context::count_type io_context::poll_one()
+{
+ boost::system::error_code ec;
+ count_type s = impl_.poll_one(ec);
+ boost::asio::detail::throw_error(ec);
+ return s;
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+io_context::count_type io_context::poll_one(boost::system::error_code& ec)
+{
+ return impl_.poll_one(ec);
+}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+void io_context::stop()
+{
+ impl_.stop();
+}
+
+bool io_context::stopped() const
+{
+ return impl_.stopped();
+}
+
+void io_context::restart()
+{
+ impl_.restart();
+}
+
+io_context::service::service(boost::asio::io_context& owner)
+ : execution_context::service(owner)
+{
+}
+
+io_context::service::~service()
+{
+}
+
+void io_context::service::shutdown()
+{
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ shutdown_service();
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+void io_context::service::shutdown_service()
+{
+}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+void io_context::service::notify_fork(io_context::fork_event ev)
+{
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ fork_service(ev);
+#else // !defined(BOOST_ASIO_NO_DEPRECATED)
+ (void)ev;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+void io_context::service::fork_service(io_context::fork_event)
+{
+}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_IO_CONTEXT_IPP
diff --git a/boost/asio/impl/io_service.hpp b/boost/asio/impl/io_service.hpp
deleted file mode 100644
index beee3f3978..0000000000
--- a/boost/asio/impl/io_service.hpp
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// impl/io_service.hpp
-// ~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_IMPL_IO_SERVICE_HPP
-#define BOOST_ASIO_IMPL_IO_SERVICE_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/handler_type_requirements.hpp>
-#include <boost/asio/detail/service_registry.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-
-template <typename Service>
-inline Service& use_service(io_service& ios)
-{
- // Check that Service meets the necessary type requirements.
- (void)static_cast<io_service::service*>(static_cast<Service*>(0));
- (void)static_cast<const io_service::id*>(&Service::id);
-
- return ios.service_registry_->template use_service<Service>();
-}
-
-template <>
-inline detail::io_service_impl& use_service<detail::io_service_impl>(
- io_service& ios)
-{
- return ios.impl_;
-}
-
-template <typename Service>
-inline void add_service(io_service& ios, Service* svc)
-{
- // Check that Service meets the necessary type requirements.
- (void)static_cast<io_service::service*>(static_cast<Service*>(0));
- (void)static_cast<const io_service::id*>(&Service::id);
-
- ios.service_registry_->template add_service<Service>(svc);
-}
-
-template <typename Service>
-inline bool has_service(io_service& ios)
-{
- // Check that Service meets the necessary type requirements.
- (void)static_cast<io_service::service*>(static_cast<Service*>(0));
- (void)static_cast<const io_service::id*>(&Service::id);
-
- return ios.service_registry_->template has_service<Service>();
-}
-
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#if defined(BOOST_ASIO_HAS_IOCP)
-# include <boost/asio/detail/win_iocp_io_service.hpp>
-#else
-# include <boost/asio/detail/task_io_service.hpp>
-#endif
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-
-template <typename CompletionHandler>
-inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
-io_service::dispatch(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
-{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a CompletionHandler.
- BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
-
- detail::async_result_init<
- CompletionHandler, void ()> init(
- BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
-
- impl_.dispatch(init.handler);
-
- return init.result.get();
-}
-
-template <typename CompletionHandler>
-inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
-io_service::post(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
-{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a CompletionHandler.
- BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
-
- detail::async_result_init<
- CompletionHandler, void ()> init(
- BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
-
- impl_.post(init.handler);
-
- return init.result.get();
-}
-
-template <typename Handler>
-#if defined(GENERATING_DOCUMENTATION)
-unspecified
-#else
-inline detail::wrapped_handler<io_service&, Handler>
-#endif
-io_service::wrap(Handler handler)
-{
- return detail::wrapped_handler<io_service&, Handler>(*this, handler);
-}
-
-inline io_service::work::work(boost::asio::io_service& io_service)
- : io_service_impl_(io_service.impl_)
-{
- io_service_impl_.work_started();
-}
-
-inline io_service::work::work(const work& other)
- : io_service_impl_(other.io_service_impl_)
-{
- io_service_impl_.work_started();
-}
-
-inline io_service::work::~work()
-{
- io_service_impl_.work_finished();
-}
-
-inline boost::asio::io_service& io_service::work::get_io_service()
-{
- return io_service_impl_.get_io_service();
-}
-
-inline boost::asio::io_service& io_service::service::get_io_service()
-{
- return owner_;
-}
-
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_IMPL_IO_SERVICE_HPP
diff --git a/boost/asio/impl/io_service.ipp b/boost/asio/impl/io_service.ipp
deleted file mode 100644
index 428db3f879..0000000000
--- a/boost/asio/impl/io_service.ipp
+++ /dev/null
@@ -1,157 +0,0 @@
-//
-// impl/io_service.ipp
-// ~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_IMPL_IO_SERVICE_IPP
-#define BOOST_ASIO_IMPL_IO_SERVICE_IPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/detail/limits.hpp>
-#include <boost/asio/detail/scoped_ptr.hpp>
-#include <boost/asio/detail/service_registry.hpp>
-#include <boost/asio/detail/throw_error.hpp>
-
-#if defined(BOOST_ASIO_HAS_IOCP)
-# include <boost/asio/detail/win_iocp_io_service.hpp>
-#else
-# include <boost/asio/detail/task_io_service.hpp>
-#endif
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-
-io_service::io_service()
- : service_registry_(new boost::asio::detail::service_registry(
- *this, static_cast<impl_type*>(0),
- (std::numeric_limits<std::size_t>::max)())),
- impl_(service_registry_->first_service<impl_type>())
-{
-}
-
-io_service::io_service(std::size_t concurrency_hint)
- : service_registry_(new boost::asio::detail::service_registry(
- *this, static_cast<impl_type*>(0), concurrency_hint)),
- impl_(service_registry_->first_service<impl_type>())
-{
-}
-
-io_service::~io_service()
-{
- delete service_registry_;
-}
-
-std::size_t io_service::run()
-{
- boost::system::error_code ec;
- std::size_t s = impl_.run(ec);
- boost::asio::detail::throw_error(ec);
- return s;
-}
-
-std::size_t io_service::run(boost::system::error_code& ec)
-{
- return impl_.run(ec);
-}
-
-std::size_t io_service::run_one()
-{
- boost::system::error_code ec;
- std::size_t s = impl_.run_one(ec);
- boost::asio::detail::throw_error(ec);
- return s;
-}
-
-std::size_t io_service::run_one(boost::system::error_code& ec)
-{
- return impl_.run_one(ec);
-}
-
-std::size_t io_service::poll()
-{
- boost::system::error_code ec;
- std::size_t s = impl_.poll(ec);
- boost::asio::detail::throw_error(ec);
- return s;
-}
-
-std::size_t io_service::poll(boost::system::error_code& ec)
-{
- return impl_.poll(ec);
-}
-
-std::size_t io_service::poll_one()
-{
- boost::system::error_code ec;
- std::size_t s = impl_.poll_one(ec);
- boost::asio::detail::throw_error(ec);
- return s;
-}
-
-std::size_t io_service::poll_one(boost::system::error_code& ec)
-{
- return impl_.poll_one(ec);
-}
-
-void io_service::stop()
-{
- impl_.stop();
-}
-
-bool io_service::stopped() const
-{
- return impl_.stopped();
-}
-
-void io_service::reset()
-{
- impl_.reset();
-}
-
-void io_service::notify_fork(boost::asio::io_service::fork_event event)
-{
- service_registry_->notify_fork(event);
-}
-
-io_service::service::service(boost::asio::io_service& owner)
- : owner_(owner),
- next_(0)
-{
-}
-
-io_service::service::~service()
-{
-}
-
-void io_service::service::fork_service(boost::asio::io_service::fork_event)
-{
-}
-
-service_already_exists::service_already_exists()
- : std::logic_error("Service already exists.")
-{
-}
-
-invalid_service_owner::invalid_service_owner()
- : std::logic_error("Invalid service owner.")
-{
-}
-
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_IMPL_IO_SERVICE_IPP
diff --git a/boost/asio/impl/post.hpp b/boost/asio/impl/post.hpp
new file mode 100644
index 0000000000..520633d42b
--- /dev/null
+++ b/boost/asio/impl/post.hpp
@@ -0,0 +1,79 @@
+//
+// impl/post.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_POST_HPP
+#define BOOST_ASIO_IMPL_POST_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/detail/work_dispatcher.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
+ BOOST_ASIO_MOVE_ARG(CompletionToken) token)
+{
+ typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
+
+ async_completion<CompletionToken, void()> init(token);
+
+ typename associated_executor<handler>::type ex(
+ (get_associated_executor)(init.completion_handler));
+
+ typename associated_allocator<handler>::type alloc(
+ (get_associated_allocator)(init.completion_handler));
+
+ ex.post(BOOST_ASIO_MOVE_CAST(handler)(init.completion_handler), alloc);
+
+ return init.result.get();
+}
+
+template <typename Executor, typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
+ const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_executor<Executor>::value>::type*)
+{
+ typedef BOOST_ASIO_HANDLER_TYPE(CompletionToken, void()) handler;
+
+ async_completion<CompletionToken, void()> init(token);
+
+ typename associated_allocator<handler>::type alloc(
+ (get_associated_allocator)(init.completion_handler));
+
+ ex.post(detail::work_dispatcher<handler>(init.completion_handler), alloc);
+
+ return init.result.get();
+}
+
+template <typename ExecutionContext, typename CompletionToken>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
+ ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_convertible<
+ ExecutionContext&, execution_context&>::value>::type*)
+{
+ return (post)(ctx.get_executor(),
+ BOOST_ASIO_MOVE_CAST(CompletionToken)(token));
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_POST_HPP
diff --git a/boost/asio/impl/read.hpp b/boost/asio/impl/read.hpp
index 8648e47918..886565f2e8 100644
--- a/boost/asio/impl/read.hpp
+++ b/boost/asio/impl/read.hpp
@@ -16,6 +16,8 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <algorithm>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/completion_condition.hpp>
#include <boost/asio/detail/array_fwd.hpp>
@@ -35,30 +37,46 @@
namespace boost {
namespace asio {
+namespace detail
+{
+ template <typename SyncReadStream, typename MutableBufferSequence,
+ typename MutableBufferIterator, typename CompletionCondition>
+ std::size_t read_buffer_sequence(SyncReadStream& s,
+ const MutableBufferSequence& buffers, const MutableBufferIterator&,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ boost::asio::detail::consuming_buffers<mutable_buffer,
+ MutableBufferSequence, MutableBufferIterator> tmp(buffers);
+ while (!tmp.empty())
+ {
+ if (std::size_t max_size = detail::adapt_completion_condition_result(
+ completion_condition(ec, tmp.total_consumed())))
+ tmp.consume(s.read_some(tmp.prepare(max_size), ec));
+ else
+ break;
+ }
+ return tmp.total_consumed();;
+ }
+} // namespace detail
+
template <typename SyncReadStream, typename MutableBufferSequence,
typename CompletionCondition>
std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
- CompletionCondition completion_condition, boost::system::error_code& ec)
+ CompletionCondition completion_condition, boost::system::error_code& ec,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type*)
{
- ec = boost::system::error_code();
- boost::asio::detail::consuming_buffers<
- mutable_buffer, MutableBufferSequence> tmp(buffers);
- std::size_t total_transferred = 0;
- tmp.prepare(detail::adapt_completion_condition_result(
- completion_condition(ec, total_transferred)));
- while (tmp.begin() != tmp.end())
- {
- std::size_t bytes_transferred = s.read_some(tmp, ec);
- tmp.consume(bytes_transferred);
- total_transferred += bytes_transferred;
- tmp.prepare(detail::adapt_completion_condition_result(
- completion_condition(ec, total_transferred)));
- }
- return total_transferred;
+ return detail::read_buffer_sequence(s, buffers,
+ boost::asio::buffer_sequence_begin(buffers), completion_condition, ec);
}
template <typename SyncReadStream, typename MutableBufferSequence>
-inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers)
+inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
@@ -68,7 +86,10 @@ inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers)
template <typename SyncReadStream, typename MutableBufferSequence>
inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
- boost::system::error_code& ec)
+ boost::system::error_code& ec,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type*)
{
return read(s, buffers, transfer_all(), ec);
}
@@ -76,7 +97,10 @@ inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
template <typename SyncReadStream, typename MutableBufferSequence,
typename CompletionCondition>
inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
- CompletionCondition completion_condition)
+ CompletionCondition completion_condition,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
@@ -84,19 +108,25 @@ inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
return bytes_transferred;
}
-#if !defined(BOOST_ASIO_NO_IOSTREAM)
-
-template <typename SyncReadStream, typename Allocator,
+template <typename SyncReadStream, typename DynamicBuffer,
typename CompletionCondition>
std::size_t read(SyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b,
- CompletionCondition completion_condition, boost::system::error_code& ec)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
{
+ typename decay<DynamicBuffer>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+
ec = boost::system::error_code();
std::size_t total_transferred = 0;
std::size_t max_size = detail::adapt_completion_condition_result(
completion_condition(ec, total_transferred));
- std::size_t bytes_available = read_size_helper(b, max_size);
+ std::size_t bytes_available = std::min<std::size_t>(
+ std::max<std::size_t>(512, b.capacity() - b.size()),
+ std::min<std::size_t>(max_size, b.max_size() - b.size()));
while (bytes_available > 0)
{
std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
@@ -104,27 +134,81 @@ std::size_t read(SyncReadStream& s,
total_transferred += bytes_transferred;
max_size = detail::adapt_completion_condition_result(
completion_condition(ec, total_transferred));
- bytes_available = read_size_helper(b, max_size);
+ bytes_available = std::min<std::size_t>(
+ std::max<std::size_t>(512, b.capacity() - b.size()),
+ std::min<std::size_t>(max_size, b.max_size() - b.size()));
}
return total_transferred;
}
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBuffer>
inline std::size_t read(SyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
{
boost::system::error_code ec;
- std::size_t bytes_transferred = read(s, b, transfer_all(), ec);
+ std::size_t bytes_transferred = read(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), transfer_all(), ec);
boost::asio::detail::throw_error(ec, "read");
return bytes_transferred;
}
+template <typename SyncReadStream, typename DynamicBuffer>
+inline std::size_t read(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
+{
+ return read(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ transfer_all(), ec);
+}
+
+template <typename SyncReadStream, typename DynamicBuffer,
+ typename CompletionCondition>
+inline std::size_t read(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ CompletionCondition completion_condition,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ completion_condition, ec);
+ boost::asio::detail::throw_error(ec, "read");
+ return bytes_transferred;
+}
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
+template <typename SyncReadStream, typename Allocator,
+ typename CompletionCondition>
+inline std::size_t read(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
+{
+ return read(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec);
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b)
+{
+ return read(s, basic_streambuf_ref<Allocator>(b));
+}
+
template <typename SyncReadStream, typename Allocator>
inline std::size_t read(SyncReadStream& s,
boost::asio::basic_streambuf<Allocator>& b,
boost::system::error_code& ec)
{
- return read(s, b, transfer_all(), ec);
+ return read(s, basic_streambuf_ref<Allocator>(b), ec);
}
template <typename SyncReadStream, typename Allocator,
@@ -133,18 +217,17 @@ inline std::size_t read(SyncReadStream& s,
boost::asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition)
{
- boost::system::error_code ec;
- std::size_t bytes_transferred = read(s, b, completion_condition, ec);
- boost::asio::detail::throw_error(ec, "read");
- return bytes_transferred;
+ return read(s, basic_streambuf_ref<Allocator>(b), completion_condition);
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
namespace detail
{
template <typename AsyncReadStream, typename MutableBufferSequence,
- typename CompletionCondition, typename ReadHandler>
+ typename MutableBufferIterator, typename CompletionCondition,
+ typename ReadHandler>
class read_op
: detail::base_from_completion_cond<CompletionCondition>
{
@@ -156,7 +239,6 @@ namespace detail
stream_(stream),
buffers_(buffers),
start_(0),
- total_transferred_(0),
handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
{
}
@@ -167,7 +249,6 @@ namespace detail
stream_(other.stream_),
buffers_(other.buffers_),
start_(other.start_),
- total_transferred_(other.total_transferred_),
handler_(other.handler_)
{
}
@@ -177,7 +258,6 @@ namespace detail
stream_(other.stream_),
buffers_(other.buffers_),
start_(other.start_),
- total_transferred_(other.total_transferred_),
handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
{
}
@@ -186,285 +266,39 @@ namespace detail
void operator()(const boost::system::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
+ std::size_t max_size;
switch (start_ = start)
{
case 1:
- buffers_.prepare(this->check_for_completion(ec, total_transferred_));
- for (;;)
+ max_size = this->check_for_completion(ec, buffers_.total_consumed());
+ do
{
- stream_.async_read_some(buffers_,
+ stream_.async_read_some(buffers_.prepare(max_size),
BOOST_ASIO_MOVE_CAST(read_op)(*this));
return; default:
- total_transferred_ += bytes_transferred;
buffers_.consume(bytes_transferred);
- buffers_.prepare(this->check_for_completion(ec, total_transferred_));
- if ((!ec && bytes_transferred == 0)
- || buffers_.begin() == buffers_.end())
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncReadStream& stream_;
- boost::asio::detail::consuming_buffers<
- mutable_buffer, MutableBufferSequence> buffers_;
- int start_;
- std::size_t total_transferred_;
- ReadHandler handler_;
- };
-
- template <typename AsyncReadStream,
- typename CompletionCondition, typename ReadHandler>
- class read_op<AsyncReadStream, boost::asio::mutable_buffers_1,
- CompletionCondition, ReadHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- read_op(AsyncReadStream& stream,
- const boost::asio::mutable_buffers_1& buffers,
- CompletionCondition completion_condition, ReadHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- stream_(stream),
- buffer_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- read_op(const read_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- read_op(read_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- stream_.async_read_some(
- boost::asio::buffer(buffer_ + total_transferred_, n),
- BOOST_ASIO_MOVE_CAST(read_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == boost::asio::buffer_size(buffer_))
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncReadStream& stream_;
- boost::asio::mutable_buffer buffer_;
- int start_;
- std::size_t total_transferred_;
- ReadHandler handler_;
- };
-
- template <typename AsyncReadStream, typename Elem,
- typename CompletionCondition, typename ReadHandler>
- class read_op<AsyncReadStream, boost::array<Elem, 2>,
- CompletionCondition, ReadHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- read_op(AsyncReadStream& stream, const boost::array<Elem, 2>& buffers,
- CompletionCondition completion_condition, ReadHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- stream_(stream),
- buffers_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- read_op(const read_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- read_op(read_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- typename boost::asio::detail::dependent_type<Elem,
- boost::array<boost::asio::mutable_buffer, 2> >::type bufs = {{
- boost::asio::mutable_buffer(buffers_[0]),
- boost::asio::mutable_buffer(buffers_[1]) }};
- std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
- std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
- bufs[1] = boost::asio::buffer(
- bufs[1] + (total_transferred_ < buffer_size0
- ? 0 : total_transferred_ - buffer_size0),
- n - boost::asio::buffer_size(bufs[0]));
- stream_.async_read_some(bufs, BOOST_ASIO_MOVE_CAST(read_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == buffer_size0 + buffer_size1)
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncReadStream& stream_;
- boost::array<Elem, 2> buffers_;
- int start_;
- std::size_t total_transferred_;
- ReadHandler handler_;
- };
-
-#if defined(BOOST_ASIO_HAS_STD_ARRAY)
-
- template <typename AsyncReadStream, typename Elem,
- typename CompletionCondition, typename ReadHandler>
- class read_op<AsyncReadStream, std::array<Elem, 2>,
- CompletionCondition, ReadHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- read_op(AsyncReadStream& stream, const std::array<Elem, 2>& buffers,
- CompletionCondition completion_condition, ReadHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- stream_(stream),
- buffers_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- read_op(const read_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- read_op(read_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- typename boost::asio::detail::dependent_type<Elem,
- std::array<boost::asio::mutable_buffer, 2> >::type bufs = {{
- boost::asio::mutable_buffer(buffers_[0]),
- boost::asio::mutable_buffer(buffers_[1]) }};
- std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
- std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
- bufs[1] = boost::asio::buffer(
- bufs[1] + (total_transferred_ < buffer_size0
- ? 0 : total_transferred_ - buffer_size0),
- n - boost::asio::buffer_size(bufs[0]));
- stream_.async_read_some(bufs, BOOST_ASIO_MOVE_CAST(read_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == buffer_size0 + buffer_size1)
+ if ((!ec && bytes_transferred == 0) || buffers_.empty())
break;
- }
+ max_size = this->check_for_completion(ec, buffers_.total_consumed());
+ } while (max_size > 0);
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ handler_(ec, buffers_.total_consumed());
}
}
//private:
AsyncReadStream& stream_;
- std::array<Elem, 2> buffers_;
+ boost::asio::detail::consuming_buffers<mutable_buffer,
+ MutableBufferSequence, MutableBufferIterator> buffers_;
int start_;
- std::size_t total_transferred_;
ReadHandler handler_;
};
-#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
-
template <typename AsyncReadStream, typename MutableBufferSequence,
- typename CompletionCondition, typename ReadHandler>
+ typename MutableBufferIterator, typename CompletionCondition,
+ typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
- read_op<AsyncReadStream, MutableBufferSequence,
+ read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
@@ -472,9 +306,10 @@ namespace detail
}
template <typename AsyncReadStream, typename MutableBufferSequence,
- typename CompletionCondition, typename ReadHandler>
+ typename MutableBufferIterator, typename CompletionCondition,
+ typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- read_op<AsyncReadStream, MutableBufferSequence,
+ read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
@@ -482,9 +317,10 @@ namespace detail
}
template <typename AsyncReadStream, typename MutableBufferSequence,
- typename CompletionCondition, typename ReadHandler>
+ typename MutableBufferIterator, typename CompletionCondition,
+ typename ReadHandler>
inline bool asio_handler_is_continuation(
- read_op<AsyncReadStream, MutableBufferSequence,
+ read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
@@ -493,10 +329,10 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename MutableBufferSequence, typename CompletionCondition,
- typename ReadHandler>
+ typename MutableBufferSequence, typename MutableBufferIterator,
+ typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
- read_op<AsyncReadStream, MutableBufferSequence,
+ read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
@@ -504,38 +340,93 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename MutableBufferSequence, typename CompletionCondition,
- typename ReadHandler>
+ typename MutableBufferSequence, typename MutableBufferIterator,
+ typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
- read_op<AsyncReadStream, MutableBufferSequence,
+ read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename MutableBufferIterator, typename CompletionCondition,
+ typename ReadHandler>
+ inline void start_read_buffer_sequence_op(AsyncReadStream& stream,
+ const MutableBufferSequence& buffers, const MutableBufferIterator&,
+ CompletionCondition completion_condition, ReadHandler& handler)
+ {
+ detail::read_op<AsyncReadStream, MutableBufferSequence,
+ MutableBufferIterator, CompletionCondition, ReadHandler>(
+ stream, buffers, completion_condition, handler)(
+ boost::system::error_code(), 0, 1);
+ }
} // namespace detail
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename MutableBufferSequence,
+ typename MutableBufferIterator, typename CompletionCondition,
+ typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_op<AsyncReadStream, MutableBufferSequence,
+ MutableBufferIterator, CompletionCondition, ReadHandler>,
+ Allocator>
+{
+ 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()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+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>
+{
+ typedef typename associated_executor<ReadHandler, Executor>::type type;
+
+ static type get(
+ const detail::read_op<AsyncReadStream, MutableBufferSequence,
+ MutableBufferIterator, CompletionCondition, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
template <typename AsyncReadStream, typename MutableBufferSequence,
typename CompletionCondition, typename ReadHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
CompletionCondition completion_condition,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- detail::read_op<AsyncReadStream, MutableBufferSequence,
- CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
- ReadHandler, void (boost::system::error_code, std::size_t))>(
- s, buffers, completion_condition, init.handler)(
- boost::system::error_code(), 0, 1);
+ detail::start_read_buffer_sequence_op(s, buffers,
+ boost::asio::buffer_sequence_begin(buffers), completion_condition,
+ init.completion_handler);
return init.result.get();
}
@@ -545,42 +436,41 @@ template <typename AsyncReadStream, typename MutableBufferSequence,
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- detail::read_op<AsyncReadStream, MutableBufferSequence,
- detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(
- ReadHandler, void (boost::system::error_code, std::size_t))>(
- s, buffers, transfer_all(), init.handler)(
- boost::system::error_code(), 0, 1);
+ detail::start_read_buffer_sequence_op(s, buffers,
+ boost::asio::buffer_sequence_begin(buffers), transfer_all(),
+ init.completion_handler);
return init.result.get();
}
-#if !defined(BOOST_ASIO_NO_IOSTREAM)
-
namespace detail
{
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler>
- class read_streambuf_op
+ class read_dynbuf_op
: detail::base_from_completion_cond<CompletionCondition>
{
public:
- read_streambuf_op(AsyncReadStream& stream,
- basic_streambuf<Allocator>& streambuf,
+ template <typename BufferSequence>
+ read_dynbuf_op(AsyncReadStream& stream,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
CompletionCondition completion_condition, ReadHandler& handler)
: detail::base_from_completion_cond<
CompletionCondition>(completion_condition),
stream_(stream),
- streambuf_(streambuf),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
start_(0),
total_transferred_(0),
handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
@@ -588,20 +478,20 @@ namespace detail
}
#if defined(BOOST_ASIO_HAS_MOVE)
- read_streambuf_op(const read_streambuf_op& other)
+ read_dynbuf_op(const read_dynbuf_op& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
stream_(other.stream_),
- streambuf_(other.streambuf_),
+ buffers_(other.buffers_),
start_(other.start_),
total_transferred_(other.total_transferred_),
handler_(other.handler_)
{
}
- read_streambuf_op(read_streambuf_op&& other)
+ read_dynbuf_op(read_dynbuf_op&& other)
: detail::base_from_completion_cond<CompletionCondition>(other),
stream_(other.stream_),
- streambuf_(other.streambuf_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
start_(other.start_),
total_transferred_(other.total_transferred_),
handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
@@ -617,16 +507,24 @@ namespace detail
{
case 1:
max_size = this->check_for_completion(ec, total_transferred_);
- bytes_available = read_size_helper(streambuf_, max_size);
+ bytes_available = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(max_size,
+ buffers_.max_size() - buffers_.size()));
for (;;)
{
- stream_.async_read_some(streambuf_.prepare(bytes_available),
- BOOST_ASIO_MOVE_CAST(read_streambuf_op)(*this));
+ stream_.async_read_some(buffers_.prepare(bytes_available),
+ BOOST_ASIO_MOVE_CAST(read_dynbuf_op)(*this));
return; default:
total_transferred_ += bytes_transferred;
- streambuf_.commit(bytes_transferred);
+ buffers_.commit(bytes_transferred);
max_size = this->check_for_completion(ec, total_transferred_);
- bytes_available = read_size_helper(streambuf_, max_size);
+ bytes_available = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(max_size,
+ buffers_.max_size() - buffers_.size()));
if ((!ec && bytes_transferred == 0) || bytes_available == 0)
break;
}
@@ -637,36 +535,36 @@ namespace detail
//private:
AsyncReadStream& stream_;
- boost::asio::basic_streambuf<Allocator>& streambuf_;
+ DynamicBuffer buffers_;
int start_;
std::size_t total_transferred_;
ReadHandler handler_;
};
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
- read_streambuf_op<AsyncReadStream, Allocator,
+ read_dynbuf_op<AsyncReadStream, DynamicBuffer,
CompletionCondition, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- read_streambuf_op<AsyncReadStream, Allocator,
+ read_dynbuf_op<AsyncReadStream, DynamicBuffer,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler>
inline bool asio_handler_is_continuation(
- read_streambuf_op<AsyncReadStream, Allocator,
+ read_dynbuf_op<AsyncReadStream, DynamicBuffer,
CompletionCondition, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
@@ -675,9 +573,10 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename Allocator, typename CompletionCondition, typename ReadHandler>
+ typename DynamicBuffer, typename CompletionCondition,
+ typename ReadHandler>
inline void asio_handler_invoke(Function& function,
- read_streambuf_op<AsyncReadStream, Allocator,
+ read_dynbuf_op<AsyncReadStream, DynamicBuffer,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
@@ -685,9 +584,10 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename Allocator, typename CompletionCondition, typename ReadHandler>
+ typename DynamicBuffer, typename CompletionCondition,
+ typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
- read_streambuf_op<AsyncReadStream, Allocator,
+ read_dynbuf_op<AsyncReadStream, DynamicBuffer,
CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
@@ -695,57 +595,119 @@ namespace detail
}
} // namespace detail
-template <typename AsyncReadStream, typename Allocator,
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename CompletionCondition, typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_dynbuf_op<AsyncReadStream,
+ DynamicBuffer, CompletionCondition, ReadHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(
+ const detail::read_dynbuf_op<AsyncReadStream,
+ DynamicBuffer, CompletionCondition, ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename CompletionCondition, typename ReadHandler, typename Executor>
+struct associated_executor<
+ detail::read_dynbuf_op<AsyncReadStream,
+ DynamicBuffer, CompletionCondition, ReadHandler>,
+ Executor>
+{
+ typedef typename associated_executor<ReadHandler, Executor>::type type;
+
+ static type get(
+ const detail::read_dynbuf_op<AsyncReadStream,
+ DynamicBuffer, CompletionCondition, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read(AsyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
+{
+ return async_read(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ transfer_all(), BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+template <typename AsyncReadStream, typename DynamicBuffer,
typename CompletionCondition, typename ReadHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read(AsyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
CompletionCondition completion_condition,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- detail::read_streambuf_op<AsyncReadStream, Allocator,
- CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
- ReadHandler, void (boost::system::error_code, std::size_t))>(
- s, b, completion_condition, init.handler)(
- boost::system::error_code(), 0, 1);
+ detail::read_dynbuf_op<AsyncReadStream,
+ typename decay<DynamicBuffer>::type,
+ CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
+ ReadHandler, void (boost::system::error_code, std::size_t))>(
+ s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ completion_condition, init.completion_handler)(
+ boost::system::error_code(), 0, 1);
return init.result.get();
}
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
-async_read(AsyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b,
+async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a ReadHandler.
- BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
-
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
+ return async_read(s, basic_streambuf_ref<Allocator>(b),
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+}
- detail::read_streambuf_op<AsyncReadStream, Allocator,
- detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(
- ReadHandler, void (boost::system::error_code, std::size_t))>(
- s, b, transfer_all(), init.handler)(
- boost::system::error_code(), 0, 1);
-
- return init.result.get();
+template <typename AsyncReadStream, typename Allocator,
+ typename CompletionCondition, typename ReadHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+{
+ return async_read(s, basic_streambuf_ref<Allocator>(b),
+ completion_condition, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
} // namespace asio
} // namespace boost
diff --git a/boost/asio/impl/read_at.hpp b/boost/asio/impl/read_at.hpp
index 0ec8a94e44..457bc056f4 100644
--- a/boost/asio/impl/read_at.hpp
+++ b/boost/asio/impl/read_at.hpp
@@ -16,6 +16,8 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <algorithm>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/completion_condition.hpp>
#include <boost/asio/detail/array_fwd.hpp>
@@ -35,28 +37,41 @@
namespace boost {
namespace asio {
+namespace detail
+{
+ template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
+ typename MutableBufferIterator, typename CompletionCondition>
+ std::size_t read_at_buffer_sequence(SyncRandomAccessReadDevice& d,
+ uint64_t offset, const MutableBufferSequence& buffers,
+ const MutableBufferIterator&, CompletionCondition completion_condition,
+ boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ boost::asio::detail::consuming_buffers<mutable_buffer,
+ MutableBufferSequence, MutableBufferIterator> tmp(buffers);
+ while (!tmp.empty())
+ {
+ if (std::size_t max_size = detail::adapt_completion_condition_result(
+ completion_condition(ec, tmp.total_consumed())))
+ {
+ tmp.consume(d.read_some_at(offset + tmp.total_consumed(),
+ tmp.prepare(max_size), ec));
+ }
+ else
+ break;
+ }
+ return tmp.total_consumed();;
+ }
+} // namespace detail
+
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,
typename CompletionCondition>
std::size_t read_at(SyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
CompletionCondition completion_condition, boost::system::error_code& ec)
{
- ec = boost::system::error_code();
- boost::asio::detail::consuming_buffers<
- mutable_buffer, MutableBufferSequence> tmp(buffers);
- std::size_t total_transferred = 0;
- tmp.prepare(detail::adapt_completion_condition_result(
- completion_condition(ec, total_transferred)));
- while (tmp.begin() != tmp.end())
- {
- std::size_t bytes_transferred = d.read_some_at(
- offset + total_transferred, tmp, ec);
- tmp.consume(bytes_transferred);
- total_transferred += bytes_transferred;
- tmp.prepare(detail::adapt_completion_condition_result(
- completion_condition(ec, total_transferred)));
- }
- return total_transferred;
+ return detail::read_at_buffer_sequence(d, offset, buffers,
+ boost::asio::buffer_sequence_begin(buffers), completion_condition, ec);
}
template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>
@@ -91,6 +106,7 @@ inline std::size_t read_at(SyncRandomAccessReadDevice& d,
return bytes_transferred;
}
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
template <typename SyncRandomAccessReadDevice, typename Allocator,
@@ -150,12 +166,13 @@ inline std::size_t read_at(SyncRandomAccessReadDevice& d,
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
namespace detail
{
template <typename AsyncRandomAccessReadDevice,
- typename MutableBufferSequence, typename CompletionCondition,
- typename ReadHandler>
+ typename MutableBufferSequence, typename MutableBufferIterator,
+ typename CompletionCondition, typename ReadHandler>
class read_at_op
: detail::base_from_completion_cond<CompletionCondition>
{
@@ -169,7 +186,6 @@ namespace detail
offset_(offset),
buffers_(buffers),
start_(0),
- total_transferred_(0),
handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
{
}
@@ -181,7 +197,6 @@ namespace detail
offset_(other.offset_),
buffers_(other.buffers_),
start_(other.start_),
- total_transferred_(other.total_transferred_),
handler_(other.handler_)
{
}
@@ -192,7 +207,6 @@ namespace detail
offset_(other.offset_),
buffers_(other.buffers_),
start_(other.start_),
- total_transferred_(other.total_transferred_),
handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
{
}
@@ -201,326 +215,64 @@ namespace detail
void operator()(const boost::system::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
+ std::size_t max_size;
switch (start_ = start)
{
case 1:
- buffers_.prepare(this->check_for_completion(ec, total_transferred_));
- for (;;)
+ max_size = this->check_for_completion(ec, buffers_.total_consumed());
+ do
{
- device_.async_read_some_at(offset_ + total_transferred_,
- buffers_, BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
+ device_.async_read_some_at(
+ offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
+ BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
return; default:
- total_transferred_ += bytes_transferred;
buffers_.consume(bytes_transferred);
- buffers_.prepare(this->check_for_completion(ec, total_transferred_));
- if ((!ec && bytes_transferred == 0)
- || buffers_.begin() == buffers_.end())
+ if ((!ec && bytes_transferred == 0) || buffers_.empty())
break;
- }
+ max_size = this->check_for_completion(ec, buffers_.total_consumed());
+ } while (max_size > 0);
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ handler_(ec, buffers_.total_consumed());
}
}
//private:
AsyncRandomAccessReadDevice& device_;
uint64_t offset_;
- boost::asio::detail::consuming_buffers<
- mutable_buffer, MutableBufferSequence> buffers_;
+ boost::asio::detail::consuming_buffers<mutable_buffer,
+ MutableBufferSequence, MutableBufferIterator> buffers_;
int start_;
- std::size_t total_transferred_;
ReadHandler handler_;
};
template <typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename MutableBufferIterator,
typename CompletionCondition, typename ReadHandler>
- class read_at_op<AsyncRandomAccessReadDevice,
- boost::asio::mutable_buffers_1, CompletionCondition, ReadHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- read_at_op(AsyncRandomAccessReadDevice& device,
- uint64_t offset, const boost::asio::mutable_buffers_1& buffers,
- CompletionCondition completion_condition, ReadHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- device_(device),
- offset_(offset),
- buffer_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- read_at_op(const read_at_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- read_at_op(read_at_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- device_.async_read_some_at(offset_ + total_transferred_,
- boost::asio::buffer(buffer_ + total_transferred_, n),
- BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == boost::asio::buffer_size(buffer_))
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncRandomAccessReadDevice& device_;
- uint64_t offset_;
- boost::asio::mutable_buffer buffer_;
- int start_;
- std::size_t total_transferred_;
- ReadHandler handler_;
- };
-
- template <typename AsyncRandomAccessReadDevice, typename Elem,
- typename CompletionCondition, typename ReadHandler>
- class read_at_op<AsyncRandomAccessReadDevice, boost::array<Elem, 2>,
- CompletionCondition, ReadHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- read_at_op(AsyncRandomAccessReadDevice& device,
- uint64_t offset, const boost::array<Elem, 2>& buffers,
- CompletionCondition completion_condition, ReadHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- device_(device),
- offset_(offset),
- buffers_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- read_at_op(const read_at_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- read_at_op(read_at_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- typename boost::asio::detail::dependent_type<Elem,
- boost::array<boost::asio::mutable_buffer, 2> >::type bufs = {{
- boost::asio::mutable_buffer(buffers_[0]),
- boost::asio::mutable_buffer(buffers_[1]) }};
- std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
- std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
- bufs[1] = boost::asio::buffer(
- bufs[1] + (total_transferred_ < buffer_size0
- ? 0 : total_transferred_ - buffer_size0),
- n - boost::asio::buffer_size(bufs[0]));
- device_.async_read_some_at(offset_ + total_transferred_,
- bufs, BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == buffer_size0 + buffer_size1)
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncRandomAccessReadDevice& device_;
- uint64_t offset_;
- boost::array<Elem, 2> buffers_;
- int start_;
- std::size_t total_transferred_;
- ReadHandler handler_;
- };
-
-#if defined(BOOST_ASIO_HAS_STD_ARRAY)
-
- template <typename AsyncRandomAccessReadDevice, typename Elem,
- typename CompletionCondition, typename ReadHandler>
- class read_at_op<AsyncRandomAccessReadDevice, std::array<Elem, 2>,
- CompletionCondition, ReadHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- read_at_op(AsyncRandomAccessReadDevice& device,
- uint64_t offset, const std::array<Elem, 2>& buffers,
- CompletionCondition completion_condition, ReadHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- device_(device),
- offset_(offset),
- buffers_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- read_at_op(const read_at_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- read_at_op(read_at_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(ReadHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- typename boost::asio::detail::dependent_type<Elem,
- std::array<boost::asio::mutable_buffer, 2> >::type bufs = {{
- boost::asio::mutable_buffer(buffers_[0]),
- boost::asio::mutable_buffer(buffers_[1]) }};
- std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
- std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
- bufs[1] = boost::asio::buffer(
- bufs[1] + (total_transferred_ < buffer_size0
- ? 0 : total_transferred_ - buffer_size0),
- n - boost::asio::buffer_size(bufs[0]));
- device_.async_read_some_at(offset_ + total_transferred_,
- bufs, BOOST_ASIO_MOVE_CAST(read_at_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == buffer_size0 + buffer_size1)
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncRandomAccessReadDevice& device_;
- uint64_t offset_;
- std::array<Elem, 2> buffers_;
- int start_;
- std::size_t total_transferred_;
- ReadHandler handler_;
- };
-
-#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
-
- template <typename AsyncRandomAccessReadDevice,
- typename MutableBufferSequence, typename CompletionCondition,
- typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
- CompletionCondition, ReadHandler>* this_handler)
+ MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
template <typename AsyncRandomAccessReadDevice,
- typename MutableBufferSequence, typename CompletionCondition,
- typename ReadHandler>
+ typename MutableBufferSequence, typename MutableBufferIterator,
+ typename CompletionCondition, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
- CompletionCondition, ReadHandler>* this_handler)
+ MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
template <typename AsyncRandomAccessReadDevice,
- typename MutableBufferSequence, typename CompletionCondition,
- typename ReadHandler>
+ typename MutableBufferSequence, typename MutableBufferIterator,
+ typename CompletionCondition, typename ReadHandler>
inline bool asio_handler_is_continuation(
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
- CompletionCondition, ReadHandler>* this_handler)
+ MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: boost_asio_handler_cont_helpers::is_continuation(
@@ -528,42 +280,86 @@ namespace detail
}
template <typename Function, typename AsyncRandomAccessReadDevice,
- typename MutableBufferSequence, typename CompletionCondition,
- typename ReadHandler>
+ typename MutableBufferSequence, typename MutableBufferIterator,
+ typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
- CompletionCondition, ReadHandler>* this_handler)
+ MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncRandomAccessReadDevice,
- typename MutableBufferSequence, typename CompletionCondition,
- typename ReadHandler>
+ typename MutableBufferSequence, typename MutableBufferIterator,
+ typename CompletionCondition, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
- CompletionCondition, ReadHandler>* this_handler)
+ MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename AsyncRandomAccessReadDevice,
- typename MutableBufferSequence, typename CompletionCondition,
- typename ReadHandler>
- inline read_at_op<AsyncRandomAccessReadDevice,
- MutableBufferSequence, CompletionCondition, ReadHandler>
- make_read_at_op(AsyncRandomAccessReadDevice& d,
+ typename MutableBufferSequence, typename MutableBufferIterator,
+ typename CompletionCondition, typename ReadHandler>
+ inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
- CompletionCondition completion_condition, ReadHandler handler)
+ const MutableBufferIterator&, CompletionCondition completion_condition,
+ ReadHandler& handler)
{
- return read_at_op<AsyncRandomAccessReadDevice,
- MutableBufferSequence, CompletionCondition, ReadHandler>(
- d, offset, buffers, completion_condition, handler);
+ detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
+ MutableBufferIterator, CompletionCondition, ReadHandler>(
+ d, offset, buffers, completion_condition, handler)(
+ boost::system::error_code(), 0, 1);
}
} // namespace detail
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncRandomAccessReadDevice,
+ typename MutableBufferSequence, typename MutableBufferIterator,
+ typename CompletionCondition, typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
+ MutableBufferIterator, CompletionCondition, ReadHandler>,
+ Allocator>
+{
+ 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()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+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>
+{
+ 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()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,
typename CompletionCondition, typename ReadHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
@@ -577,15 +373,12 @@ async_read_at(AsyncRandomAccessReadDevice& d,
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
- CompletionCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- d, offset, buffers, completion_condition, init.handler)(
- boost::system::error_code(), 0, 1);
+ detail::start_read_at_buffer_sequence_op(d, offset, buffers,
+ boost::asio::buffer_sequence_begin(buffers), completion_condition,
+ init.completion_handler);
return init.result.get();
}
@@ -602,19 +395,17 @@ async_read_at(AsyncRandomAccessReadDevice& d,
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,
- detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- d, offset, buffers, transfer_all(), init.handler)(
- boost::system::error_code(), 0, 1);
+ detail::start_read_at_buffer_sequence_op(d, offset, buffers,
+ boost::asio::buffer_sequence_begin(buffers), transfer_all(),
+ init.completion_handler);
return init.result.get();
}
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
namespace detail
@@ -751,6 +542,46 @@ namespace detail
}
} // namespace detail
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncRandomAccessReadDevice, typename Allocator,
+ typename CompletionCondition, typename ReadHandler, typename Allocator1>
+struct associated_allocator<
+ detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
+ Allocator, CompletionCondition, ReadHandler>,
+ Allocator1>
+{
+ 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()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncRandomAccessReadDevice, typename Executor,
+ typename CompletionCondition, typename ReadHandler, typename Executor1>
+struct associated_executor<
+ detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
+ Executor, CompletionCondition, ReadHandler>,
+ Executor1>
+{
+ typedef typename associated_executor<ReadHandler, Executor1>::type type;
+
+ static type get(
+ const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,
+ Executor, CompletionCondition, ReadHandler>& h,
+ const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
@@ -764,14 +595,13 @@ async_read_at(AsyncRandomAccessReadDevice& d,
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
CompletionCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))>(
- d, offset, b, completion_condition, init.handler)(
+ d, offset, b, completion_condition, init.completion_handler)(
boost::system::error_code(), 0, 1);
return init.result.get();
@@ -789,20 +619,20 @@ async_read_at(AsyncRandomAccessReadDevice& d,
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,
detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))>(
- d, offset, b, transfer_all(), init.handler)(
+ d, offset, b, transfer_all(), init.completion_handler)(
boost::system::error_code(), 0, 1);
return init.result.get();
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
} // namespace asio
} // namespace boost
diff --git a/boost/asio/impl/read_until.hpp b/boost/asio/impl/read_until.hpp
index 737dedcdf2..c8a409f46b 100644
--- a/boost/asio/impl/read_until.hpp
+++ b/boost/asio/impl/read_until.hpp
@@ -19,6 +19,8 @@
#include <string>
#include <vector>
#include <utility>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/buffers_iterator.hpp>
#include <boost/asio/detail/bind_handler.hpp>
@@ -34,32 +36,35 @@
namespace boost {
namespace asio {
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBuffer>
inline std::size_t read_until(SyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, char delim)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, char delim)
{
boost::system::error_code ec;
- std::size_t bytes_transferred = read_until(s, b, delim, ec);
+ std::size_t bytes_transferred = read_until(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), delim, ec);
boost::asio::detail::throw_error(ec, "read_until");
return bytes_transferred;
}
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBuffer>
std::size_t read_until(SyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, char delim,
- boost::system::error_code& ec)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ char delim, boost::system::error_code& ec)
{
+ typename decay<DynamicBuffer>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+
std::size_t search_position = 0;
for (;;)
{
// Determine the range of the data to be searched.
- typedef typename boost::asio::basic_streambuf<
- Allocator>::const_buffers_type const_buffers_type;
- typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
- const_buffers_type buffers = b.data();
- iterator begin = iterator::begin(buffers);
+ typedef typename DynamicBuffer::const_buffers_type buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers = b.data();
+ iterator begin = iterator::begin(data_buffers);
iterator start_pos = begin + search_position;
- iterator end = iterator::end(buffers);
+ iterator end = iterator::end(data_buffers);
// Look for a match.
iterator iter = std::find(start_pos, end, delim);
@@ -83,19 +88,23 @@ std::size_t read_until(SyncReadStream& s,
}
// Need more data.
- std::size_t bytes_to_read = read_size_helper(b, 65536);
+ std::size_t bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512, b.capacity() - b.size()),
+ std::min<std::size_t>(65536, b.max_size() - b.size()));
b.commit(s.read_some(b.prepare(bytes_to_read), ec));
if (ec)
return 0;
}
}
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBuffer>
inline std::size_t read_until(SyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, const std::string& delim)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_STRING_VIEW_PARAM delim)
{
boost::system::error_code ec;
- std::size_t bytes_transferred = read_until(s, b, delim, ec);
+ std::size_t bytes_transferred = read_until(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), delim, ec);
boost::asio::detail::throw_error(ec, "read_until");
return bytes_transferred;
}
@@ -135,22 +144,24 @@ namespace detail
}
} // namespace detail
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBuffer>
std::size_t read_until(SyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, const std::string& delim,
- boost::system::error_code& ec)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec)
{
+ typename decay<DynamicBuffer>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+
std::size_t search_position = 0;
for (;;)
{
// Determine the range of the data to be searched.
- typedef typename boost::asio::basic_streambuf<
- Allocator>::const_buffers_type const_buffers_type;
- typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
- const_buffers_type buffers = b.data();
- iterator begin = iterator::begin(buffers);
+ typedef typename DynamicBuffer::const_buffers_type buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers = b.data();
+ iterator begin = iterator::begin(data_buffers);
iterator start_pos = begin + search_position;
- iterator end = iterator::end(buffers);
+ iterator end = iterator::end(data_buffers);
// Look for a match.
std::pair<iterator, bool> result = detail::partial_search(
@@ -183,41 +194,48 @@ std::size_t read_until(SyncReadStream& s,
}
// Need more data.
- std::size_t bytes_to_read = read_size_helper(b, 65536);
+ std::size_t bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512, b.capacity() - b.size()),
+ std::min<std::size_t>(65536, b.max_size() - b.size()));
b.commit(s.read_some(b.prepare(bytes_to_read), ec));
if (ec)
return 0;
}
}
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if defined(BOOST_ASIO_HAS_BOOST_REGEX)
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBuffer>
inline std::size_t read_until(SyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ const boost::regex& expr)
{
boost::system::error_code ec;
- std::size_t bytes_transferred = read_until(s, b, expr, ec);
+ std::size_t bytes_transferred = read_until(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers), expr, ec);
boost::asio::detail::throw_error(ec, "read_until");
return bytes_transferred;
}
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBuffer>
std::size_t read_until(SyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
- boost::system::error_code& ec)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ const boost::regex& expr, boost::system::error_code& ec)
{
+ typename decay<DynamicBuffer>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+
std::size_t search_position = 0;
for (;;)
{
// Determine the range of the data to be searched.
- typedef typename boost::asio::basic_streambuf<
- Allocator>::const_buffers_type const_buffers_type;
- typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
- const_buffers_type buffers = b.data();
- iterator begin = iterator::begin(buffers);
+ typedef typename DynamicBuffer::const_buffers_type buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers = b.data();
+ iterator begin = iterator::begin(data_buffers);
iterator start_pos = begin + search_position;
- iterator end = iterator::end(buffers);
+ iterator end = iterator::end(data_buffers);
// Look for a match.
boost::match_results<iterator,
@@ -261,23 +279,41 @@ std::size_t read_until(SyncReadStream& s,
#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
-template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+template <typename SyncReadStream,
+ typename DynamicBuffer, typename MatchCondition>
+inline std::size_t read_until(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ MatchCondition match_condition,
+ typename enable_if<is_match_condition<MatchCondition>::value>::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = read_until(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ match_condition, ec);
+ boost::asio::detail::throw_error(ec, "read_until");
+ return bytes_transferred;
+}
+
+template <typename SyncReadStream,
+ typename DynamicBuffer, typename MatchCondition>
std::size_t read_until(SyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
MatchCondition match_condition, boost::system::error_code& ec,
typename enable_if<is_match_condition<MatchCondition>::value>::type*)
{
+ typename decay<DynamicBuffer>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+
std::size_t search_position = 0;
for (;;)
{
// Determine the range of the data to be searched.
- typedef typename boost::asio::basic_streambuf<
- Allocator>::const_buffers_type const_buffers_type;
- typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
- const_buffers_type buffers = b.data();
- iterator begin = iterator::begin(buffers);
+ typedef typename DynamicBuffer::const_buffers_type buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers = b.data();
+ iterator begin = iterator::begin(data_buffers);
iterator start_pos = begin + search_position;
- iterator end = iterator::end(buffers);
+ iterator end = iterator::end(data_buffers);
// Look for a match.
std::pair<iterator, bool> result = match_condition(start_pos, end);
@@ -306,35 +342,100 @@ std::size_t read_until(SyncReadStream& s,
}
// Need more data.
- std::size_t bytes_to_read = read_size_helper(b, 65536);
+ std::size_t bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512, b.capacity() - b.size()),
+ std::min<std::size_t>(65536, b.max_size() - b.size()));
b.commit(s.read_some(b.prepare(bytes_to_read), ec));
if (ec)
return 0;
}
}
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, char delim)
+{
+ return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, char delim,
+ boost::system::error_code& ec)
+{
+ return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ BOOST_ASIO_STRING_VIEW_PARAM delim)
+{
+ return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec)
+{
+ return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
+}
+
+#if defined(BOOST_ASIO_HAS_BOOST_REGEX)
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
+{
+ return read_until(s, basic_streambuf_ref<Allocator>(b), expr);
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+ boost::system::error_code& ec)
+{
+ return read_until(s, basic_streambuf_ref<Allocator>(b), expr, ec);
+}
+
+#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
+
template <typename SyncReadStream, typename Allocator, typename MatchCondition>
inline std::size_t read_until(SyncReadStream& s,
boost::asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
typename enable_if<is_match_condition<MatchCondition>::value>::type*)
{
- boost::system::error_code ec;
- std::size_t bytes_transferred = read_until(s, b, match_condition, ec);
- boost::asio::detail::throw_error(ec, "read_until");
- return bytes_transferred;
+ return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition);
+}
+
+template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+inline std::size_t read_until(SyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ MatchCondition match_condition, boost::system::error_code& ec,
+ typename enable_if<is_match_condition<MatchCondition>::value>::type*)
+{
+ return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition, ec);
}
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
namespace detail
{
- template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
class read_until_delim_op
{
public:
+ template <typename BufferSequence>
read_until_delim_op(AsyncReadStream& stream,
- boost::asio::basic_streambuf<Allocator>& streambuf,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
char delim, ReadHandler& handler)
: stream_(stream),
- streambuf_(streambuf),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
delim_(delim),
start_(0),
search_position_(0),
@@ -345,7 +446,7 @@ namespace detail
#if defined(BOOST_ASIO_HAS_MOVE)
read_until_delim_op(const read_until_delim_op& other)
: stream_(other.stream_),
- streambuf_(other.streambuf_),
+ buffers_(other.buffers_),
delim_(other.delim_),
start_(other.start_),
search_position_(other.search_position_),
@@ -355,7 +456,7 @@ namespace detail
read_until_delim_op(read_until_delim_op&& other)
: stream_(other.stream_),
- streambuf_(other.streambuf_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
delim_(other.delim_),
start_(other.start_),
search_position_(other.search_position_),
@@ -376,13 +477,13 @@ namespace detail
{
{
// Determine the range of the data to be searched.
- typedef typename boost::asio::basic_streambuf<
- Allocator>::const_buffers_type const_buffers_type;
- typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
- const_buffers_type buffers = streambuf_.data();
- iterator begin = iterator::begin(buffers);
+ typedef typename DynamicBuffer::const_buffers_type
+ buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers = buffers_.data();
+ iterator begin = iterator::begin(data_buffers);
iterator start_pos = begin + search_position_;
- iterator end = iterator::end(buffers);
+ iterator end = iterator::end(data_buffers);
// Look for a match.
iterator iter = std::find(start_pos, end, delim_);
@@ -394,7 +495,7 @@ namespace detail
}
// No match yet. Check if buffer is full.
- else if (streambuf_.size() == streambuf_.max_size())
+ else if (buffers_.size() == buffers_.max_size())
{
search_position_ = not_found;
bytes_to_read = 0;
@@ -405,7 +506,11 @@ namespace detail
{
// Next search can start with the new data.
search_position_ = end - begin;
- bytes_to_read = read_size_helper(streambuf_, 65536);
+ bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(65536,
+ buffers_.max_size() - buffers_.size()));
}
}
@@ -414,10 +519,10 @@ namespace detail
break;
// Start a new asynchronous read operation to obtain more data.
- stream_.async_read_some(streambuf_.prepare(bytes_to_read),
+ stream_.async_read_some(buffers_.prepare(bytes_to_read),
BOOST_ASIO_MOVE_CAST(read_until_delim_op)(*this));
return; default:
- streambuf_.commit(bytes_transferred);
+ buffers_.commit(bytes_transferred);
if (ec || bytes_transferred == 0)
break;
}
@@ -436,97 +541,143 @@ namespace detail
//private:
AsyncReadStream& stream_;
- boost::asio::basic_streambuf<Allocator>& streambuf_;
+ DynamicBuffer buffers_;
char delim_;
int start_;
std::size_t search_position_;
ReadHandler handler_;
};
- template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
read_until_delim_op<AsyncReadStream,
- Allocator, ReadHandler>* this_handler)
+ DynamicBuffer, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
read_until_delim_op<AsyncReadStream,
- Allocator, ReadHandler>* this_handler)
+ DynamicBuffer, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
inline bool asio_handler_is_continuation(
read_until_delim_op<AsyncReadStream,
- Allocator, ReadHandler>* this_handler)
+ DynamicBuffer, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
- template <typename Function, typename AsyncReadStream, typename Allocator,
- typename ReadHandler>
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
read_until_delim_op<AsyncReadStream,
- Allocator, ReadHandler>* this_handler)
+ DynamicBuffer, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
- template <typename Function, typename AsyncReadStream, typename Allocator,
- typename ReadHandler>
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
read_until_delim_op<AsyncReadStream,
- Allocator, ReadHandler>* this_handler)
+ DynamicBuffer, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
-template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_until_delim_op<AsyncReadStream,
+ DynamicBuffer, ReadHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(
+ const detail::read_until_delim_op<AsyncReadStream,
+ DynamicBuffer, ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename ReadHandler, typename Executor>
+struct associated_executor<
+ detail::read_until_delim_op<AsyncReadStream,
+ DynamicBuffer, ReadHandler>,
+ Executor>
+{
+ typedef typename associated_executor<ReadHandler, Executor>::type type;
+
+ static type get(
+ const detail::read_until_delim_op<AsyncReadStream,
+ DynamicBuffer, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_until(AsyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, char delim,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
detail::read_until_delim_op<AsyncReadStream,
- Allocator, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- s, b, delim, init.handler)(
- boost::system::error_code(), 0, 1);
+ typename decay<DynamicBuffer>::type,
+ BOOST_ASIO_HANDLER_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))>(
+ s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ delim, init.completion_handler)(boost::system::error_code(), 0, 1);
return init.result.get();
}
namespace detail
{
- template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
class read_until_delim_string_op
{
public:
+ template <typename BufferSequence>
read_until_delim_string_op(AsyncReadStream& stream,
- boost::asio::basic_streambuf<Allocator>& streambuf,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
const std::string& delim, ReadHandler& handler)
: stream_(stream),
- streambuf_(streambuf),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
delim_(delim),
start_(0),
search_position_(0),
@@ -537,7 +688,7 @@ namespace detail
#if defined(BOOST_ASIO_HAS_MOVE)
read_until_delim_string_op(const read_until_delim_string_op& other)
: stream_(other.stream_),
- streambuf_(other.streambuf_),
+ buffers_(other.buffers_),
delim_(other.delim_),
start_(other.start_),
search_position_(other.search_position_),
@@ -547,7 +698,7 @@ namespace detail
read_until_delim_string_op(read_until_delim_string_op&& other)
: stream_(other.stream_),
- streambuf_(other.streambuf_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
delim_(BOOST_ASIO_MOVE_CAST(std::string)(other.delim_)),
start_(other.start_),
search_position_(other.search_position_),
@@ -568,13 +719,13 @@ namespace detail
{
{
// Determine the range of the data to be searched.
- typedef typename boost::asio::basic_streambuf<
- Allocator>::const_buffers_type const_buffers_type;
- typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
- const_buffers_type buffers = streambuf_.data();
- iterator begin = iterator::begin(buffers);
+ typedef typename DynamicBuffer::const_buffers_type
+ buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers = buffers_.data();
+ iterator begin = iterator::begin(data_buffers);
iterator start_pos = begin + search_position_;
- iterator end = iterator::end(buffers);
+ iterator end = iterator::end(data_buffers);
// Look for a match.
std::pair<iterator, bool> result = detail::partial_search(
@@ -587,7 +738,7 @@ namespace detail
}
// No match yet. Check if buffer is full.
- else if (streambuf_.size() == streambuf_.max_size())
+ else if (buffers_.size() == buffers_.max_size())
{
search_position_ = not_found;
bytes_to_read = 0;
@@ -608,7 +759,11 @@ namespace detail
search_position_ = end - begin;
}
- bytes_to_read = read_size_helper(streambuf_, 65536);
+ bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(65536,
+ buffers_.max_size() - buffers_.size()));
}
}
@@ -617,10 +772,10 @@ namespace detail
break;
// Start a new asynchronous read operation to obtain more data.
- stream_.async_read_some(streambuf_.prepare(bytes_to_read),
+ stream_.async_read_some(buffers_.prepare(bytes_to_read),
BOOST_ASIO_MOVE_CAST(read_until_delim_string_op)(*this));
return; default:
- streambuf_.commit(bytes_transferred);
+ buffers_.commit(bytes_transferred);
if (ec || bytes_transferred == 0)
break;
}
@@ -639,35 +794,38 @@ namespace detail
//private:
AsyncReadStream& stream_;
- boost::asio::basic_streambuf<Allocator>& streambuf_;
+ DynamicBuffer buffers_;
std::string delim_;
int start_;
std::size_t search_position_;
ReadHandler handler_;
};
- template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
read_until_delim_string_op<AsyncReadStream,
- Allocator, ReadHandler>* this_handler)
+ DynamicBuffer, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
read_until_delim_string_op<AsyncReadStream,
- Allocator, ReadHandler>* this_handler)
+ DynamicBuffer, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+ template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
inline bool asio_handler_is_continuation(
read_until_delim_string_op<AsyncReadStream,
- Allocator, ReadHandler>* this_handler)
+ DynamicBuffer, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: boost_asio_handler_cont_helpers::is_continuation(
@@ -675,64 +833,109 @@ namespace detail
}
template <typename Function, typename AsyncReadStream,
- typename Allocator, typename ReadHandler>
+ typename DynamicBuffer, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
read_until_delim_string_op<AsyncReadStream,
- Allocator, ReadHandler>* this_handler)
+ DynamicBuffer, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncReadStream,
- typename Allocator, typename ReadHandler>
+ typename DynamicBuffer, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
read_until_delim_string_op<AsyncReadStream,
- Allocator, ReadHandler>* this_handler)
+ DynamicBuffer, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
-template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_until_delim_string_op<AsyncReadStream,
+ DynamicBuffer, ReadHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(
+ const detail::read_until_delim_string_op<AsyncReadStream,
+ DynamicBuffer, ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename ReadHandler, typename Executor>
+struct associated_executor<
+ detail::read_until_delim_string_op<AsyncReadStream,
+ DynamicBuffer, ReadHandler>,
+ Executor>
+{
+ typedef typename associated_executor<ReadHandler, Executor>::type type;
+
+ static type get(
+ const detail::read_until_delim_string_op<AsyncReadStream,
+ DynamicBuffer, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_until(AsyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, const std::string& delim,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_STRING_VIEW_PARAM delim,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
detail::read_until_delim_string_op<AsyncReadStream,
- Allocator, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- s, b, delim, init.handler)(
- boost::system::error_code(), 0, 1);
+ typename decay<DynamicBuffer>::type,
+ BOOST_ASIO_HANDLER_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))>(
+ s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ static_cast<std::string>(delim),
+ init.completion_handler)(boost::system::error_code(), 0, 1);
return init.result.get();
}
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if defined(BOOST_ASIO_HAS_BOOST_REGEX)
namespace detail
{
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename RegEx, typename ReadHandler>
class read_until_expr_op
{
public:
+ template <typename BufferSequence>
read_until_expr_op(AsyncReadStream& stream,
- boost::asio::basic_streambuf<Allocator>& streambuf,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
const boost::regex& expr, ReadHandler& handler)
: stream_(stream),
- streambuf_(streambuf),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
expr_(expr),
start_(0),
search_position_(0),
@@ -743,7 +946,7 @@ namespace detail
#if defined(BOOST_ASIO_HAS_MOVE)
read_until_expr_op(const read_until_expr_op& other)
: stream_(other.stream_),
- streambuf_(other.streambuf_),
+ buffers_(other.buffers_),
expr_(other.expr_),
start_(other.start_),
search_position_(other.search_position_),
@@ -753,7 +956,7 @@ namespace detail
read_until_expr_op(read_until_expr_op&& other)
: stream_(other.stream_),
- streambuf_(other.streambuf_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
expr_(other.expr_),
start_(other.start_),
search_position_(other.search_position_),
@@ -774,13 +977,13 @@ namespace detail
{
{
// Determine the range of the data to be searched.
- typedef typename boost::asio::basic_streambuf<
- Allocator>::const_buffers_type const_buffers_type;
- typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
- const_buffers_type buffers = streambuf_.data();
- iterator begin = iterator::begin(buffers);
+ typedef typename DynamicBuffer::const_buffers_type
+ buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers = buffers_.data();
+ iterator begin = iterator::begin(data_buffers);
iterator start_pos = begin + search_position_;
- iterator end = iterator::end(buffers);
+ iterator end = iterator::end(data_buffers);
// Look for a match.
boost::match_results<iterator,
@@ -796,7 +999,7 @@ namespace detail
}
// No match yet. Check if buffer is full.
- else if (streambuf_.size() == streambuf_.max_size())
+ else if (buffers_.size() == buffers_.max_size())
{
search_position_ = not_found;
bytes_to_read = 0;
@@ -817,7 +1020,11 @@ namespace detail
search_position_ = end - begin;
}
- bytes_to_read = read_size_helper(streambuf_, 65536);
+ bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(65536,
+ buffers_.max_size() - buffers_.size()));
}
}
@@ -826,10 +1033,10 @@ namespace detail
break;
// Start a new asynchronous read operation to obtain more data.
- stream_.async_read_some(streambuf_.prepare(bytes_to_read),
+ stream_.async_read_some(buffers_.prepare(bytes_to_read),
BOOST_ASIO_MOVE_CAST(read_until_expr_op)(*this));
return; default:
- streambuf_.commit(bytes_transferred);
+ buffers_.commit(bytes_transferred);
if (ec || bytes_transferred == 0)
break;
}
@@ -848,85 +1055,127 @@ namespace detail
//private:
AsyncReadStream& stream_;
- boost::asio::basic_streambuf<Allocator>& streambuf_;
+ DynamicBuffer buffers_;
RegEx expr_;
int start_;
std::size_t search_position_;
ReadHandler handler_;
};
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename RegEx, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
read_until_expr_op<AsyncReadStream,
- Allocator, RegEx, ReadHandler>* this_handler)
+ DynamicBuffer, RegEx, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename RegEx, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
read_until_expr_op<AsyncReadStream,
- Allocator, RegEx, ReadHandler>* this_handler)
+ DynamicBuffer, RegEx, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename RegEx, typename ReadHandler>
inline bool asio_handler_is_continuation(
read_until_expr_op<AsyncReadStream,
- Allocator, RegEx, ReadHandler>* this_handler)
+ DynamicBuffer, RegEx, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
- template <typename Function, typename AsyncReadStream, typename Allocator,
- typename RegEx, typename ReadHandler>
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer, typename RegEx, typename ReadHandler>
inline void asio_handler_invoke(Function& function,
read_until_expr_op<AsyncReadStream,
- Allocator, RegEx, ReadHandler>* this_handler)
+ DynamicBuffer, RegEx, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
- template <typename Function, typename AsyncReadStream, typename Allocator,
- typename RegEx, typename ReadHandler>
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer, typename RegEx, typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
read_until_expr_op<AsyncReadStream,
- Allocator, RegEx, ReadHandler>* this_handler)
+ DynamicBuffer, RegEx, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
-template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename RegEx, typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_until_expr_op<AsyncReadStream,
+ DynamicBuffer, RegEx, ReadHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(
+ const detail::read_until_expr_op<AsyncReadStream,
+ DynamicBuffer, RegEx, ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename RegEx, typename ReadHandler, typename Executor>
+struct associated_executor<
+ detail::read_until_expr_op<AsyncReadStream,
+ DynamicBuffer, RegEx, ReadHandler>,
+ Executor>
+{
+ typedef typename associated_executor<ReadHandler, Executor>::type type;
+
+ static type get(
+ const detail::read_until_expr_op<AsyncReadStream,
+ DynamicBuffer, RegEx, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_until(AsyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ const boost::regex& expr,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- detail::read_until_expr_op<AsyncReadStream, Allocator,
- boost::regex, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- s, b, expr, init.handler)(
- boost::system::error_code(), 0, 1);
+ detail::read_until_expr_op<AsyncReadStream,
+ typename decay<DynamicBuffer>::type,
+ boost::regex, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))>(
+ s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ expr, init.completion_handler)(boost::system::error_code(), 0, 1);
return init.result.get();
}
@@ -935,16 +1184,17 @@ async_read_until(AsyncReadStream& s,
namespace detail
{
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename MatchCondition, typename ReadHandler>
class read_until_match_op
{
public:
+ template <typename BufferSequence>
read_until_match_op(AsyncReadStream& stream,
- boost::asio::basic_streambuf<Allocator>& streambuf,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
MatchCondition match_condition, ReadHandler& handler)
: stream_(stream),
- streambuf_(streambuf),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
match_condition_(match_condition),
start_(0),
search_position_(0),
@@ -955,7 +1205,7 @@ namespace detail
#if defined(BOOST_ASIO_HAS_MOVE)
read_until_match_op(const read_until_match_op& other)
: stream_(other.stream_),
- streambuf_(other.streambuf_),
+ buffers_(other.buffers_),
match_condition_(other.match_condition_),
start_(other.start_),
search_position_(other.search_position_),
@@ -965,7 +1215,7 @@ namespace detail
read_until_match_op(read_until_match_op&& other)
: stream_(other.stream_),
- streambuf_(other.streambuf_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
match_condition_(other.match_condition_),
start_(other.start_),
search_position_(other.search_position_),
@@ -986,13 +1236,13 @@ namespace detail
{
{
// Determine the range of the data to be searched.
- typedef typename boost::asio::basic_streambuf<
- Allocator>::const_buffers_type const_buffers_type;
- typedef boost::asio::buffers_iterator<const_buffers_type> iterator;
- const_buffers_type buffers = streambuf_.data();
- iterator begin = iterator::begin(buffers);
+ typedef typename DynamicBuffer::const_buffers_type
+ buffers_type;
+ typedef buffers_iterator<buffers_type> iterator;
+ buffers_type data_buffers = buffers_.data();
+ iterator begin = iterator::begin(data_buffers);
iterator start_pos = begin + search_position_;
- iterator end = iterator::end(buffers);
+ iterator end = iterator::end(data_buffers);
// Look for a match.
std::pair<iterator, bool> result = match_condition_(start_pos, end);
@@ -1004,7 +1254,7 @@ namespace detail
}
// No match yet. Check if buffer is full.
- else if (streambuf_.size() == streambuf_.max_size())
+ else if (buffers_.size() == buffers_.max_size())
{
search_position_ = not_found;
bytes_to_read = 0;
@@ -1025,7 +1275,11 @@ namespace detail
search_position_ = end - begin;
}
- bytes_to_read = read_size_helper(streambuf_, 65536);
+ bytes_to_read = std::min<std::size_t>(
+ std::max<std::size_t>(512,
+ buffers_.capacity() - buffers_.size()),
+ std::min<std::size_t>(65536,
+ buffers_.max_size() - buffers_.size()));
}
}
@@ -1034,10 +1288,10 @@ namespace detail
break;
// Start a new asynchronous read operation to obtain more data.
- stream_.async_read_some(streambuf_.prepare(bytes_to_read),
+ stream_.async_read_some(buffers_.prepare(bytes_to_read),
BOOST_ASIO_MOVE_CAST(read_until_match_op)(*this));
return; default:
- streambuf_.commit(bytes_transferred);
+ buffers_.commit(bytes_transferred);
if (ec || bytes_transferred == 0)
break;
}
@@ -1056,71 +1310,113 @@ namespace detail
//private:
AsyncReadStream& stream_;
- boost::asio::basic_streambuf<Allocator>& streambuf_;
+ DynamicBuffer buffers_;
MatchCondition match_condition_;
int start_;
std::size_t search_position_;
ReadHandler handler_;
};
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename MatchCondition, typename ReadHandler>
inline void* asio_handler_allocate(std::size_t size,
- read_until_match_op<AsyncReadStream,
- Allocator, MatchCondition, ReadHandler>* this_handler)
+ read_until_match_op<AsyncReadStream, DynamicBuffer,
+ MatchCondition, ReadHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename MatchCondition, typename ReadHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- read_until_match_op<AsyncReadStream,
- Allocator, MatchCondition, ReadHandler>* this_handler)
+ read_until_match_op<AsyncReadStream, DynamicBuffer,
+ MatchCondition, ReadHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename AsyncReadStream, typename Allocator,
+ template <typename AsyncReadStream, typename DynamicBuffer,
typename MatchCondition, typename ReadHandler>
inline bool asio_handler_is_continuation(
- read_until_match_op<AsyncReadStream,
- Allocator, MatchCondition, ReadHandler>* this_handler)
+ read_until_match_op<AsyncReadStream, DynamicBuffer,
+ MatchCondition, ReadHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
- template <typename Function, typename AsyncReadStream, typename Allocator,
- typename MatchCondition, typename ReadHandler>
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer, typename MatchCondition,
+ typename ReadHandler>
inline void asio_handler_invoke(Function& function,
- read_until_match_op<AsyncReadStream,
- Allocator, MatchCondition, ReadHandler>* this_handler)
+ read_until_match_op<AsyncReadStream, DynamicBuffer,
+ MatchCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
- template <typename Function, typename AsyncReadStream, typename Allocator,
- typename MatchCondition, typename ReadHandler>
+ template <typename Function, typename AsyncReadStream,
+ typename DynamicBuffer, typename MatchCondition,
+ typename ReadHandler>
inline void asio_handler_invoke(const Function& function,
- read_until_match_op<AsyncReadStream,
- Allocator, MatchCondition, ReadHandler>* this_handler)
+ read_until_match_op<AsyncReadStream, DynamicBuffer,
+ MatchCondition, ReadHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
-template <typename AsyncReadStream, typename Allocator,
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename MatchCondition, typename ReadHandler, typename Allocator>
+struct associated_allocator<
+ detail::read_until_match_op<AsyncReadStream,
+ DynamicBuffer, MatchCondition, ReadHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<ReadHandler, Allocator>::type type;
+
+ static type get(
+ const detail::read_until_match_op<AsyncReadStream,
+ DynamicBuffer, MatchCondition, ReadHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename MatchCondition, typename ReadHandler, typename Executor>
+struct associated_executor<
+ detail::read_until_match_op<AsyncReadStream,
+ DynamicBuffer, MatchCondition, ReadHandler>,
+ Executor>
+{
+ typedef typename associated_executor<ReadHandler, Executor>::type type;
+
+ static type get(
+ const detail::read_until_match_op<AsyncReadStream,
+ DynamicBuffer, MatchCondition, ReadHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncReadStream, typename DynamicBuffer,
typename MatchCondition, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_until(AsyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
typename enable_if<is_match_condition<MatchCondition>::value>::type*)
{
@@ -1128,19 +1424,76 @@ async_read_until(AsyncReadStream& s,
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- detail::read_until_match_op<AsyncReadStream, Allocator,
- MatchCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
- void (boost::system::error_code, std::size_t))>(
- s, b, match_condition, init.handler)(
- boost::system::error_code(), 0, 1);
+ detail::read_until_match_op<AsyncReadStream,
+ typename decay<DynamicBuffer>::type,
+ MatchCondition, BOOST_ASIO_HANDLER_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))>(
+ s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ match_condition, init.completion_handler)(
+ boost::system::error_code(), 0, 1);
return init.result.get();
}
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+{
+ return async_read_until(s, basic_streambuf_ref<Allocator>(b),
+ delim, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ BOOST_ASIO_STRING_VIEW_PARAM delim,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+{
+ return async_read_until(s, basic_streambuf_ref<Allocator>(b),
+ delim, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+#if defined(BOOST_ASIO_HAS_BOOST_REGEX)
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+{
+ return async_read_until(s, basic_streambuf_ref<Allocator>(b),
+ expr, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
+
+template <typename AsyncReadStream, typename Allocator,
+ typename MatchCondition, typename ReadHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<is_match_condition<MatchCondition>::value>::type*)
+{
+ return async_read_until(s, basic_streambuf_ref<Allocator>(b),
+ match_condition, BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
} // namespace asio
} // namespace boost
diff --git a/boost/asio/impl/serial_port_base.ipp b/boost/asio/impl/serial_port_base.ipp
index fcb6ce3df4..25a8a60ba0 100644
--- a/boost/asio/impl/serial_port_base.ipp
+++ b/boost/asio/impl/serial_port_base.ipp
@@ -38,7 +38,7 @@
namespace boost {
namespace asio {
-boost::system::error_code serial_port_base::baud_rate::store(
+BOOST_ASIO_SYNC_OP_VOID serial_port_base::baud_rate::store(
BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -112,9 +112,9 @@ boost::system::error_code serial_port_base::baud_rate::store(
# endif
default:
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
-# if defined(_BSD_SOURCE)
+# if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
::cfsetspeed(&storage, baud);
# else
::cfsetispeed(&storage, baud);
@@ -122,10 +122,10 @@ boost::system::error_code serial_port_base::baud_rate::store(
# endif
#endif
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
-boost::system::error_code serial_port_base::baud_rate::load(
+BOOST_ASIO_SYNC_OP_VOID serial_port_base::baud_rate::load(
const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -200,11 +200,11 @@ boost::system::error_code serial_port_base::baud_rate::load(
default:
value_ = 0;
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
#endif
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
serial_port_base::flow_control::flow_control(
@@ -218,7 +218,7 @@ serial_port_base::flow_control::flow_control(
}
}
-boost::system::error_code serial_port_base::flow_control::store(
+BOOST_ASIO_SYNC_OP_VOID serial_port_base::flow_control::store(
BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -250,7 +250,7 @@ boost::system::error_code serial_port_base::flow_control::store(
{
case none:
storage.c_iflag &= ~(IXOFF | IXON);
-# if defined(_BSD_SOURCE)
+# if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
storage.c_cflag &= ~CRTSCTS;
# elif defined(__QNXNTO__)
storage.c_cflag &= ~(IHFLOW | OHFLOW);
@@ -258,14 +258,14 @@ boost::system::error_code serial_port_base::flow_control::store(
break;
case software:
storage.c_iflag |= IXOFF | IXON;
-# if defined(_BSD_SOURCE)
+# if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
storage.c_cflag &= ~CRTSCTS;
# elif defined(__QNXNTO__)
storage.c_cflag &= ~(IHFLOW | OHFLOW);
# endif
break;
case hardware:
-# if defined(_BSD_SOURCE)
+# if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
storage.c_iflag &= ~(IXOFF | IXON);
storage.c_cflag |= CRTSCTS;
break;
@@ -275,17 +275,17 @@ boost::system::error_code serial_port_base::flow_control::store(
break;
# else
ec = boost::asio::error::operation_not_supported;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
# endif
default:
break;
}
#endif
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
-boost::system::error_code serial_port_base::flow_control::load(
+BOOST_ASIO_SYNC_OP_VOID serial_port_base::flow_control::load(
const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -306,7 +306,7 @@ boost::system::error_code serial_port_base::flow_control::load(
{
value_ = software;
}
-# if defined(_BSD_SOURCE)
+# if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)
else if (storage.c_cflag & CRTSCTS)
{
value_ = hardware;
@@ -323,7 +323,7 @@ boost::system::error_code serial_port_base::flow_control::load(
}
#endif
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
serial_port_base::parity::parity(serial_port_base::parity::type t)
@@ -336,7 +336,7 @@ serial_port_base::parity::parity(serial_port_base::parity::type t)
}
}
-boost::system::error_code serial_port_base::parity::store(
+BOOST_ASIO_SYNC_OP_VOID serial_port_base::parity::store(
BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -380,10 +380,10 @@ boost::system::error_code serial_port_base::parity::store(
}
#endif
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
-boost::system::error_code serial_port_base::parity::load(
+BOOST_ASIO_SYNC_OP_VOID serial_port_base::parity::load(
const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -417,7 +417,7 @@ boost::system::error_code serial_port_base::parity::load(
}
#endif
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
serial_port_base::stop_bits::stop_bits(
@@ -431,7 +431,7 @@ serial_port_base::stop_bits::stop_bits(
}
}
-boost::system::error_code serial_port_base::stop_bits::store(
+BOOST_ASIO_SYNC_OP_VOID serial_port_base::stop_bits::store(
BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -460,14 +460,14 @@ boost::system::error_code serial_port_base::stop_bits::store(
break;
default:
ec = boost::asio::error::operation_not_supported;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
#endif
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
-boost::system::error_code serial_port_base::stop_bits::load(
+BOOST_ASIO_SYNC_OP_VOID serial_port_base::stop_bits::load(
const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -491,7 +491,7 @@ boost::system::error_code serial_port_base::stop_bits::load(
value_ = (storage.c_cflag & CSTOPB) ? two : one;
#endif
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
serial_port_base::character_size::character_size(unsigned int t)
@@ -504,7 +504,7 @@ serial_port_base::character_size::character_size(unsigned int t)
}
}
-boost::system::error_code serial_port_base::character_size::store(
+BOOST_ASIO_SYNC_OP_VOID serial_port_base::character_size::store(
BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec) const
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -521,10 +521,10 @@ boost::system::error_code serial_port_base::character_size::store(
}
#endif
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
-boost::system::error_code serial_port_base::character_size::load(
+BOOST_ASIO_SYNC_OP_VOID serial_port_base::character_size::load(
const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
{
#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
@@ -541,7 +541,7 @@ boost::system::error_code serial_port_base::character_size::load(
}
#endif
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
} // namespace asio
diff --git a/boost/asio/impl/spawn.hpp b/boost/asio/impl/spawn.hpp
index a42fc6fbad..ec1ff45d19 100644
--- a/boost/asio/impl/spawn.hpp
+++ b/boost/asio/impl/spawn.hpp
@@ -16,14 +16,18 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
#include <boost/asio/async_result.hpp>
+#include <boost/asio/bind_executor.hpp>
#include <boost/asio/detail/atomic_count.hpp>
#include <boost/asio/detail/handler_alloc_helpers.hpp>
#include <boost/asio/detail/handler_cont_helpers.hpp>
#include <boost/asio/detail/handler_invoke_helpers.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/noncopyable.hpp>
-#include <boost/asio/detail/shared_ptr.hpp>
-#include <boost/asio/handler_type.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/system/system_error.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -64,7 +68,7 @@ namespace detail {
//private:
shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;
typename basic_yield_context<Handler>::caller_type& ca_;
- Handler& handler_;
+ Handler handler_;
atomic_count* ready_;
boost::system::error_code* ec_;
T* value_;
@@ -100,7 +104,7 @@ namespace detail {
//private:
shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;
typename basic_yield_context<Handler>::caller_type& ca_;
- Handler& handler_;
+ Handler handler_;
atomic_count* ready_;
boost::system::error_code* ec_;
};
@@ -143,11 +147,140 @@ namespace detail {
function, this_handler->handler_);
}
+ 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 boost::system::system_error(ec_);
+ return BOOST_ASIO_MOVE_CAST(return_type)(value_);
+ }
+
+ private:
+ completion_handler_type& handler_;
+ typename basic_yield_context<Handler>::caller_type& ca_;
+ atomic_count ready_;
+ boost::system::error_code* out_ec_;
+ boost::system::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 boost::system::system_error(ec_);
+ }
+
+ private:
+ completion_handler_type& handler_;
+ typename basic_yield_context<Handler>::caller_type& ca_;
+ atomic_count ready_;
+ boost::system::error_code* out_ec_;
+ boost::system::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, Arg1>(h)
+ {
+ }
+};
+
+template <typename Handler, typename ReturnType>
+class async_result<basic_yield_context<Handler>,
+ ReturnType(boost::system::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(boost::system::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, Arg2>(h)
+ {
+ }
+};
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+template <typename Handler, typename ReturnType>
struct handler_type<basic_yield_context<Handler>, ReturnType()>
{
typedef detail::coro_handler<Handler, void> type;
@@ -156,7 +289,7 @@ struct handler_type<basic_yield_context<Handler>, ReturnType()>
template <typename Handler, typename ReturnType, typename Arg1>
struct handler_type<basic_yield_context<Handler>, ReturnType(Arg1)>
{
- typedef detail::coro_handler<Handler, Arg1> type;
+ typedef detail::coro_handler<Handler, typename decay<Arg1>::type> type;
};
template <typename Handler, typename ReturnType>
@@ -170,74 +303,48 @@ template <typename Handler, typename ReturnType, typename Arg2>
struct handler_type<basic_yield_context<Handler>,
ReturnType(boost::system::error_code, Arg2)>
{
- typedef detail::coro_handler<Handler, Arg2> type;
+ typedef detail::coro_handler<Handler, typename decay<Arg2>::type> type;
};
template <typename Handler, typename T>
class async_result<detail::coro_handler<Handler, T> >
+ : public detail::coro_async_result<Handler, T>
{
public:
- typedef T type;
-
- explicit async_result(detail::coro_handler<Handler, T>& h)
- : handler_(h),
- ca_(h.ca_),
- ready_(2)
- {
- h.ready_ = &ready_;
- out_ec_ = h.ec_;
- if (!out_ec_) h.ec_ = &ec_;
- h.value_ = &value_;
- }
+ typedef typename detail::coro_async_result<Handler, T>::return_type type;
- type get()
+ explicit async_result(
+ typename detail::coro_async_result<Handler,
+ void>::completion_handler_type& h)
+ : detail::coro_async_result<Handler, T>(h)
{
- handler_.coro_.reset(); // Must not hold shared_ptr to coro while suspended.
- if (--ready_ != 0)
- ca_();
- if (!out_ec_ && ec_) throw boost::system::system_error(ec_);
- return BOOST_ASIO_MOVE_CAST(type)(value_);
}
-
-private:
- detail::coro_handler<Handler, T>& handler_;
- typename basic_yield_context<Handler>::caller_type& ca_;
- detail::atomic_count ready_;
- boost::system::error_code* out_ec_;
- boost::system::error_code ec_;
- type value_;
};
-template <typename Handler>
-class async_result<detail::coro_handler<Handler, void> >
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+template <typename Handler, typename T, typename Allocator>
+struct associated_allocator<detail::coro_handler<Handler, T>, Allocator>
{
-public:
- typedef void type;
+ typedef typename associated_allocator<Handler, Allocator>::type type;
- explicit async_result(detail::coro_handler<Handler, void>& h)
- : handler_(h),
- ca_(h.ca_),
- ready_(2)
+ static type get(const detail::coro_handler<Handler, T>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
{
- h.ready_ = &ready_;
- out_ec_ = h.ec_;
- if (!out_ec_) h.ec_ = &ec_;
+ 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;
- void get()
+ static type get(const detail::coro_handler<Handler, T>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
{
- handler_.coro_.reset(); // Must not hold shared_ptr to coro while suspended.
- if (--ready_ != 0)
- ca_();
- if (!out_ec_ && ec_) throw boost::system::system_error(ec_);
+ return associated_executor<Handler, Executor>::get(h.handler_, ex);
}
-
-private:
- detail::coro_handler<Handler, void>& handler_;
- typename basic_yield_context<Handler>::caller_type& ca_;
- detail::atomic_count ready_;
- boost::system::error_code* out_ec_;
- boost::system::error_code ec_;
};
namespace detail {
@@ -270,6 +377,7 @@ namespace detail {
#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_)();
@@ -294,22 +402,61 @@ namespace detail {
boost::coroutines::attributes attributes_;
};
+ template <typename Function, typename Handler, typename Function1>
+ inline void asio_handler_invoke(Function& function,
+ spawn_helper<Handler, Function1>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->data_->handler_);
+ }
+
+ template <typename Function, typename Handler, typename Function1>
+ inline void asio_handler_invoke(const Function& function,
+ spawn_helper<Handler, Function1>* this_handler)
+ {
+ boost_asio_handler_invoke_helpers::invoke(
+ function, this_handler->data_->handler_);
+ }
+
inline void default_spawn_handler() {}
} // namespace detail
+template <typename Function>
+inline void spawn(BOOST_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));
+
+ boost::asio::spawn(ex, BOOST_ASIO_MOVE_CAST(Function)(function), attributes);
+}
+
template <typename Handler, typename Function>
void spawn(BOOST_ASIO_MOVE_ARG(Handler) handler,
BOOST_ASIO_MOVE_ARG(Function) function,
- const boost::coroutines::attributes& attributes)
+ const boost::coroutines::attributes& attributes,
+ typename enable_if<!is_executor<typename decay<Handler>::type>::value &&
+ !is_convertible<Handler&, execution_context&>::value>::type*)
{
- detail::spawn_helper<Handler, Function> helper;
+ typedef typename decay<Handler>::type handler_type;
+
+ typename associated_executor<handler_type>::type ex(
+ (get_associated_executor)(handler));
+
+ typename associated_allocator<handler_type>::type a(
+ (get_associated_allocator)(handler));
+
+ detail::spawn_helper<handler_type, Function> helper;
helper.data_.reset(
- new detail::spawn_data<Handler, Function>(
+ new detail::spawn_data<handler_type, Function>(
BOOST_ASIO_MOVE_CAST(Handler)(handler), true,
BOOST_ASIO_MOVE_CAST(Function)(function)));
helper.attributes_ = attributes;
- boost_asio_handler_invoke_helpers::invoke(helper, helper.data_->handler_);
+
+ ex.dispatch(helper, a);
}
template <typename Handler, typename Function>
@@ -318,30 +465,61 @@ void spawn(basic_yield_context<Handler> ctx,
const boost::coroutines::attributes& attributes)
{
Handler handler(ctx.handler_); // Explicit copy that might be moved from.
+
+ typename associated_executor<Handler>::type ex(
+ (get_associated_executor)(handler));
+
+ typename associated_allocator<Handler>::type a(
+ (get_associated_allocator)(handler));
+
detail::spawn_helper<Handler, Function> helper;
helper.data_.reset(
new detail::spawn_data<Handler, Function>(
BOOST_ASIO_MOVE_CAST(Handler)(handler), false,
BOOST_ASIO_MOVE_CAST(Function)(function)));
helper.attributes_ = attributes;
- boost_asio_handler_invoke_helpers::invoke(helper, helper.data_->handler_);
+
+ ex.dispatch(helper, a);
}
-template <typename Function>
-void spawn(boost::asio::io_service::strand strand,
+template <typename Function, typename Executor>
+inline void spawn(const Executor& ex,
+ BOOST_ASIO_MOVE_ARG(Function) function,
+ const boost::coroutines::attributes& attributes,
+ typename enable_if<is_executor<Executor>::value>::type*)
+{
+ boost::asio::spawn(boost::asio::strand<Executor>(ex),
+ BOOST_ASIO_MOVE_CAST(Function)(function), attributes);
+}
+
+template <typename Function, typename Executor>
+inline void spawn(const strand<Executor>& ex,
BOOST_ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes)
{
- boost::asio::spawn(strand.wrap(&detail::default_spawn_handler),
+ boost::asio::spawn(boost::asio::bind_executor(
+ ex, &detail::default_spawn_handler),
BOOST_ASIO_MOVE_CAST(Function)(function), attributes);
}
template <typename Function>
-void spawn(boost::asio::io_service& io_service,
+inline void spawn(const boost::asio::io_context::strand& s,
BOOST_ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes)
{
- boost::asio::spawn(boost::asio::io_service::strand(io_service),
+ boost::asio::spawn(boost::asio::bind_executor(
+ s, &detail::default_spawn_handler),
+ BOOST_ASIO_MOVE_CAST(Function)(function), attributes);
+}
+
+template <typename Function, typename ExecutionContext>
+inline void spawn(ExecutionContext& ctx,
+ BOOST_ASIO_MOVE_ARG(Function) function,
+ const boost::coroutines::attributes& attributes,
+ typename enable_if<is_convertible<
+ ExecutionContext&, execution_context&>::value>::type*)
+{
+ boost::asio::spawn(ctx.get_executor(),
BOOST_ASIO_MOVE_CAST(Function)(function), attributes);
}
diff --git a/boost/asio/impl/src.hpp b/boost/asio/impl/src.hpp
index 7b9a03eda9..ad75cb744d 100644
--- a/boost/asio/impl/src.hpp
+++ b/boost/asio/impl/src.hpp
@@ -20,9 +20,13 @@
#endif
#include <boost/asio/impl/error.ipp>
+#include <boost/asio/impl/execution_context.ipp>
+#include <boost/asio/impl/executor.ipp>
#include <boost/asio/impl/handler_alloc_hook.ipp>
-#include <boost/asio/impl/io_service.ipp>
+#include <boost/asio/impl/io_context.ipp>
#include <boost/asio/impl/serial_port_base.ipp>
+#include <boost/asio/impl/system_context.ipp>
+#include <boost/asio/impl/thread_pool.ipp>
#include <boost/asio/detail/impl/buffer_sequence_adapter.ipp>
#include <boost/asio/detail/impl/descriptor_ops.ipp>
#include <boost/asio/detail/impl/dev_poll_reactor.ipp>
@@ -30,6 +34,7 @@
#include <boost/asio/detail/impl/eventfd_select_interrupter.ipp>
#include <boost/asio/detail/impl/handler_tracking.ipp>
#include <boost/asio/detail/impl/kqueue_reactor.ipp>
+#include <boost/asio/detail/impl/null_event.ipp>
#include <boost/asio/detail/impl/pipe_select_interrupter.ipp>
#include <boost/asio/detail/impl/posix_event.ipp>
#include <boost/asio/detail/impl/posix_mutex.ipp>
@@ -39,18 +44,19 @@
#include <boost/asio/detail/impl/reactive_serial_port_service.ipp>
#include <boost/asio/detail/impl/reactive_socket_service_base.ipp>
#include <boost/asio/detail/impl/resolver_service_base.ipp>
+#include <boost/asio/detail/impl/scheduler.ipp>
#include <boost/asio/detail/impl/select_reactor.ipp>
#include <boost/asio/detail/impl/service_registry.ipp>
#include <boost/asio/detail/impl/signal_set_service.ipp>
#include <boost/asio/detail/impl/socket_ops.ipp>
#include <boost/asio/detail/impl/socket_select_interrupter.ipp>
+#include <boost/asio/detail/impl/strand_executor_service.ipp>
#include <boost/asio/detail/impl/strand_service.ipp>
-#include <boost/asio/detail/impl/task_io_service.ipp>
#include <boost/asio/detail/impl/throw_error.ipp>
#include <boost/asio/detail/impl/timer_queue_ptime.ipp>
#include <boost/asio/detail/impl/timer_queue_set.ipp>
#include <boost/asio/detail/impl/win_iocp_handle_service.ipp>
-#include <boost/asio/detail/impl/win_iocp_io_service.ipp>
+#include <boost/asio/detail/impl/win_iocp_io_context.ipp>
#include <boost/asio/detail/impl/win_iocp_serial_port_service.ipp>
#include <boost/asio/detail/impl/win_iocp_socket_service_base.ipp>
#include <boost/asio/detail/impl/win_event.ipp>
@@ -67,6 +73,8 @@
#include <boost/asio/ip/impl/address_v4.ipp>
#include <boost/asio/ip/impl/address_v6.ipp>
#include <boost/asio/ip/impl/host_name.ipp>
+#include <boost/asio/ip/impl/network_v4.ipp>
+#include <boost/asio/ip/impl/network_v6.ipp>
#include <boost/asio/ip/detail/impl/endpoint.ipp>
#include <boost/asio/local/detail/impl/endpoint.ipp>
diff --git a/boost/asio/ssl/context_service.hpp b/boost/asio/impl/system_context.hpp
index b0a31f3750..88d42e51f9 100644
--- a/boost/asio/ssl/context_service.hpp
+++ b/boost/asio/impl/system_context.hpp
@@ -1,5 +1,5 @@
//
-// ssl/context_service.hpp
+// impl/system_context.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
@@ -8,35 +8,29 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
-#ifndef BOOST_ASIO_SSL_CONTEXT_SERVICE_HPP
-#define BOOST_ASIO_SSL_CONTEXT_SERVICE_HPP
+#ifndef BOOST_ASIO_IMPL_SYSTEM_CONTEXT_HPP
+#define BOOST_ASIO_IMPL_SYSTEM_CONTEXT_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include <boost/asio/detail/config.hpp>
-
-#if defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/ssl/old/context_service.hpp>
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/system_executor.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
-namespace ssl {
-#if defined(BOOST_ASIO_ENABLE_OLD_SSL)
+inline system_context::executor_type
+system_context::get_executor() BOOST_ASIO_NOEXCEPT
+{
+ return system_executor();
+}
-using boost::asio::ssl::old::context_service;
-
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
-} // namespace ssl
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
-#endif // BOOST_ASIO_SSL_CONTEXT_SERVICE_HPP
+#endif // BOOST_ASIO_IMPL_SYSTEM_CONTEXT_HPP
diff --git a/boost/asio/impl/system_context.ipp b/boost/asio/impl/system_context.ipp
new file mode 100644
index 0000000000..86bb44548f
--- /dev/null
+++ b/boost/asio/impl/system_context.ipp
@@ -0,0 +1,75 @@
+//
+// impl/system_context.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_SYSTEM_CONTEXT_IPP
+#define BOOST_ASIO_IMPL_SYSTEM_CONTEXT_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/system_context.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+struct system_context::thread_function
+{
+ detail::scheduler* scheduler_;
+
+ void operator()()
+ {
+ boost::system::error_code ec;
+ scheduler_->run(ec);
+ }
+};
+
+system_context::system_context()
+ : scheduler_(use_service<detail::scheduler>(*this))
+{
+ scheduler_.work_started();
+
+ thread_function f = { &scheduler_ };
+ std::size_t num_threads = detail::thread::hardware_concurrency() * 2;
+ threads_.create_threads(f, num_threads ? num_threads : 2);
+}
+
+system_context::~system_context()
+{
+ scheduler_.work_finished();
+ scheduler_.stop();
+ threads_.join();
+}
+
+void system_context::stop()
+{
+ scheduler_.stop();
+}
+
+bool system_context::stopped() const BOOST_ASIO_NOEXCEPT
+{
+ return scheduler_.stopped();
+}
+
+void system_context::join()
+{
+ scheduler_.work_finished();
+ threads_.join();
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_SYSTEM_CONTEXT_IPP
diff --git a/boost/asio/impl/system_executor.hpp b/boost/asio/impl/system_executor.hpp
new file mode 100644
index 0000000000..c8a0cf4027
--- /dev/null
+++ b/boost/asio/impl/system_executor.hpp
@@ -0,0 +1,87 @@
+//
+// impl/system_executor.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_SYSTEM_EXECUTOR_HPP
+#define BOOST_ASIO_IMPL_SYSTEM_EXECUTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/executor_op.hpp>
+#include <boost/asio/detail/global.hpp>
+#include <boost/asio/detail/recycling_allocator.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/system_context.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+inline system_context& system_executor::context() const BOOST_ASIO_NOEXCEPT
+{
+ return detail::global<system_context>();
+}
+
+template <typename Function, typename Allocator>
+void system_executor::dispatch(
+ BOOST_ASIO_MOVE_ARG(Function) f, const Allocator&) const
+{
+ typename decay<Function>::type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
+ boost_asio_handler_invoke_helpers::invoke(tmp, tmp);
+}
+
+template <typename Function, typename Allocator>
+void system_executor::post(
+ BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+{
+ typedef typename decay<Function>::type function_type;
+
+ system_context& ctx = detail::global<system_context>();
+
+ // Allocate and construct an operation to wrap the function.
+ typedef detail::executor_op<function_type, Allocator> op;
+ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
+ p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
+
+ BOOST_ASIO_HANDLER_CREATION((ctx, *p.p,
+ "system_executor", &this->context(), 0, "post"));
+
+ ctx.scheduler_.post_immediate_completion(p.p, false);
+ p.v = p.p = 0;
+}
+
+template <typename Function, typename Allocator>
+void system_executor::defer(
+ BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+{
+ typedef typename decay<Function>::type function_type;
+
+ system_context& ctx = detail::global<system_context>();
+
+ // Allocate and construct an operation to wrap the function.
+ typedef detail::executor_op<function_type, Allocator> op;
+ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
+ p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
+
+ BOOST_ASIO_HANDLER_CREATION((ctx, *p.p,
+ "system_executor", &this->context(), 0, "defer"));
+
+ ctx.scheduler_.post_immediate_completion(p.p, true);
+ p.v = p.p = 0;
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_SYSTEM_EXECUTOR_HPP
diff --git a/boost/asio/impl/thread_pool.hpp b/boost/asio/impl/thread_pool.hpp
new file mode 100644
index 0000000000..53a4900d34
--- /dev/null
+++ b/boost/asio/impl/thread_pool.hpp
@@ -0,0 +1,129 @@
+//
+// impl/thread_pool.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_THREAD_POOL_HPP
+#define BOOST_ASIO_IMPL_THREAD_POOL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/executor_op.hpp>
+#include <boost/asio/detail/fenced_block.hpp>
+#include <boost/asio/detail/recycling_allocator.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/execution_context.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+inline thread_pool::executor_type
+thread_pool::get_executor() BOOST_ASIO_NOEXCEPT
+{
+ return executor_type(*this);
+}
+
+inline thread_pool&
+thread_pool::executor_type::context() const BOOST_ASIO_NOEXCEPT
+{
+ return pool_;
+}
+
+inline void
+thread_pool::executor_type::on_work_started() const BOOST_ASIO_NOEXCEPT
+{
+ pool_.scheduler_.work_started();
+}
+
+inline void thread_pool::executor_type::on_work_finished()
+const BOOST_ASIO_NOEXCEPT
+{
+ pool_.scheduler_.work_finished();
+}
+
+template <typename Function, typename Allocator>
+void thread_pool::executor_type::dispatch(
+ BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+{
+ typedef typename decay<Function>::type function_type;
+
+ // Invoke immediately if we are already inside the thread pool.
+ if (pool_.scheduler_.can_dispatch())
+ {
+ // Make a local, non-const copy of the function.
+ function_type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
+
+ detail::fenced_block b(detail::fenced_block::full);
+ boost_asio_handler_invoke_helpers::invoke(tmp, tmp);
+ return;
+ }
+
+ // Allocate and construct an operation to wrap the function.
+ typedef detail::executor_op<function_type, Allocator> op;
+ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
+ p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
+
+ BOOST_ASIO_HANDLER_CREATION((pool_, *p.p,
+ "thread_pool", &this->context(), 0, "dispatch"));
+
+ pool_.scheduler_.post_immediate_completion(p.p, false);
+ p.v = p.p = 0;
+}
+
+template <typename Function, typename Allocator>
+void thread_pool::executor_type::post(
+ BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+{
+ typedef typename decay<Function>::type function_type;
+
+ // Allocate and construct an operation to wrap the function.
+ typedef detail::executor_op<function_type, Allocator> op;
+ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
+ p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
+
+ BOOST_ASIO_HANDLER_CREATION((pool_, *p.p,
+ "thread_pool", &this->context(), 0, "post"));
+
+ pool_.scheduler_.post_immediate_completion(p.p, false);
+ p.v = p.p = 0;
+}
+
+template <typename Function, typename Allocator>
+void thread_pool::executor_type::defer(
+ BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+{
+ typedef typename decay<Function>::type function_type;
+
+ // Allocate and construct an operation to wrap the function.
+ typedef detail::executor_op<function_type, Allocator> op;
+ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
+ p.p = new (p.v) op(BOOST_ASIO_MOVE_CAST(Function)(f), a);
+
+ BOOST_ASIO_HANDLER_CREATION((pool_, *p.p,
+ "thread_pool", &this->context(), 0, "defer"));
+
+ pool_.scheduler_.post_immediate_completion(p.p, true);
+ p.v = p.p = 0;
+}
+
+inline bool
+thread_pool::executor_type::running_in_this_thread() const BOOST_ASIO_NOEXCEPT
+{
+ return pool_.scheduler_.can_dispatch();
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_THREAD_POOL_HPP
diff --git a/boost/asio/impl/thread_pool.ipp b/boost/asio/impl/thread_pool.ipp
new file mode 100644
index 0000000000..43ae029359
--- /dev/null
+++ b/boost/asio/impl/thread_pool.ipp
@@ -0,0 +1,78 @@
+//
+// impl/thread_pool.ipp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IMPL_THREAD_POOL_IPP
+#define BOOST_ASIO_IMPL_THREAD_POOL_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/thread_pool.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+struct thread_pool::thread_function
+{
+ detail::scheduler* scheduler_;
+
+ void operator()()
+ {
+ boost::system::error_code ec;
+ scheduler_->run(ec);
+ }
+};
+
+thread_pool::thread_pool()
+ : scheduler_(use_service<detail::scheduler>(*this))
+{
+ scheduler_.work_started();
+
+ thread_function f = { &scheduler_ };
+ std::size_t num_threads = detail::thread::hardware_concurrency() * 2;
+ threads_.create_threads(f, num_threads ? num_threads : 2);
+}
+
+thread_pool::thread_pool(std::size_t num_threads)
+ : scheduler_(use_service<detail::scheduler>(*this))
+{
+ scheduler_.work_started();
+
+ thread_function f = { &scheduler_ };
+ threads_.create_threads(f, num_threads);
+}
+
+thread_pool::~thread_pool()
+{
+ stop();
+ join();
+}
+
+void thread_pool::stop()
+{
+ scheduler_.stop();
+}
+
+void thread_pool::join()
+{
+ scheduler_.work_finished();
+ threads_.join();
+}
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IMPL_THREAD_POOL_IPP
diff --git a/boost/asio/impl/use_future.hpp b/boost/asio/impl/use_future.hpp
index c74050ea63..e02dfeebd2 100644
--- a/boost/asio/impl/use_future.hpp
+++ b/boost/asio/impl/use_future.hpp
@@ -17,11 +17,13 @@
#include <boost/asio/detail/config.hpp>
#include <future>
+#include <tuple>
#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/system/error_code.hpp>
-#include <boost/asio/handler_type.hpp>
+#include <boost/asio/packaged_task.hpp>
#include <boost/system/system_error.hpp>
-#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/system_executor.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -29,146 +31,905 @@ namespace boost {
namespace asio {
namespace detail {
- // Completion handler to adapt a promise as a completion handler.
- template <typename T>
- class promise_handler
- {
- public:
- // Construct from use_future special value.
- template <typename Alloc>
- promise_handler(use_future_t<Alloc> uf)
- : promise_(std::allocate_shared<std::promise<T> >(
- BOOST_ASIO_REBIND_ALLOC(Alloc, char)(uf.get_allocator()),
- std::allocator_arg,
- BOOST_ASIO_REBIND_ALLOC(Alloc, char)(uf.get_allocator())))
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename T, typename F, typename... Args>
+inline void promise_invoke_and_set(std::promise<T>& p,
+ F& f, BOOST_ASIO_MOVE_ARG(Args)... args)
+{
+#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ try
+#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ {
+ p.set_value(f(BOOST_ASIO_MOVE_CAST(Args)(args)...));
+ }
+#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ catch (...)
+ {
+ p.set_exception(std::current_exception());
+ }
+#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
+}
+
+template <typename F, typename... Args>
+inline void promise_invoke_and_set(std::promise<void>& p,
+ F& f, BOOST_ASIO_MOVE_ARG(Args)... args)
+{
+#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ try
+#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ {
+ f(BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ p.set_value();
+ }
+#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ catch (...)
+ {
+ p.set_exception(std::current_exception());
+ }
+#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
+}
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename T, typename F>
+inline void promise_invoke_and_set(std::promise<T>& p, F& f)
+{
+#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ try
+#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ {
+ p.set_value(f());
+ }
+#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ catch (...)
+ {
+ p.set_exception(std::current_exception());
+ }
+#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
+}
+
+template <typename F, typename Args>
+inline void promise_invoke_and_set(std::promise<void>& p, F& f)
+{
+#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ try
+#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ {
+ f();
+ p.set_value();
+#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ }
+ catch (...)
+ {
+ p.set_exception(std::current_exception());
+ }
+#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
+}
+
+#if defined(BOOST_ASIO_NO_EXCEPTIONS)
+
+#define BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \
+ template <typename T, typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ inline void promise_invoke_and_set(std::promise<T>& p, \
+ F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ p.set_value(f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
+ } \
+ \
+ template <typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ inline void promise_invoke_and_set(std::promise<void>& p, \
+ F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ p.set_value(); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF)
+#undef BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF
+
+#else // defined(BOOST_ASIO_NO_EXCEPTIONS)
+
+#define BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \
+ template <typename T, typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ inline void promise_invoke_and_set(std::promise<T>& p, \
+ F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ try \
+ { \
+ p.set_value(f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
+ } \
+ catch (...) \
+ { \
+ p.set_exception(std::current_exception()); \
+ } \
+ } \
+ \
+ template <typename F, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ inline void promise_invoke_and_set(std::promise<void>& p, \
+ F& f, BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ { \
+ try \
+ { \
+ f(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ p.set_value(); \
+ } \
+ catch (...) \
+ { \
+ p.set_exception(std::current_exception()); \
+ } \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF)
+#undef BOOST_ASIO_PRIVATE_PROMISE_INVOKE_DEF
+
+#endif // defined(BOOST_ASIO_NO_EXCEPTIONS)
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+// A function object adapter to invoke a nullary function object and capture
+// any exception thrown into a promise.
+template <typename T, typename F>
+class promise_invoker
+{
+public:
+ promise_invoker(const shared_ptr<std::promise<T> >& p,
+ BOOST_ASIO_MOVE_ARG(F) f)
+ : p_(p), f_(BOOST_ASIO_MOVE_CAST(F)(f))
+ {
+ }
+
+ void operator()()
+ {
+#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ try
+#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
{
+ f_();
}
-
- void operator()(T t)
+#if !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ catch (...)
{
- promise_->set_value(t);
+ p_->set_exception(std::current_exception());
}
+#endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
+ }
+
+private:
+ shared_ptr<std::promise<T> > p_;
+ typename decay<F>::type f_;
+};
+
+// An executor that adapts the system_executor to capture any exeption thrown
+// by a submitted function object and save it into a promise.
+template <typename T>
+class promise_executor
+{
+public:
+ explicit promise_executor(const shared_ptr<std::promise<T> >& p)
+ : p_(p)
+ {
+ }
+
+ execution_context& context() const BOOST_ASIO_NOEXCEPT
+ {
+ return system_executor().context();
+ }
+
+ void on_work_started() const BOOST_ASIO_NOEXCEPT {}
+ void on_work_finished() const BOOST_ASIO_NOEXCEPT {}
+
+ template <typename F, typename A>
+ void dispatch(BOOST_ASIO_MOVE_ARG(F) f, const A&) const
+ {
+ promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f))();
+ }
+
+ template <typename F, typename A>
+ void post(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const
+ {
+ system_executor().post(
+ promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)), a);
+ }
+
+ template <typename F, typename A>
+ void defer(BOOST_ASIO_MOVE_ARG(F) f, const A& a) const
+ {
+ system_executor().defer(
+ promise_invoker<T, F>(p_, BOOST_ASIO_MOVE_CAST(F)(f)), a);
+ }
+
+ friend bool operator==(const promise_executor& a,
+ const promise_executor& b) BOOST_ASIO_NOEXCEPT
+ {
+ return a.p_ == b.p_;
+ }
+
+ friend bool operator!=(const promise_executor& a,
+ const promise_executor& b) BOOST_ASIO_NOEXCEPT
+ {
+ return a.p_ != b.p_;
+ }
+
+private:
+ shared_ptr<std::promise<T> > p_;
+};
+
+// The base class for all completion handlers that create promises.
+template <typename T>
+class promise_creator
+{
+public:
+ typedef promise_executor<T> executor_type;
+
+ executor_type get_executor() const BOOST_ASIO_NOEXCEPT
+ {
+ return executor_type(p_);
+ }
+
+ typedef std::future<T> future_type;
+
+ future_type get_future()
+ {
+ return p_->get_future();
+ }
+
+protected:
+ template <typename Allocator>
+ void create_promise(const Allocator& a)
+ {
+ BOOST_ASIO_REBIND_ALLOC(Allocator, char) b(a);
+ p_ = std::allocate_shared<std::promise<T>>(b, std::allocator_arg, b);
+ }
- void operator()(const boost::system::error_code& ec, T t)
+ shared_ptr<std::promise<T> > p_;
+};
+
+// For completion signature void().
+class promise_handler_0
+ : public promise_creator<void>
+{
+public:
+ void operator()()
+ {
+ this->p_->set_value();
+ }
+};
+
+// For completion signature void(error_code).
+class promise_handler_ec_0
+ : public promise_creator<void>
+{
+public:
+ void operator()(const boost::system::error_code& ec)
+ {
+ if (ec)
{
- if (ec)
- promise_->set_exception(
- std::make_exception_ptr(
- boost::system::system_error(ec)));
- else
- promise_->set_value(t);
+ this->p_->set_exception(
+ std::make_exception_ptr(
+ boost::system::system_error(ec)));
}
-
- //private:
- std::shared_ptr<std::promise<T> > promise_;
- };
-
- // Completion handler to adapt a void promise as a completion handler.
- template <>
- class promise_handler<void>
- {
- public:
- // Construct from use_future special value. Used during rebinding.
- template <typename Alloc>
- promise_handler(use_future_t<Alloc> uf)
- : promise_(std::allocate_shared<std::promise<void> >(
- BOOST_ASIO_REBIND_ALLOC(Alloc, char)(uf.get_allocator()),
- std::allocator_arg,
- BOOST_ASIO_REBIND_ALLOC(Alloc, char)(uf.get_allocator())))
+ else
{
+ this->p_->set_value();
}
+ }
+};
- void operator()()
+// For completion signature void(exception_ptr).
+class promise_handler_ex_0
+ : public promise_creator<void>
+{
+public:
+ void operator()(const std::exception_ptr& ex)
+ {
+ if (ex)
{
- promise_->set_value();
+ this->p_->set_exception(ex);
}
+ else
+ {
+ this->p_->set_value();
+ }
+ }
+};
+
+// For completion signature void(T).
+template <typename T>
+class promise_handler_1
+ : public promise_creator<T>
+{
+public:
+ template <typename Arg>
+ void operator()(BOOST_ASIO_MOVE_ARG(Arg) arg)
+ {
+ this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
+ }
+};
- void operator()(const boost::system::error_code& ec)
+// For completion signature void(error_code, T).
+template <typename T>
+class promise_handler_ec_1
+ : public promise_creator<T>
+{
+public:
+ template <typename Arg>
+ void operator()(const boost::system::error_code& ec,
+ BOOST_ASIO_MOVE_ARG(Arg) arg)
+ {
+ if (ec)
{
- if (ec)
- promise_->set_exception(
- std::make_exception_ptr(
- boost::system::system_error(ec)));
- else
- promise_->set_value();
+ this->p_->set_exception(
+ std::make_exception_ptr(
+ boost::system::system_error(ec)));
}
+ else
+ this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
+ }
+};
- //private:
- std::shared_ptr<std::promise<void> > promise_;
- };
+// For completion signature void(exception_ptr, T).
+template <typename T>
+class promise_handler_ex_1
+ : public promise_creator<T>
+{
+public:
+ template <typename Arg>
+ void operator()(const std::exception_ptr& ex,
+ BOOST_ASIO_MOVE_ARG(Arg) arg)
+ {
+ if (ex)
+ this->p_->set_exception(ex);
+ else
+ this->p_->set_value(BOOST_ASIO_MOVE_CAST(Arg)(arg));
+ }
+};
- // Ensure any exceptions thrown from the handler are propagated back to the
- // caller via the future.
- template <typename Function, typename T>
- void asio_handler_invoke(Function f, promise_handler<T>* h)
+// For completion signature void(T1, ..., Tn);
+template <typename T>
+class promise_handler_n
+ : public promise_creator<T>
+{
+public:
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename... Args>
+ void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
{
- std::shared_ptr<std::promise<T> > p(h->promise_);
- try
+ this->p_->set_value(
+ std::forward_as_tuple(
+ BOOST_ASIO_MOVE_CAST(Args)(args)...));
+ }
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+#define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
+ template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ {\
+ this->p_->set_value( \
+ std::forward_as_tuple( \
+ BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
+#undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+};
+
+// For completion signature void(error_code, T1, ..., Tn);
+template <typename T>
+class promise_handler_ec_n
+ : public promise_creator<T>
+{
+public:
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename... Args>
+ void operator()(const boost::system::error_code& ec,
+ BOOST_ASIO_MOVE_ARG(Args)... args)
+ {
+ if (ec)
{
- f();
+ this->p_->set_exception(
+ std::make_exception_ptr(
+ boost::system::system_error(ec)));
}
- catch (...)
+ else
{
- p->set_exception(std::current_exception());
+ this->p_->set_value(
+ std::forward_as_tuple(
+ BOOST_ASIO_MOVE_CAST(Args)(args)...));
}
}
-} // namespace detail
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
-#if !defined(GENERATING_DOCUMENTATION)
+#define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
+ template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ void operator()(const boost::system::error_code& ec, \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ {\
+ if (ec) \
+ { \
+ this->p_->set_exception( \
+ std::make_exception_ptr( \
+ boost::system::system_error(ec))); \
+ } \
+ else \
+ { \
+ this->p_->set_value( \
+ std::forward_as_tuple( \
+ BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
+ } \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
+#undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+};
-// Handler traits specialisation for promise_handler.
+// For completion signature void(exception_ptr, T1, ..., Tn);
template <typename T>
-class async_result<detail::promise_handler<T> >
+class promise_handler_ex_n
+ : public promise_creator<T>
+{
+public:
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename... Args>
+ void operator()(const std::exception_ptr& ex,
+ BOOST_ASIO_MOVE_ARG(Args)... args)
+ {
+ if (ex)
+ this->p_->set_exception(ex);
+ else
+ {
+ this->p_->set_value(
+ std::forward_as_tuple(
+ BOOST_ASIO_MOVE_CAST(Args)(args)...));
+ }
+ }
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+#define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
+ template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ void operator()(const std::exception_ptr& ex, \
+ BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ {\
+ if (ex) \
+ this->p_->set_exception(ex); \
+ else \
+ { \
+ this->p_->set_value( \
+ std::forward_as_tuple( \
+ BOOST_ASIO_VARIADIC_MOVE_ARGS(n))); \
+ } \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
+#undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+};
+
+// Helper template to choose the appropriate concrete promise handler
+// implementation based on the supplied completion signature.
+template <typename> class promise_handler_selector;
+
+template <>
+class promise_handler_selector<void()>
+ : public promise_handler_0 {};
+
+template <>
+class promise_handler_selector<void(boost::system::error_code)>
+ : public promise_handler_ec_0 {};
+
+template <>
+class promise_handler_selector<void(std::exception_ptr)>
+ : public promise_handler_ex_0 {};
+
+template <typename Arg>
+class promise_handler_selector<void(Arg)>
+ : public promise_handler_1<Arg> {};
+
+template <typename Arg>
+class promise_handler_selector<void(boost::system::error_code, Arg)>
+ : public promise_handler_ec_1<Arg> {};
+
+template <typename Arg>
+class promise_handler_selector<void(std::exception_ptr, Arg)>
+ : public promise_handler_ex_1<Arg> {};
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename... Arg>
+class promise_handler_selector<void(Arg...)>
+ : public promise_handler_n<std::tuple<Arg...> > {};
+
+template <typename... Arg>
+class promise_handler_selector<void(boost::system::error_code, Arg...)>
+ : public promise_handler_ec_n<std::tuple<Arg...> > {};
+
+template <typename... Arg>
+class promise_handler_selector<void(std::exception_ptr, Arg...)>
+ : public promise_handler_ex_n<std::tuple<Arg...> > {};
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+#define BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF(n) \
+ template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ class promise_handler_selector< \
+ void(Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
+ : public promise_handler_n< \
+ std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
+ \
+ template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ class promise_handler_selector< \
+ void(boost::system::error_code, Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
+ : public promise_handler_ec_n< \
+ std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
+ \
+ template <typename Arg, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ class promise_handler_selector< \
+ void(std::exception_ptr, Arg, BOOST_ASIO_VARIADIC_TARGS(n))> \
+ : public promise_handler_ex_n< \
+ std::tuple<Arg, BOOST_ASIO_VARIADIC_TARGS(n)> > {}; \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF)
+#undef BOOST_ASIO_PRIVATE_PROMISE_SELECTOR_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+// Completion handlers produced from the use_future completion token, when not
+// using use_future::operator().
+template <typename Signature, typename Allocator>
+class promise_handler
+ : public promise_handler_selector<Signature>
{
public:
- // The initiating function will return a future.
- typedef std::future<T> type;
+ typedef Allocator allocator_type;
+ typedef void result_type;
- // Constructor creates a new promise for the async operation, and obtains the
- // corresponding future.
- explicit async_result(detail::promise_handler<T>& h)
+ promise_handler(use_future_t<Allocator> u)
+ : allocator_(u.get_allocator())
{
- value_ = h.promise_->get_future();
+ this->create_promise(allocator_);
}
- // Obtain the future to be returned from the initiating function.
- type get() { return std::move(value_); }
+ allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
+ {
+ return allocator_;
+ }
private:
- type value_;
+ Allocator allocator_;
};
-// Handler type specialisation for use_future.
-template <typename Allocator, typename ReturnType>
-struct handler_type<use_future_t<Allocator>, ReturnType()>
+template <typename Function, typename Signature, typename Allocator>
+inline void asio_handler_invoke(Function& f,
+ promise_handler<Signature, Allocator>* h)
{
- typedef detail::promise_handler<void> type;
+ typename promise_handler<Signature, Allocator>::executor_type
+ ex(h->get_executor());
+ ex.dispatch(BOOST_ASIO_MOVE_CAST(Function)(f), std::allocator<void>());
+}
+
+template <typename Function, typename Signature, typename Allocator>
+inline void asio_handler_invoke(const Function& f,
+ promise_handler<Signature, Allocator>* h)
+{
+ typename promise_handler<Signature, Allocator>::executor_type
+ ex(h->get_executor());
+ ex.dispatch(f, std::allocator<void>());
+}
+
+// Helper base class for async_result specialisation.
+template <typename Signature, typename Allocator>
+class promise_async_result
+{
+public:
+ typedef promise_handler<Signature, Allocator> completion_handler_type;
+ typedef typename completion_handler_type::future_type return_type;
+
+ explicit promise_async_result(completion_handler_type& h)
+ : future_(h.get_future())
+ {
+ }
+
+ return_type get()
+ {
+ return BOOST_ASIO_MOVE_CAST(return_type)(future_);
+ }
+
+private:
+ return_type future_;
};
-// Handler type specialisation for use_future.
-template <typename Allocator, typename ReturnType, typename Arg1>
-struct handler_type<use_future_t<Allocator>, ReturnType(Arg1)>
+// Return value from use_future::operator().
+template <typename Function, typename Allocator>
+class packaged_token
{
- typedef detail::promise_handler<Arg1> type;
+public:
+ packaged_token(Function f, const Allocator& a)
+ : function_(BOOST_ASIO_MOVE_CAST(Function)(f)),
+ allocator_(a)
+ {
+ }
+
+//private:
+ Function function_;
+ Allocator allocator_;
};
-// Handler type specialisation for use_future.
-template <typename Allocator, typename ReturnType>
-struct handler_type<use_future_t<Allocator>,
- ReturnType(boost::system::error_code)>
+// Completion handlers produced from the use_future completion token, when
+// using use_future::operator().
+template <typename Function, typename Allocator, typename Result>
+class packaged_handler
+ : public promise_creator<Result>
{
- typedef detail::promise_handler<void> type;
+public:
+ typedef Allocator allocator_type;
+ typedef void result_type;
+
+ packaged_handler(packaged_token<Function, Allocator> t)
+ : function_(BOOST_ASIO_MOVE_CAST(Function)(t.function_)),
+ allocator_(t.allocator_)
+ {
+ this->create_promise(allocator_);
+ }
+
+ allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
+ {
+ return allocator_;
+ }
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ template <typename... Args>
+ void operator()(BOOST_ASIO_MOVE_ARG(Args)... args)
+ {
+ (promise_invoke_and_set)(*this->p_,
+ function_, BOOST_ASIO_MOVE_CAST(Args)(args)...);
+ }
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+ void operator()()
+ {
+ (promise_invoke_and_set)(*this->p_, function_);
+ }
+
+#define BOOST_ASIO_PRIVATE_CALL_OP_DEF(n) \
+ template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ void operator()(BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
+ {\
+ (promise_invoke_and_set)(*this->p_, \
+ function_, BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
+ } \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CALL_OP_DEF)
+#undef BOOST_ASIO_PRIVATE_CALL_OP_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+private:
+ Function function_;
+ Allocator allocator_;
+};
+
+template <typename Function,
+ typename Function1, typename Allocator, typename Result>
+inline void asio_handler_invoke(Function& f,
+ packaged_handler<Function1, Allocator, Result>* h)
+{
+ typename packaged_handler<Function1, Allocator, Result>::executor_type
+ ex(h->get_executor());
+ ex.dispatch(BOOST_ASIO_MOVE_CAST(Function)(f), std::allocator<void>());
+}
+
+template <typename Function,
+ typename Function1, typename Allocator, typename Result>
+inline void asio_handler_invoke(const Function& f,
+ packaged_handler<Function1, Allocator, Result>* h)
+{
+ typename packaged_handler<Function1, Allocator, Result>::executor_type
+ ex(h->get_executor());
+ ex.dispatch(f, std::allocator<void>());
+}
+
+// Helper base class for async_result specialisation.
+template <typename Function, typename Allocator, typename Result>
+class packaged_async_result
+{
+public:
+ typedef packaged_handler<Function, Allocator, Result> completion_handler_type;
+ typedef typename completion_handler_type::future_type return_type;
+
+ explicit packaged_async_result(completion_handler_type& h)
+ : future_(h.get_future())
+ {
+ }
+
+ return_type get()
+ {
+ return BOOST_ASIO_MOVE_CAST(return_type)(future_);
+ }
+
+private:
+ return_type future_;
+};
+
+} // namespace detail
+
+template <typename Allocator> template <typename Function>
+inline detail::packaged_token<typename decay<Function>::type, Allocator>
+use_future_t<Allocator>::operator()(BOOST_ASIO_MOVE_ARG(Function) f) const
+{
+ return detail::packaged_token<typename decay<Function>::type, Allocator>(
+ BOOST_ASIO_MOVE_CAST(Function)(f), allocator_);
+}
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename Allocator, typename Result, typename... Args>
+class async_result<use_future_t<Allocator>, Result(Args...)>
+ : public detail::promise_async_result<
+ void(typename decay<Args>::type...), Allocator>
+{
+public:
+ explicit async_result(
+ typename detail::promise_async_result<void(typename decay<Args>::type...),
+ Allocator>::completion_handler_type& h)
+ : detail::promise_async_result<
+ void(typename decay<Args>::type...), Allocator>(h)
+ {
+ }
+};
+
+template <typename Function, typename Allocator,
+ typename Result, typename... Args>
+class async_result<detail::packaged_token<Function, Allocator>, Result(Args...)>
+ : public detail::packaged_async_result<Function, Allocator,
+ typename result_of<Function(Args...)>::type>
+{
+public:
+ explicit async_result(
+ typename detail::packaged_async_result<Function, Allocator,
+ typename result_of<Function(Args...)>::type>::completion_handler_type& h)
+ : detail::packaged_async_result<Function, Allocator,
+ typename result_of<Function(Args...)>::type>(h)
+ {
+ }
+};
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+template <typename Allocator, typename Result>
+class async_result<use_future_t<Allocator>, Result()>
+ : public detail::promise_async_result<void(), Allocator>
+{
+public:
+ explicit async_result(
+ typename detail::promise_async_result<
+ void(), Allocator>::completion_handler_type& h)
+ : detail::promise_async_result<void(), Allocator>(h)
+ {
+ }
+};
+
+template <typename Function, typename Allocator, typename Result>
+class async_result<detail::packaged_token<Function, Allocator>, Result()>
+ : public detail::packaged_async_result<Function, Allocator,
+ typename result_of<Function()>::type>
+{
+public:
+ explicit async_result(
+ typename detail::packaged_async_result<Function, Allocator,
+ typename result_of<Function()>::type>::completion_handler_type& h)
+ : detail::packaged_async_result<Function, Allocator,
+ typename result_of<Function()>::type>(h)
+ {
+ }
};
-// Handler type specialisation for use_future.
-template <typename Allocator, typename ReturnType, typename Arg2>
-struct handler_type<use_future_t<Allocator>,
- ReturnType(boost::system::error_code, Arg2)>
+#define BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \
+ template <typename Allocator, \
+ typename Result, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ class async_result<use_future_t<Allocator>, \
+ Result(BOOST_ASIO_VARIADIC_TARGS(n))> \
+ : public detail::promise_async_result< \
+ void(BOOST_ASIO_VARIADIC_DECAY(n)), Allocator> \
+ { \
+ public: \
+ explicit async_result( \
+ typename detail::promise_async_result< \
+ void(BOOST_ASIO_VARIADIC_DECAY(n)), \
+ Allocator>::completion_handler_type& h) \
+ : detail::promise_async_result< \
+ void(BOOST_ASIO_VARIADIC_DECAY(n)), Allocator>(h) \
+ { \
+ } \
+ }; \
+ \
+ template <typename Function, typename Allocator, \
+ typename Result, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
+ class async_result<detail::packaged_token<Function, Allocator>, \
+ Result(BOOST_ASIO_VARIADIC_TARGS(n))> \
+ : public detail::packaged_async_result<Function, Allocator, \
+ typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type> \
+ { \
+ public: \
+ explicit async_result( \
+ typename detail::packaged_async_result<Function, Allocator, \
+ typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type \
+ >::completion_handler_type& h) \
+ : detail::packaged_async_result<Function, Allocator, \
+ typename result_of<Function(BOOST_ASIO_VARIADIC_TARGS(n))>::type>(h) \
+ { \
+ } \
+ }; \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF)
+#undef BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+template <typename Allocator, typename Signature>
+struct handler_type<use_future_t<Allocator>, Signature>
{
- typedef detail::promise_handler<Arg2> type;
+ typedef typename async_result<use_future_t<Allocator>,
+ Signature>::completion_handler_type type;
};
+template <typename Signature, typename Allocator>
+class async_result<detail::promise_handler<Signature, Allocator> >
+ : public detail::promise_async_result<Signature, Allocator>
+{
+public:
+ typedef typename detail::promise_async_result<
+ Signature, Allocator>::return_type type;
+
+ explicit async_result(
+ typename detail::promise_async_result<
+ Signature, Allocator>::completion_handler_type& h)
+ : detail::promise_async_result<Signature, Allocator>(h)
+ {
+ }
+};
+
+template <typename Function, typename Allocator, typename Signature>
+struct handler_type<detail::packaged_token<Function, Allocator>, Signature>
+{
+ typedef typename async_result<detail::packaged_token<Function, Allocator>,
+ Signature>::completion_handler_type type;
+};
+
+template <typename Function, typename Allocator, typename Result>
+class async_result<detail::packaged_handler<Function, Allocator, Result> >
+ : public detail::packaged_async_result<Function, Allocator, Result>
+{
+public:
+ typedef typename detail::packaged_async_result<
+ Function, Allocator, Result>::return_type type;
+
+ explicit async_result(
+ typename detail::packaged_async_result<
+ Function, Allocator, Result>::completion_handler_type& h)
+ : detail::packaged_async_result<Function, Allocator, Result>(h)
+ {
+ }
+};
+
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
#endif // !defined(GENERATING_DOCUMENTATION)
} // namespace asio
diff --git a/boost/asio/impl/write.hpp b/boost/asio/impl/write.hpp
index 84313fed09..8048380f9f 100644
--- a/boost/asio/impl/write.hpp
+++ b/boost/asio/impl/write.hpp
@@ -15,6 +15,8 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/completion_condition.hpp>
#include <boost/asio/detail/array_fwd.hpp>
@@ -33,30 +35,46 @@
namespace boost {
namespace asio {
-template <typename SyncWriteStream, typename ConstBufferSequence,
- typename CompletionCondition>
-std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
- CompletionCondition completion_condition, boost::system::error_code& ec)
+namespace detail
{
- ec = boost::system::error_code();
- boost::asio::detail::consuming_buffers<
- const_buffer, ConstBufferSequence> tmp(buffers);
- std::size_t total_transferred = 0;
- tmp.prepare(detail::adapt_completion_condition_result(
- completion_condition(ec, total_transferred)));
- while (tmp.begin() != tmp.end())
+ template <typename SyncWriteStream, typename ConstBufferSequence,
+ typename ConstBufferIterator, typename CompletionCondition>
+ std::size_t write_buffer_sequence(SyncWriteStream& s,
+ const ConstBufferSequence& buffers, const ConstBufferIterator&,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
{
- std::size_t bytes_transferred = s.write_some(tmp, ec);
- tmp.consume(bytes_transferred);
- total_transferred += bytes_transferred;
- tmp.prepare(detail::adapt_completion_condition_result(
- completion_condition(ec, total_transferred)));
+ ec = boost::system::error_code();
+ boost::asio::detail::consuming_buffers<const_buffer,
+ ConstBufferSequence, ConstBufferIterator> tmp(buffers);
+ while (!tmp.empty())
+ {
+ if (std::size_t max_size = detail::adapt_completion_condition_result(
+ completion_condition(ec, tmp.total_consumed())))
+ tmp.consume(s.write_some(tmp.prepare(max_size), ec));
+ else
+ break;
+ }
+ return tmp.total_consumed();;
}
- return total_transferred;
+} // namespace detail
+
+template <typename SyncWriteStream, typename ConstBufferSequence,
+ typename CompletionCondition>
+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type*)
+{
+ return detail::write_buffer_sequence(s, buffers,
+ boost::asio::buffer_sequence_begin(buffers), completion_condition, ec);
}
template <typename SyncWriteStream, typename ConstBufferSequence>
-inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers)
+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
@@ -66,7 +84,10 @@ inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers)
template <typename SyncWriteStream, typename ConstBufferSequence>
inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
- boost::system::error_code& ec)
+ boost::system::error_code& ec,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type*)
{
return write(s, buffers, transfer_all(), ec);
}
@@ -74,7 +95,10 @@ inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
template <typename SyncWriteStream, typename ConstBufferSequence,
typename CompletionCondition>
inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
- CompletionCondition completion_condition)
+ CompletionCondition completion_condition,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type*)
{
boost::system::error_code ec;
std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
@@ -82,35 +106,92 @@ inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
return bytes_transferred;
}
-#if !defined(BOOST_ASIO_NO_IOSTREAM)
-
-template <typename SyncWriteStream, typename Allocator,
+template <typename SyncWriteStream, typename DynamicBuffer,
typename CompletionCondition>
std::size_t write(SyncWriteStream& s,
- boost::asio::basic_streambuf<Allocator>& b,
- CompletionCondition completion_condition, boost::system::error_code& ec)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
{
+ typename decay<DynamicBuffer>::type b(
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers));
+
std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec);
b.consume(bytes_transferred);
return bytes_transferred;
}
-template <typename SyncWriteStream, typename Allocator>
+template <typename SyncWriteStream, typename DynamicBuffer>
inline std::size_t write(SyncWriteStream& s,
- boost::asio::basic_streambuf<Allocator>& b)
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
{
boost::system::error_code ec;
- std::size_t bytes_transferred = write(s, b, transfer_all(), ec);
+ std::size_t bytes_transferred = write(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ transfer_all(), ec);
boost::asio::detail::throw_error(ec, "write");
return bytes_transferred;
}
+template <typename SyncWriteStream, typename DynamicBuffer>
+inline std::size_t write(SyncWriteStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
+{
+ return write(s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ transfer_all(), ec);
+}
+
+template <typename SyncWriteStream, typename DynamicBuffer,
+ typename CompletionCondition>
+inline std::size_t write(SyncWriteStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ CompletionCondition completion_condition,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
+{
+ boost::system::error_code ec;
+ std::size_t bytes_transferred = write(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ completion_condition, ec);
+ boost::asio::detail::throw_error(ec, "write");
+ return bytes_transferred;
+}
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
+template <typename SyncWriteStream, typename Allocator,
+ typename CompletionCondition>
+inline std::size_t write(SyncWriteStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition, boost::system::error_code& ec)
+{
+ return write(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec);
+}
+
+template <typename SyncWriteStream, typename Allocator>
+inline std::size_t write(SyncWriteStream& s,
+ boost::asio::basic_streambuf<Allocator>& b)
+{
+ return write(s, basic_streambuf_ref<Allocator>(b));
+}
+
template <typename SyncWriteStream, typename Allocator>
inline std::size_t write(SyncWriteStream& s,
boost::asio::basic_streambuf<Allocator>& b,
boost::system::error_code& ec)
{
- return write(s, b, transfer_all(), ec);
+ return write(s, basic_streambuf_ref<Allocator>(b), ec);
}
template <typename SyncWriteStream, typename Allocator,
@@ -119,18 +200,17 @@ inline std::size_t write(SyncWriteStream& s,
boost::asio::basic_streambuf<Allocator>& b,
CompletionCondition completion_condition)
{
- boost::system::error_code ec;
- std::size_t bytes_transferred = write(s, b, completion_condition, ec);
- boost::asio::detail::throw_error(ec, "write");
- return bytes_transferred;
+ return write(s, basic_streambuf_ref<Allocator>(b), completion_condition);
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
namespace detail
{
template <typename AsyncWriteStream, typename ConstBufferSequence,
- typename CompletionCondition, typename WriteHandler>
+ typename ConstBufferIterator, typename CompletionCondition,
+ typename WriteHandler>
class write_op
: detail::base_from_completion_cond<CompletionCondition>
{
@@ -142,7 +222,6 @@ namespace detail
stream_(stream),
buffers_(buffers),
start_(0),
- total_transferred_(0),
handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
{
}
@@ -153,7 +232,6 @@ namespace detail
stream_(other.stream_),
buffers_(other.buffers_),
start_(other.start_),
- total_transferred_(other.total_transferred_),
handler_(other.handler_)
{
}
@@ -163,7 +241,6 @@ namespace detail
stream_(other.stream_),
buffers_(other.buffers_),
start_(other.start_),
- total_transferred_(other.total_transferred_),
handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
{
}
@@ -172,362 +249,39 @@ namespace detail
void operator()(const boost::system::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
+ std::size_t max_size;
switch (start_ = start)
{
case 1:
- buffers_.prepare(this->check_for_completion(ec, total_transferred_));
- for (;;)
+ max_size = this->check_for_completion(ec, buffers_.total_consumed());
+ do
{
- stream_.async_write_some(buffers_,
+ stream_.async_write_some(buffers_.prepare(max_size),
BOOST_ASIO_MOVE_CAST(write_op)(*this));
return; default:
- total_transferred_ += bytes_transferred;
buffers_.consume(bytes_transferred);
- buffers_.prepare(this->check_for_completion(ec, total_transferred_));
- if ((!ec && bytes_transferred == 0)
- || buffers_.begin() == buffers_.end())
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncWriteStream& stream_;
- boost::asio::detail::consuming_buffers<
- const_buffer, ConstBufferSequence> buffers_;
- int start_;
- std::size_t total_transferred_;
- WriteHandler handler_;
- };
-
- template <typename AsyncWriteStream,
- typename CompletionCondition, typename WriteHandler>
- class write_op<AsyncWriteStream, boost::asio::mutable_buffers_1,
- CompletionCondition, WriteHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- write_op(AsyncWriteStream& stream,
- const boost::asio::mutable_buffers_1& buffers,
- CompletionCondition completion_condition,
- WriteHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- stream_(stream),
- buffer_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- write_op(const write_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- write_op(write_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- stream_.async_write_some(
- boost::asio::buffer(buffer_ + total_transferred_, n),
- BOOST_ASIO_MOVE_CAST(write_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == boost::asio::buffer_size(buffer_))
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncWriteStream& stream_;
- boost::asio::mutable_buffer buffer_;
- int start_;
- std::size_t total_transferred_;
- WriteHandler handler_;
- };
-
- template <typename AsyncWriteStream,
- typename CompletionCondition, typename WriteHandler>
- class write_op<AsyncWriteStream, boost::asio::const_buffers_1,
- CompletionCondition, WriteHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- write_op(AsyncWriteStream& stream,
- const boost::asio::const_buffers_1& buffers,
- CompletionCondition completion_condition,
- WriteHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- stream_(stream),
- buffer_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- write_op(const write_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- write_op(write_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- stream_.async_write_some(
- boost::asio::buffer(buffer_ + total_transferred_, n),
- BOOST_ASIO_MOVE_CAST(write_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == boost::asio::buffer_size(buffer_))
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncWriteStream& stream_;
- boost::asio::const_buffer buffer_;
- int start_;
- std::size_t total_transferred_;
- WriteHandler handler_;
- };
-
- template <typename AsyncWriteStream, typename Elem,
- typename CompletionCondition, typename WriteHandler>
- class write_op<AsyncWriteStream, boost::array<Elem, 2>,
- CompletionCondition, WriteHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- write_op(AsyncWriteStream& stream, const boost::array<Elem, 2>& buffers,
- CompletionCondition completion_condition, WriteHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- stream_(stream),
- buffers_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- write_op(const write_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- write_op(write_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- typename boost::asio::detail::dependent_type<Elem,
- boost::array<boost::asio::const_buffer, 2> >::type bufs = {{
- boost::asio::const_buffer(buffers_[0]),
- boost::asio::const_buffer(buffers_[1]) }};
- std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
- std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
- bufs[1] = boost::asio::buffer(
- bufs[1] + (total_transferred_ < buffer_size0
- ? 0 : total_transferred_ - buffer_size0),
- n - boost::asio::buffer_size(bufs[0]));
- stream_.async_write_some(bufs, BOOST_ASIO_MOVE_CAST(write_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == buffer_size0 + buffer_size1)
+ if ((!ec && bytes_transferred == 0) || buffers_.empty())
break;
- }
+ max_size = this->check_for_completion(ec, buffers_.total_consumed());
+ } while (max_size > 0);
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ handler_(ec, buffers_.total_consumed());
}
}
//private:
AsyncWriteStream& stream_;
- boost::array<Elem, 2> buffers_;
+ boost::asio::detail::consuming_buffers<const_buffer,
+ ConstBufferSequence, ConstBufferIterator> buffers_;
int start_;
- std::size_t total_transferred_;
WriteHandler handler_;
};
-#if defined(BOOST_ASIO_HAS_STD_ARRAY)
-
- template <typename AsyncWriteStream, typename Elem,
- typename CompletionCondition, typename WriteHandler>
- class write_op<AsyncWriteStream, std::array<Elem, 2>,
- CompletionCondition, WriteHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- write_op(AsyncWriteStream& stream, const std::array<Elem, 2>& buffers,
- CompletionCondition completion_condition, WriteHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- stream_(stream),
- buffers_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- write_op(const write_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- write_op(write_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- stream_(other.stream_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- typename boost::asio::detail::dependent_type<Elem,
- std::array<boost::asio::const_buffer, 2> >::type bufs = {{
- boost::asio::const_buffer(buffers_[0]),
- boost::asio::const_buffer(buffers_[1]) }};
- std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
- std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
- bufs[1] = boost::asio::buffer(
- bufs[1] + (total_transferred_ < buffer_size0
- ? 0 : total_transferred_ - buffer_size0),
- n - boost::asio::buffer_size(bufs[0]));
- stream_.async_write_some(bufs, BOOST_ASIO_MOVE_CAST(write_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == buffer_size0 + buffer_size1)
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncWriteStream& stream_;
- std::array<Elem, 2> buffers_;
- int start_;
- std::size_t total_transferred_;
- WriteHandler handler_;
- };
-
-#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
-
template <typename AsyncWriteStream, typename ConstBufferSequence,
- typename CompletionCondition, typename WriteHandler>
+ typename ConstBufferIterator, typename CompletionCondition,
+ typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
- write_op<AsyncWriteStream, ConstBufferSequence,
+ write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
@@ -535,9 +289,10 @@ namespace detail
}
template <typename AsyncWriteStream, typename ConstBufferSequence,
- typename CompletionCondition, typename WriteHandler>
+ typename ConstBufferIterator, typename CompletionCondition,
+ typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- write_op<AsyncWriteStream, ConstBufferSequence,
+ write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
@@ -545,9 +300,10 @@ namespace detail
}
template <typename AsyncWriteStream, typename ConstBufferSequence,
- typename CompletionCondition, typename WriteHandler>
+ typename ConstBufferIterator, typename CompletionCondition,
+ typename WriteHandler>
inline bool asio_handler_is_continuation(
- write_op<AsyncWriteStream, ConstBufferSequence,
+ write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
@@ -556,10 +312,10 @@ namespace detail
}
template <typename Function, typename AsyncWriteStream,
- typename ConstBufferSequence, typename CompletionCondition,
- typename WriteHandler>
+ typename ConstBufferSequence, typename ConstBufferIterator,
+ typename CompletionCondition, typename WriteHandler>
inline void asio_handler_invoke(Function& function,
- write_op<AsyncWriteStream, ConstBufferSequence,
+ write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
@@ -567,38 +323,94 @@ namespace detail
}
template <typename Function, typename AsyncWriteStream,
- typename ConstBufferSequence, typename CompletionCondition,
- typename WriteHandler>
+ typename ConstBufferSequence, typename ConstBufferIterator,
+ typename CompletionCondition, typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
- write_op<AsyncWriteStream, ConstBufferSequence,
+ write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,
CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
+
+ template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename ConstBufferIterator, typename CompletionCondition,
+ typename WriteHandler>
+ inline void start_write_buffer_sequence_op(AsyncWriteStream& stream,
+ const ConstBufferSequence& buffers, const ConstBufferIterator&,
+ CompletionCondition completion_condition, WriteHandler& handler)
+ {
+ detail::write_op<AsyncWriteStream, ConstBufferSequence,
+ ConstBufferIterator, CompletionCondition, WriteHandler>(
+ stream, buffers, completion_condition, handler)(
+ boost::system::error_code(), 0, 1);
+ }
+
} // namespace detail
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncWriteStream, typename ConstBufferSequence,
+ typename ConstBufferIterator, typename CompletionCondition,
+ typename WriteHandler, typename Allocator>
+struct associated_allocator<
+ detail::write_op<AsyncWriteStream, ConstBufferSequence,
+ ConstBufferIterator, CompletionCondition, WriteHandler>,
+ Allocator>
+{
+ 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()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+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>
+{
+ typedef typename associated_executor<WriteHandler, Executor>::type type;
+
+ static type get(
+ const detail::write_op<AsyncWriteStream, ConstBufferSequence,
+ ConstBufferIterator, CompletionCondition, WriteHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
template <typename AsyncWriteStream, typename ConstBufferSequence,
typename CompletionCondition, typename WriteHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (boost::system::error_code, std::size_t))
async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
CompletionCondition completion_condition,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- detail::write_op<AsyncWriteStream, ConstBufferSequence,
- CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- s, buffers, completion_condition, init.handler)(
- boost::system::error_code(), 0, 1);
+ detail::start_write_buffer_sequence_op(s, buffers,
+ boost::asio::buffer_sequence_begin(buffers), completion_condition,
+ init.completion_handler);
return init.result.get();
}
@@ -608,132 +420,227 @@ template <typename AsyncWriteStream, typename ConstBufferSequence,
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (boost::system::error_code, std::size_t))
async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- detail::write_op<AsyncWriteStream, ConstBufferSequence,
- detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- s, buffers, transfer_all(), init.handler)(
- boost::system::error_code(), 0, 1);
+ detail::start_write_buffer_sequence_op(s, buffers,
+ boost::asio::buffer_sequence_begin(buffers), transfer_all(),
+ init.completion_handler);
return init.result.get();
}
-#if !defined(BOOST_ASIO_NO_IOSTREAM)
-
namespace detail
{
- template <typename Allocator, typename WriteHandler>
- class write_streambuf_handler
+ template <typename AsyncWriteStream, typename DynamicBuffer,
+ typename CompletionCondition, typename WriteHandler>
+ class write_dynbuf_op
{
public:
- write_streambuf_handler(boost::asio::basic_streambuf<Allocator>& streambuf,
- WriteHandler& handler)
- : streambuf_(streambuf),
+ template <typename BufferSequence>
+ write_dynbuf_op(AsyncWriteStream& stream,
+ BOOST_ASIO_MOVE_ARG(BufferSequence) buffers,
+ CompletionCondition completion_condition, WriteHandler& handler)
+ : stream_(stream),
+ buffers_(BOOST_ASIO_MOVE_CAST(BufferSequence)(buffers)),
+ completion_condition_(
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),
handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
{
}
#if defined(BOOST_ASIO_HAS_MOVE)
- write_streambuf_handler(const write_streambuf_handler& other)
- : streambuf_(other.streambuf_),
+ write_dynbuf_op(const write_dynbuf_op& other)
+ : stream_(other.stream_),
+ buffers_(other.buffers_),
+ completion_condition_(other.completion_condition_),
handler_(other.handler_)
{
}
- write_streambuf_handler(write_streambuf_handler&& other)
- : streambuf_(other.streambuf_),
+ write_dynbuf_op(write_dynbuf_op&& other)
+ : stream_(other.stream_),
+ buffers_(BOOST_ASIO_MOVE_CAST(DynamicBuffer)(other.buffers_)),
+ completion_condition_(
+ BOOST_ASIO_MOVE_CAST(CompletionCondition)(
+ other.completion_condition_)),
handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
{
}
#endif // defined(BOOST_ASIO_HAS_MOVE)
void operator()(const boost::system::error_code& ec,
- const std::size_t bytes_transferred)
+ std::size_t bytes_transferred, int start = 0)
{
- streambuf_.consume(bytes_transferred);
- handler_(ec, bytes_transferred);
+ switch (start)
+ {
+ case 1:
+ async_write(stream_, buffers_.data(), completion_condition_,
+ BOOST_ASIO_MOVE_CAST(write_dynbuf_op)(*this));
+ return; default:
+ buffers_.consume(bytes_transferred);
+ handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
+ }
}
//private:
- boost::asio::basic_streambuf<Allocator>& streambuf_;
+ AsyncWriteStream& stream_;
+ DynamicBuffer buffers_;
+ CompletionCondition completion_condition_;
WriteHandler handler_;
};
- template <typename Allocator, typename WriteHandler>
+ template <typename AsyncWriteStream, typename DynamicBuffer,
+ typename CompletionCondition, typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
- write_streambuf_handler<Allocator, WriteHandler>* this_handler)
+ write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
+ CompletionCondition, WriteHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename Allocator, typename WriteHandler>
+ template <typename AsyncWriteStream, typename DynamicBuffer,
+ typename CompletionCondition, typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
- write_streambuf_handler<Allocator, WriteHandler>* this_handler)
+ write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
+ CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename Allocator, typename WriteHandler>
+ template <typename AsyncWriteStream, typename DynamicBuffer,
+ typename CompletionCondition, typename WriteHandler>
inline bool asio_handler_is_continuation(
- write_streambuf_handler<Allocator, WriteHandler>* this_handler)
+ write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
+ CompletionCondition, WriteHandler>* this_handler)
{
return boost_asio_handler_cont_helpers::is_continuation(
this_handler->handler_);
}
- template <typename Function, typename Allocator, typename WriteHandler>
+ template <typename Function, typename AsyncWriteStream,
+ typename DynamicBuffer, typename CompletionCondition,
+ typename WriteHandler>
inline void asio_handler_invoke(Function& function,
- write_streambuf_handler<Allocator, WriteHandler>* this_handler)
+ write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
+ CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
- template <typename Function, typename Allocator, typename WriteHandler>
+ template <typename Function, typename AsyncWriteStream,
+ typename DynamicBuffer, typename CompletionCondition,
+ typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
- write_streambuf_handler<Allocator, WriteHandler>* this_handler)
+ write_dynbuf_op<AsyncWriteStream, DynamicBuffer,
+ CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
} // namespace detail
-template <typename AsyncWriteStream, typename Allocator,
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncWriteStream, typename DynamicBuffer,
+ typename CompletionCondition, typename WriteHandler, typename Allocator>
+struct associated_allocator<
+ detail::write_dynbuf_op<AsyncWriteStream,
+ DynamicBuffer, CompletionCondition, WriteHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<WriteHandler, Allocator>::type type;
+
+ static type get(
+ const detail::write_dynbuf_op<AsyncWriteStream,
+ DynamicBuffer, CompletionCondition, WriteHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+template <typename AsyncWriteStream, typename DynamicBuffer,
+ typename CompletionCondition, typename WriteHandler, typename Executor>
+struct associated_executor<
+ detail::write_dynbuf_op<AsyncWriteStream,
+ DynamicBuffer, CompletionCondition, WriteHandler>,
+ Executor>
+{
+ typedef typename associated_executor<WriteHandler, Executor>::type type;
+
+ static type get(
+ const detail::write_dynbuf_op<AsyncWriteStream,
+ DynamicBuffer, CompletionCondition, WriteHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncWriteStream,
+ typename DynamicBuffer, typename WriteHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+async_write(AsyncWriteStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
+{
+ return async_write(s,
+ BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ transfer_all(), BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+}
+
+template <typename AsyncWriteStream, typename DynamicBuffer,
typename CompletionCondition, typename WriteHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (boost::system::error_code, std::size_t))
async_write(AsyncWriteStream& s,
- boost::asio::basic_streambuf<Allocator>& b,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
CompletionCondition completion_condition,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type*)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- async_write(s, b.data(), completion_condition,
- detail::write_streambuf_handler<Allocator, BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- b, init.handler));
+ detail::write_dynbuf_op<AsyncWriteStream,
+ typename decay<DynamicBuffer>::type,
+ CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
+ WriteHandler, void (boost::system::error_code, std::size_t))>(
+ s, BOOST_ASIO_MOVE_CAST(DynamicBuffer)(buffers),
+ completion_condition, init.completion_handler)(
+ boost::system::error_code(), 0, 1);
return init.result.get();
}
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (boost::system::error_code, std::size_t))
@@ -741,23 +648,25 @@ async_write(AsyncWriteStream& s,
boost::asio::basic_streambuf<Allocator>& b,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a WriteHandler.
- BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
+ return async_write(s, basic_streambuf_ref<Allocator>(b),
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+}
- async_write(s, b.data(), transfer_all(),
- detail::write_streambuf_handler<Allocator, BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- b, init.handler));
-
- return init.result.get();
+template <typename AsyncWriteStream, typename Allocator,
+ typename CompletionCondition, typename WriteHandler>
+inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+async_write(AsyncWriteStream& s,
+ boost::asio::basic_streambuf<Allocator>& b,
+ CompletionCondition completion_condition,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+{
+ return async_write(s, basic_streambuf_ref<Allocator>(b),
+ completion_condition, BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
} // namespace asio
} // namespace boost
diff --git a/boost/asio/impl/write_at.hpp b/boost/asio/impl/write_at.hpp
index 20e95d9338..b1cf426c5e 100644
--- a/boost/asio/impl/write_at.hpp
+++ b/boost/asio/impl/write_at.hpp
@@ -15,6 +15,8 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/associated_executor.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/completion_condition.hpp>
#include <boost/asio/detail/array_fwd.hpp>
@@ -33,28 +35,41 @@
namespace boost {
namespace asio {
+namespace detail
+{
+ template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename ConstBufferIterator, typename CompletionCondition>
+ std::size_t write_at_buffer_sequence(SyncRandomAccessWriteDevice& d,
+ uint64_t offset, const ConstBufferSequence& buffers,
+ const ConstBufferIterator&, CompletionCondition completion_condition,
+ boost::system::error_code& ec)
+ {
+ ec = boost::system::error_code();
+ boost::asio::detail::consuming_buffers<const_buffer,
+ ConstBufferSequence, ConstBufferIterator> tmp(buffers);
+ while (!tmp.empty())
+ {
+ if (std::size_t max_size = detail::adapt_completion_condition_result(
+ completion_condition(ec, tmp.total_consumed())))
+ {
+ tmp.consume(d.write_some_at(offset + tmp.total_consumed(),
+ tmp.prepare(max_size), ec));
+ }
+ else
+ break;
+ }
+ return tmp.total_consumed();;
+ }
+} // namespace detail
+
template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,
typename CompletionCondition>
std::size_t write_at(SyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
CompletionCondition completion_condition, boost::system::error_code& ec)
{
- ec = boost::system::error_code();
- boost::asio::detail::consuming_buffers<
- const_buffer, ConstBufferSequence> tmp(buffers);
- std::size_t total_transferred = 0;
- tmp.prepare(detail::adapt_completion_condition_result(
- completion_condition(ec, total_transferred)));
- while (tmp.begin() != tmp.end())
- {
- std::size_t bytes_transferred = d.write_some_at(
- offset + total_transferred, tmp, ec);
- tmp.consume(bytes_transferred);
- total_transferred += bytes_transferred;
- tmp.prepare(detail::adapt_completion_condition_result(
- completion_condition(ec, total_transferred)));
- }
- return total_transferred;
+ return detail::write_at_buffer_sequence(d, offset, buffers,
+ boost::asio::buffer_sequence_begin(buffers), completion_condition, ec);
}
template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>
@@ -89,6 +104,7 @@ inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
return bytes_transferred;
}
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
template <typename SyncRandomAccessWriteDevice, typename Allocator,
@@ -135,10 +151,12 @@ inline std::size_t write_at(SyncRandomAccessWriteDevice& d,
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
namespace detail
{
- template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ template <typename AsyncRandomAccessWriteDevice,
+ typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
class write_at_op
: detail::base_from_completion_cond<CompletionCondition>
@@ -153,7 +171,6 @@ namespace detail
offset_(offset),
buffers_(buffers),
start_(0),
- total_transferred_(0),
handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
{
}
@@ -165,7 +182,6 @@ namespace detail
offset_(other.offset_),
buffers_(other.buffers_),
start_(other.start_),
- total_transferred_(other.total_transferred_),
handler_(other.handler_)
{
}
@@ -176,7 +192,6 @@ namespace detail
offset_(other.offset_),
buffers_(other.buffers_),
start_(other.start_),
- total_transferred_(other.total_transferred_),
handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
{
}
@@ -185,405 +200,64 @@ namespace detail
void operator()(const boost::system::error_code& ec,
std::size_t bytes_transferred, int start = 0)
{
+ std::size_t max_size;
switch (start_ = start)
{
case 1:
- buffers_.prepare(this->check_for_completion(ec, total_transferred_));
- for (;;)
+ max_size = this->check_for_completion(ec, buffers_.total_consumed());
+ do
{
device_.async_write_some_at(
- offset_ + total_transferred_, buffers_,
+ offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),
BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
return; default:
- total_transferred_ += bytes_transferred;
buffers_.consume(bytes_transferred);
- buffers_.prepare(this->check_for_completion(ec, total_transferred_));
- if ((!ec && bytes_transferred == 0)
- || buffers_.begin() == buffers_.end())
+ if ((!ec && bytes_transferred == 0) || buffers_.empty())
break;
- }
+ max_size = this->check_for_completion(ec, buffers_.total_consumed());
+ } while (max_size > 0);
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
+ handler_(ec, buffers_.total_consumed());
}
}
//private:
AsyncRandomAccessWriteDevice& device_;
uint64_t offset_;
- boost::asio::detail::consuming_buffers<
- const_buffer, ConstBufferSequence> buffers_;
+ boost::asio::detail::consuming_buffers<const_buffer,
+ ConstBufferSequence, ConstBufferIterator> buffers_;
int start_;
- std::size_t total_transferred_;
WriteHandler handler_;
};
template <typename AsyncRandomAccessWriteDevice,
- typename CompletionCondition, typename WriteHandler>
- class write_at_op<AsyncRandomAccessWriteDevice,
- boost::asio::mutable_buffers_1, CompletionCondition, WriteHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- write_at_op(AsyncRandomAccessWriteDevice& device,
- uint64_t offset, const boost::asio::mutable_buffers_1& buffers,
- CompletionCondition completion_condition,
- WriteHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- device_(device),
- offset_(offset),
- buffer_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- write_at_op(const write_at_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- write_at_op(write_at_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- device_.async_write_some_at(offset_ + total_transferred_,
- boost::asio::buffer(buffer_ + total_transferred_, n),
- BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == boost::asio::buffer_size(buffer_))
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncRandomAccessWriteDevice& device_;
- uint64_t offset_;
- boost::asio::mutable_buffer buffer_;
- int start_;
- std::size_t total_transferred_;
- WriteHandler handler_;
- };
-
- template <typename AsyncRandomAccessWriteDevice,
- typename CompletionCondition, typename WriteHandler>
- class write_at_op<AsyncRandomAccessWriteDevice, boost::asio::const_buffers_1,
- CompletionCondition, WriteHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- write_at_op(AsyncRandomAccessWriteDevice& device,
- uint64_t offset, const boost::asio::const_buffers_1& buffers,
- CompletionCondition completion_condition,
- WriteHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- device_(device),
- offset_(offset),
- buffer_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- write_at_op(const write_at_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- write_at_op(write_at_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffer_(other.buffer_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- device_.async_write_some_at(offset_ + total_transferred_,
- boost::asio::buffer(buffer_ + total_transferred_, n),
- BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == boost::asio::buffer_size(buffer_))
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncRandomAccessWriteDevice& device_;
- uint64_t offset_;
- boost::asio::const_buffer buffer_;
- int start_;
- std::size_t total_transferred_;
- WriteHandler handler_;
- };
-
- template <typename AsyncRandomAccessWriteDevice, typename Elem,
- typename CompletionCondition, typename WriteHandler>
- class write_at_op<AsyncRandomAccessWriteDevice, boost::array<Elem, 2>,
- CompletionCondition, WriteHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- write_at_op(AsyncRandomAccessWriteDevice& device,
- uint64_t offset, const boost::array<Elem, 2>& buffers,
- CompletionCondition completion_condition, WriteHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- device_(device),
- offset_(offset),
- buffers_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- write_at_op(const write_at_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- write_at_op(write_at_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- typename boost::asio::detail::dependent_type<Elem,
- boost::array<boost::asio::const_buffer, 2> >::type bufs = {{
- boost::asio::const_buffer(buffers_[0]),
- boost::asio::const_buffer(buffers_[1]) }};
- std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
- std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
- bufs[1] = boost::asio::buffer(
- bufs[1] + (total_transferred_ < buffer_size0
- ? 0 : total_transferred_ - buffer_size0),
- n - boost::asio::buffer_size(bufs[0]));
- device_.async_write_some_at(offset_ + total_transferred_,
- bufs, BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == buffer_size0 + buffer_size1)
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncRandomAccessWriteDevice& device_;
- uint64_t offset_;
- boost::array<Elem, 2> buffers_;
- int start_;
- std::size_t total_transferred_;
- WriteHandler handler_;
- };
-
-#if defined(BOOST_ASIO_HAS_STD_ARRAY)
-
- template <typename AsyncRandomAccessWriteDevice, typename Elem,
- typename CompletionCondition, typename WriteHandler>
- class write_at_op<AsyncRandomAccessWriteDevice, std::array<Elem, 2>,
- CompletionCondition, WriteHandler>
- : detail::base_from_completion_cond<CompletionCondition>
- {
- public:
- write_at_op(AsyncRandomAccessWriteDevice& device,
- uint64_t offset, const std::array<Elem, 2>& buffers,
- CompletionCondition completion_condition, WriteHandler& handler)
- : detail::base_from_completion_cond<
- CompletionCondition>(completion_condition),
- device_(device),
- offset_(offset),
- buffers_(buffers),
- start_(0),
- total_transferred_(0),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))
- {
- }
-
-#if defined(BOOST_ASIO_HAS_MOVE)
- write_at_op(const write_at_op& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(other.handler_)
- {
- }
-
- write_at_op(write_at_op&& other)
- : detail::base_from_completion_cond<CompletionCondition>(other),
- device_(other.device_),
- offset_(other.offset_),
- buffers_(other.buffers_),
- start_(other.start_),
- total_transferred_(other.total_transferred_),
- handler_(BOOST_ASIO_MOVE_CAST(WriteHandler)(other.handler_))
- {
- }
-#endif // defined(BOOST_ASIO_HAS_MOVE)
-
- void operator()(const boost::system::error_code& ec,
- std::size_t bytes_transferred, int start = 0)
- {
- typename boost::asio::detail::dependent_type<Elem,
- std::array<boost::asio::const_buffer, 2> >::type bufs = {{
- boost::asio::const_buffer(buffers_[0]),
- boost::asio::const_buffer(buffers_[1]) }};
- std::size_t buffer_size0 = boost::asio::buffer_size(bufs[0]);
- std::size_t buffer_size1 = boost::asio::buffer_size(bufs[1]);
- std::size_t n = 0;
- switch (start_ = start)
- {
- case 1:
- n = this->check_for_completion(ec, total_transferred_);
- for (;;)
- {
- bufs[0] = boost::asio::buffer(bufs[0] + total_transferred_, n);
- bufs[1] = boost::asio::buffer(
- bufs[1] + (total_transferred_ < buffer_size0
- ? 0 : total_transferred_ - buffer_size0),
- n - boost::asio::buffer_size(bufs[0]));
- device_.async_write_some_at(offset_ + total_transferred_,
- bufs, BOOST_ASIO_MOVE_CAST(write_at_op)(*this));
- return; default:
- total_transferred_ += bytes_transferred;
- if ((!ec && bytes_transferred == 0)
- || (n = this->check_for_completion(ec, total_transferred_)) == 0
- || total_transferred_ == buffer_size0 + buffer_size1)
- break;
- }
-
- handler_(ec, static_cast<const std::size_t&>(total_transferred_));
- }
- }
-
- //private:
- AsyncRandomAccessWriteDevice& device_;
- uint64_t offset_;
- std::array<Elem, 2> buffers_;
- int start_;
- std::size_t total_transferred_;
- WriteHandler handler_;
- };
-
-#endif // defined(BOOST_ASIO_HAS_STD_ARRAY)
-
- template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void* asio_handler_allocate(std::size_t size,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
- CompletionCondition, WriteHandler>* this_handler)
+ ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
return boost_asio_handler_alloc_helpers::allocate(
size, this_handler->handler_);
}
- template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ template <typename AsyncRandomAccessWriteDevice,
+ typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline void asio_handler_deallocate(void* pointer, std::size_t size,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
- CompletionCondition, WriteHandler>* this_handler)
+ ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_alloc_helpers::deallocate(
pointer, size, this_handler->handler_);
}
- template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ template <typename AsyncRandomAccessWriteDevice,
+ typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
inline bool asio_handler_is_continuation(
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
- CompletionCondition, WriteHandler>* this_handler)
+ ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
return this_handler->start_ == 0 ? true
: boost_asio_handler_cont_helpers::is_continuation(
@@ -591,41 +265,86 @@ namespace detail
}
template <typename Function, typename AsyncRandomAccessWriteDevice,
- typename ConstBufferSequence, typename CompletionCondition,
- typename WriteHandler>
+ typename ConstBufferSequence, typename ConstBufferIterator,
+ typename CompletionCondition, typename WriteHandler>
inline void asio_handler_invoke(Function& function,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
- CompletionCondition, WriteHandler>* this_handler)
+ ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
template <typename Function, typename AsyncRandomAccessWriteDevice,
- typename ConstBufferSequence, typename CompletionCondition,
- typename WriteHandler>
+ typename ConstBufferSequence, typename ConstBufferIterator,
+ typename CompletionCondition, typename WriteHandler>
inline void asio_handler_invoke(const Function& function,
write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
- CompletionCondition, WriteHandler>* this_handler)
+ ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)
{
boost_asio_handler_invoke_helpers::invoke(
function, this_handler->handler_);
}
- template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
+ template <typename AsyncRandomAccessWriteDevice,
+ typename ConstBufferSequence, typename ConstBufferIterator,
typename CompletionCondition, typename WriteHandler>
- inline write_at_op<AsyncRandomAccessWriteDevice,
- ConstBufferSequence, CompletionCondition, WriteHandler>
- make_write_at_op(AsyncRandomAccessWriteDevice& d,
+ inline void start_write_at_buffer_sequence_op(AsyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
- CompletionCondition completion_condition, WriteHandler handler)
+ const ConstBufferIterator&, CompletionCondition completion_condition,
+ WriteHandler& handler)
{
- return write_at_op<AsyncRandomAccessWriteDevice,
- ConstBufferSequence, CompletionCondition, WriteHandler>(
- d, offset, buffers, completion_condition, handler);
+ detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+ ConstBufferIterator, CompletionCondition, WriteHandler>(
+ d, offset, buffers, completion_condition, handler)(
+ boost::system::error_code(), 0, 1);
}
} // namespace detail
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename AsyncRandomAccessWriteDevice,
+ typename ConstBufferSequence, typename ConstBufferIterator,
+ typename CompletionCondition, typename WriteHandler, typename Allocator>
+struct associated_allocator<
+ detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
+ ConstBufferIterator, CompletionCondition, WriteHandler>,
+ Allocator>
+{
+ typedef typename associated_allocator<WriteHandler, Allocator>::type type;
+
+ static type get(
+ const detail::write_at_op<AsyncRandomAccessWriteDevice,
+ ConstBufferSequence, ConstBufferIterator,
+ CompletionCondition, WriteHandler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
+ }
+};
+
+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>
+{
+ typedef typename associated_executor<WriteHandler, Executor>::type type;
+
+ static type get(
+ const detail::write_at_op<AsyncRandomAccessWriteDevice,
+ ConstBufferSequence, ConstBufferIterator,
+ CompletionCondition, WriteHandler>& h,
+ const Executor& ex = Executor()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,
typename CompletionCondition, typename WriteHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
@@ -639,15 +358,12 @@ async_write_at(AsyncRandomAccessWriteDevice& d,
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
- CompletionCondition, BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- d, offset, buffers, completion_condition, init.handler)(
- boost::system::error_code(), 0, 1);
+ detail::start_write_at_buffer_sequence_op(d, offset, buffers,
+ boost::asio::buffer_sequence_begin(buffers), completion_condition,
+ init.completion_handler);
return init.result.get();
}
@@ -664,19 +380,17 @@ async_write_at(AsyncRandomAccessWriteDevice& d,
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,
- detail::transfer_all_t, BOOST_ASIO_HANDLER_TYPE(
- WriteHandler, void (boost::system::error_code, std::size_t))>(
- d, offset, buffers, transfer_all(), init.handler)(
- boost::system::error_code(), 0, 1);
+ detail::start_write_at_buffer_sequence_op(d, offset, buffers,
+ boost::asio::buffer_sequence_begin(buffers), transfer_all(),
+ init.completion_handler);
return init.result.get();
}
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
namespace detail
@@ -768,6 +482,40 @@ namespace detail
}
} // namespace detail
+#if !defined(GENERATING_DOCUMENTATION)
+
+template <typename Allocator, typename WriteHandler, typename Allocator1>
+struct associated_allocator<
+ detail::write_at_streambuf_op<Allocator, WriteHandler>,
+ Allocator1>
+{
+ typedef typename associated_allocator<WriteHandler, Allocator1>::type type;
+
+ static type get(
+ const detail::write_at_streambuf_op<Allocator, WriteHandler>& h,
+ const Allocator1& a = Allocator1()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<WriteHandler, Allocator1>::get(h.handler_, a);
+ }
+};
+
+template <typename Executor, typename WriteHandler, typename Executor1>
+struct associated_executor<
+ detail::write_at_streambuf_op<Executor, WriteHandler>,
+ Executor1>
+{
+ typedef typename associated_executor<WriteHandler, Executor1>::type type;
+
+ static type get(
+ const detail::write_at_streambuf_op<Executor, WriteHandler>& h,
+ const Executor1& ex = Executor1()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<WriteHandler, Executor1>::get(h.handler_, ex);
+ }
+};
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
template <typename AsyncRandomAccessWriteDevice, typename Allocator,
typename CompletionCondition, typename WriteHandler>
inline BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
@@ -781,14 +529,13 @@ async_write_at(AsyncRandomAccessWriteDevice& d,
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
async_write_at(d, offset, b.data(), completion_condition,
detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE(
WriteHandler, void (boost::system::error_code, std::size_t))>(
- b, init.handler));
+ b, init.completion_handler));
return init.result.get();
}
@@ -805,19 +552,19 @@ async_write_at(AsyncRandomAccessWriteDevice& d,
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
async_write_at(d, offset, b.data(), transfer_all(),
detail::write_at_streambuf_op<Allocator, BOOST_ASIO_HANDLER_TYPE(
WriteHandler, void (boost::system::error_code, std::size_t))>(
- b, init.handler));
+ b, init.completion_handler));
return init.result.get();
}
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
} // namespace asio
} // namespace boost
diff --git a/boost/asio/io_context.hpp b/boost/asio/io_context.hpp
new file mode 100644
index 0000000000..2eb3c4624f
--- /dev/null
+++ b/boost/asio/io_context.hpp
@@ -0,0 +1,878 @@
+//
+// io_context.hpp
+// ~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IO_CONTEXT_HPP
+#define BOOST_ASIO_IO_CONTEXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <stdexcept>
+#include <typeinfo>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/wrapped_handler.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/asio/execution_context.hpp>
+
+#if defined(BOOST_ASIO_HAS_CHRONO)
+# include <boost/asio/detail/chrono.hpp>
+#endif // defined(BOOST_ASIO_HAS_CHRONO)
+
+#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+# include <boost/asio/detail/winsock_init.hpp>
+#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \
+ || defined(__osf__)
+# include <boost/asio/detail/signal_init.hpp>
+#endif
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+namespace detail {
+#if defined(BOOST_ASIO_HAS_IOCP)
+ typedef class win_iocp_io_context io_context_impl;
+ class win_iocp_overlapped_ptr;
+#else
+ typedef class scheduler io_context_impl;
+#endif
+} // namespace detail
+
+/// Provides core I/O functionality.
+/**
+ * The io_context class provides the core I/O functionality for users of the
+ * asynchronous I/O objects, including:
+ *
+ * @li boost::asio::ip::tcp::socket
+ * @li boost::asio::ip::tcp::acceptor
+ * @li boost::asio::ip::udp::socket
+ * @li boost::asio::deadline_timer.
+ *
+ * The io_context class also includes facilities intended for developers of
+ * custom asynchronous services.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Safe, with the specific exceptions of the restart()
+ * and notify_fork() functions. Calling restart() while there are unfinished
+ * run(), run_one(), run_for(), run_until(), poll() or poll_one() calls results
+ * in undefined behaviour. The notify_fork() function should not be called
+ * while any io_context function, or any function on an I/O object that is
+ * associated with the io_context, is being called in another thread.
+ *
+ * @par Concepts:
+ * Dispatcher.
+ *
+ * @par Synchronous and asynchronous operations
+ *
+ * Synchronous operations on I/O objects implicitly run the io_context object
+ * for an individual operation. The io_context functions run(), run_one(),
+ * run_for(), run_until(), poll() or poll_one() must be called for the
+ * io_context to perform asynchronous operations on behalf of a C++ program.
+ * Notification that an asynchronous operation has completed is delivered by
+ * invocation of the associated handler. Handlers are invoked only by a thread
+ * that is currently calling any overload of run(), run_one(), run_for(),
+ * run_until(), poll() or poll_one() for the io_context.
+ *
+ * @par Effect of exceptions thrown from handlers
+ *
+ * If an exception is thrown from a handler, the exception is allowed to
+ * propagate through the throwing thread's invocation of run(), run_one(),
+ * run_for(), run_until(), poll() or poll_one(). No other threads that are
+ * calling any of these functions are affected. It is then the responsibility
+ * of the application to catch the exception.
+ *
+ * After the exception has been caught, the run(), run_one(), run_for(),
+ * run_until(), poll() or poll_one() call may be restarted @em without the need
+ * for an intervening call to restart(). This allows the thread to rejoin the
+ * io_context object's thread pool without impacting any other threads in the
+ * pool.
+ *
+ * For example:
+ *
+ * @code
+ * boost::asio::io_context io_context;
+ * ...
+ * for (;;)
+ * {
+ * try
+ * {
+ * io_context.run();
+ * break; // run() exited normally
+ * }
+ * catch (my_exception& e)
+ * {
+ * // Deal with exception as appropriate.
+ * }
+ * }
+ * @endcode
+ *
+ * @par Submitting arbitrary tasks to the io_context
+ *
+ * To submit functions to the io_context, use the @ref boost::asio::dispatch,
+ * @ref boost::asio::post or @ref boost::asio::defer free functions.
+ *
+ * For example:
+ *
+ * @code void my_task()
+ * {
+ * ...
+ * }
+ *
+ * ...
+ *
+ * boost::asio::io_context io_context;
+ *
+ * // Submit a function to the io_context.
+ * boost::asio::post(io_context, my_task);
+ *
+ * // Submit a lambda object to the io_context.
+ * boost::asio::post(io_context,
+ * []()
+ * {
+ * ...
+ * });
+ *
+ * // Run the io_context until it runs out of work.
+ * io_context.run(); @endcode
+ *
+ * @par Stopping the io_context from running out of work
+ *
+ * Some applications may need to prevent an io_context object's run() call from
+ * 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 object of type
+ * boost::asio::executor_work_guard<io_context::executor_type>:
+ *
+ * @code boost::asio::io_context io_context;
+ * boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
+ * = boost::asio::make_work_guard(io_context);
+ * ... @endcode
+ *
+ * To effect a shutdown, the application will then need to call the io_context
+ * object's stop() member function. This will cause the io_context run() call
+ * to return as soon as possible, abandoning unfinished operations and without
+ * permitting ready handlers to be dispatched.
+ *
+ * Alternatively, if the application requires that all operations and handlers
+ * be allowed to finish normally, the work object may be explicitly reset.
+ *
+ * @code boost::asio::io_context io_context;
+ * boost::asio::executor_work_guard<boost::asio::io_context::executor_type>
+ * = boost::asio::make_work_guard(io_context);
+ * ...
+ * work.reset(); // Allow run() to exit. @endcode
+ */
+class io_context
+ : public execution_context
+{
+private:
+ typedef detail::io_context_impl impl_type;
+#if defined(BOOST_ASIO_HAS_IOCP)
+ friend class detail::win_iocp_overlapped_ptr;
+#endif
+
+public:
+ class executor_type;
+ friend class executor_type;
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ class work;
+ friend class work;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ class service;
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+ class strand;
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+ /// The type used to count the number of handlers executed by the context.
+ typedef std::size_t count_type;
+
+ /// Constructor.
+ BOOST_ASIO_DECL io_context();
+
+ /// Constructor.
+ /**
+ * Construct with a hint about the required level of concurrency.
+ *
+ * @param concurrency_hint A suggestion to the implementation on how many
+ * threads it should allow to run simultaneously.
+ */
+ BOOST_ASIO_DECL explicit io_context(int concurrency_hint);
+
+ /// Destructor.
+ /**
+ * On destruction, the io_context performs the following sequence of
+ * operations:
+ *
+ * @li For each service object @c svc in the io_context set, in reverse order
+ * of the beginning of service object lifetime, performs
+ * @c svc->shutdown().
+ *
+ * @li Uninvoked handler objects that were scheduled for deferred invocation
+ * on the io_context, or any associated strand, are destroyed.
+ *
+ * @li For each service object @c svc in the io_context set, in reverse order
+ * of the beginning of service object lifetime, performs
+ * <tt>delete static_cast<io_context::service*>(svc)</tt>.
+ *
+ * @note The destruction sequence described above permits programs to
+ * simplify their resource management by using @c shared_ptr<>. Where an
+ * object's lifetime is tied to the lifetime of a connection (or some other
+ * sequence of asynchronous operations), a @c shared_ptr to the object would
+ * be bound into the handlers for all asynchronous operations associated with
+ * it. This works as follows:
+ *
+ * @li When a single connection ends, all associated asynchronous operations
+ * complete. The corresponding handler objects are destroyed, and all
+ * @c shared_ptr references to the objects are destroyed.
+ *
+ * @li To shut down the whole program, the io_context function stop() is
+ * called to terminate any run() calls as soon as possible. The io_context
+ * destructor defined above destroys all handlers, causing all @c shared_ptr
+ * references to all connection objects to be destroyed.
+ */
+ BOOST_ASIO_DECL ~io_context();
+
+ /// Obtains the executor associated with the io_context.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT;
+
+ /// Run the io_context object's event processing loop.
+ /**
+ * The run() function blocks until all work has finished and there are no
+ * more handlers to be dispatched, or until the io_context has been stopped.
+ *
+ * Multiple threads may call the run() function to set up a pool of threads
+ * from which the io_context may execute handlers. All threads that are
+ * waiting in the pool are equivalent and the io_context may choose any one
+ * of them to invoke a handler.
+ *
+ * A normal exit from the run() function implies that the io_context object
+ * is stopped (the stopped() function returns @c true). Subsequent calls to
+ * run(), run_one(), poll() or poll_one() will return immediately unless there
+ * is a prior call to restart().
+ *
+ * @return The number of handlers that were executed.
+ *
+ * @note Calling the run() function from a thread that is currently calling
+ * one of run(), run_one(), run_for(), run_until(), poll() or poll_one() on
+ * the same io_context object may introduce the potential for deadlock. It is
+ * the caller's reponsibility to avoid this.
+ *
+ * The poll() function may also be used to dispatch ready handlers, but
+ * without blocking.
+ */
+ BOOST_ASIO_DECL count_type run();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use non-error_code overload.) Run the io_context object's
+ /// event processing loop.
+ /**
+ * The run() function blocks until all work has finished and there are no
+ * more handlers to be dispatched, or until the io_context has been stopped.
+ *
+ * Multiple threads may call the run() function to set up a pool of threads
+ * from which the io_context may execute handlers. All threads that are
+ * waiting in the pool are equivalent and the io_context may choose any one
+ * of them to invoke a handler.
+ *
+ * A normal exit from the run() function implies that the io_context object
+ * is stopped (the stopped() function returns @c true). Subsequent calls to
+ * run(), run_one(), poll() or poll_one() will return immediately unless there
+ * is a prior call to restart().
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of handlers that were executed.
+ *
+ * @note Calling the run() function from a thread that is currently calling
+ * one of run(), run_one(), run_for(), run_until(), poll() or poll_one() on
+ * the same io_context object may introduce the potential for deadlock. It is
+ * the caller's reponsibility to avoid this.
+ *
+ * The poll() function may also be used to dispatch ready handlers, but
+ * without blocking.
+ */
+ BOOST_ASIO_DECL count_type run(boost::system::error_code& ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+#if defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)
+ /// Run the io_context object's event processing loop for a specified
+ /// duration.
+ /**
+ * The run_for() function blocks until all work has finished and there are no
+ * more handlers to be dispatched, until the io_context has been stopped, or
+ * until the specified duration has elapsed.
+ *
+ * @param rel_time The duration for which the call may block.
+ *
+ * @return The number of handlers that were executed.
+ */
+ template <typename Rep, typename Period>
+ std::size_t run_for(const chrono::duration<Rep, Period>& rel_time);
+
+ /// Run the io_context object's event processing loop until a specified time.
+ /**
+ * The run_until() function blocks until all work has finished and there are
+ * no more handlers to be dispatched, until the io_context has been stopped,
+ * or until the specified time has been reached.
+ *
+ * @param abs_time The time point until which the call may block.
+ *
+ * @return The number of handlers that were executed.
+ */
+ template <typename Clock, typename Duration>
+ std::size_t run_until(const chrono::time_point<Clock, Duration>& abs_time);
+#endif // defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)
+
+ /// 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
+ * until the io_context has been stopped.
+ *
+ * @return The number of handlers that were executed. A zero return value
+ * implies that the io_context object is stopped (the stopped() function
+ * returns @c true). Subsequent calls to run(), run_one(), poll() or
+ * poll_one() will return immediately unless there is a prior call to
+ * restart().
+ *
+ * @note Calling the run_one() function from a thread that is currently
+ * calling one of run(), run_one(), run_for(), run_until(), poll() or
+ * poll_one() on the same io_context object may introduce the potential for
+ * deadlock. It is the caller's reponsibility to avoid this.
+ */
+ BOOST_ASIO_DECL count_type run_one();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use non-error_code overlaod.) 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
+ * until the io_context has been stopped.
+ *
+ * @return The number of handlers that were executed. A zero return value
+ * implies that the io_context object is stopped (the stopped() function
+ * returns @c true). Subsequent calls to run(), run_one(), poll() or
+ * poll_one() will return immediately unless there is a prior call to
+ * restart().
+ *
+ * @return The number of handlers that were executed.
+ *
+ * @note Calling the run_one() function from a thread that is currently
+ * calling one of run(), run_one(), run_for(), run_until(), poll() or
+ * poll_one() on the same io_context object may introduce the potential for
+ * deadlock. It is the caller's reponsibility to avoid this.
+ */
+ BOOST_ASIO_DECL count_type run_one(boost::system::error_code& ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+#if defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)
+ /// Run the io_context object's event processing loop for a specified duration
+ /// to execute at most one handler.
+ /**
+ * The run_one_for() function blocks until one handler has been dispatched,
+ * until the io_context has been stopped, or until the specified duration has
+ * elapsed.
+ *
+ * @param rel_time The duration for which the call may block.
+ *
+ * @return The number of handlers that were executed.
+ */
+ template <typename Rep, typename Period>
+ std::size_t run_one_for(const chrono::duration<Rep, Period>& rel_time);
+
+ /// Run the io_context object's event processing loop until a specified time
+ /// to execute at most one handler.
+ /**
+ * The run_one_until() function blocks until one handler has been dispatched,
+ * until the io_context has been stopped, or until the specified time has
+ * been reached.
+ *
+ * @param abs_time The time point until which the call may block.
+ *
+ * @return The number of handlers that were executed.
+ */
+ template <typename Clock, typename Duration>
+ std::size_t run_one_until(
+ const chrono::time_point<Clock, Duration>& abs_time);
+#endif // defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)
+
+ /// Run the io_context object's event processing loop to execute ready
+ /// handlers.
+ /**
+ * The poll() function runs handlers that are ready to run, without blocking,
+ * until the io_context has been stopped or there are no more ready handlers.
+ *
+ * @return The number of handlers that were executed.
+ */
+ BOOST_ASIO_DECL count_type poll();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use non-error_code overload.) Run the io_context object's
+ /// event processing loop to execute ready handlers.
+ /**
+ * The poll() function runs handlers that are ready to run, without blocking,
+ * until the io_context has been stopped or there are no more ready handlers.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of handlers that were executed.
+ */
+ BOOST_ASIO_DECL count_type poll(boost::system::error_code& ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Run the io_context object's event processing loop to execute one ready
+ /// handler.
+ /**
+ * The poll_one() function runs at most one handler that is ready to run,
+ * without blocking.
+ *
+ * @return The number of handlers that were executed.
+ */
+ BOOST_ASIO_DECL count_type poll_one();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use non-error_code overload.) Run the io_context object's
+ /// event processing loop to execute one ready handler.
+ /**
+ * The poll_one() function runs at most one handler that is ready to run,
+ * without blocking.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @return The number of handlers that were executed.
+ */
+ BOOST_ASIO_DECL count_type poll_one(boost::system::error_code& ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Stop the io_context object's event processing loop.
+ /**
+ * This function does not block, but instead simply signals the io_context to
+ * stop. All invocations of its run() or run_one() member functions should
+ * return as soon as possible. Subsequent calls to run(), run_one(), poll()
+ * or poll_one() will return immediately until restart() is called.
+ */
+ BOOST_ASIO_DECL void stop();
+
+ /// Determine whether the io_context object has been stopped.
+ /**
+ * This function is used to determine whether an io_context object has been
+ * stopped, either through an explicit call to stop(), or due to running out
+ * of work. When an io_context object is stopped, calls to run(), run_one(),
+ * poll() or poll_one() will return immediately without invoking any
+ * handlers.
+ *
+ * @return @c true if the io_context object is stopped, otherwise @c false.
+ */
+ BOOST_ASIO_DECL bool stopped() const;
+
+ /// Restart the io_context in preparation for a subsequent run() invocation.
+ /**
+ * This function must be called prior to any second or later set of
+ * invocations of the run(), run_one(), poll() or poll_one() functions when a
+ * previous invocation of these functions returned due to the io_context
+ * being stopped or running out of work. After a call to restart(), the
+ * io_context object's stopped() function will return @c false.
+ *
+ * This function must not be called while there are any unfinished calls to
+ * the run(), run_one(), poll() or poll_one() functions.
+ */
+ BOOST_ASIO_DECL void restart();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use restart().) Reset the io_context in preparation for a
+ /// subsequent run() invocation.
+ /**
+ * This function must be called prior to any second or later set of
+ * invocations of the run(), run_one(), poll() or poll_one() functions when a
+ * previous invocation of these functions returned due to the io_context
+ * being stopped or running out of work. After a call to restart(), the
+ * io_context object's stopped() function will return @c false.
+ *
+ * This function must not be called while there are any unfinished calls to
+ * the run(), run_one(), poll() or poll_one() functions.
+ */
+ void reset();
+
+ /// (Deprecated: Use boost::asio::dispatch().) Request the io_context to
+ /// invoke the given handler.
+ /**
+ * This function is used to ask the io_context to execute the given handler.
+ *
+ * The io_context guarantees that the handler will only be called in a thread
+ * in which the run(), run_one(), poll() or poll_one() member functions is
+ * currently being invoked. The handler may be executed inside this function
+ * if the guarantee can be met.
+ *
+ * @param handler The handler to be called. The io_context will make
+ * a copy of the handler object as required. The function signature of the
+ * handler must be: @code void handler(); @endcode
+ *
+ * @note This function throws an exception only if:
+ *
+ * @li the handler's @c asio_handler_allocate function; or
+ *
+ * @li the handler's copy constructor
+ *
+ * throws an exception.
+ */
+ template <typename CompletionHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
+ dispatch(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler);
+
+ /// (Deprecated: Use boost::asio::post().) Request the io_context to invoke
+ /// the given handler and return immediately.
+ /**
+ * This function is used to ask the io_context to execute the given handler,
+ * but without allowing the io_context to call the handler from inside this
+ * function.
+ *
+ * The io_context guarantees that the handler will only be called in a thread
+ * in which the run(), run_one(), poll() or poll_one() member functions is
+ * currently being invoked.
+ *
+ * @param handler The handler to be called. The io_context will make
+ * a copy of the handler object as required. The function signature of the
+ * handler must be: @code void handler(); @endcode
+ *
+ * @note This function throws an exception only if:
+ *
+ * @li the handler's @c asio_handler_allocate function; or
+ *
+ * @li the handler's copy constructor
+ *
+ * throws an exception.
+ */
+ template <typename CompletionHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
+ post(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler);
+
+ /// (Deprecated: Use boost::asio::bind_executor().) Create a new handler that
+ /// automatically dispatches the wrapped handler on the io_context.
+ /**
+ * This function is used to create a new handler function object that, when
+ * invoked, will automatically pass the wrapped handler to the io_context
+ * object's dispatch function.
+ *
+ * @param handler The handler to be wrapped. The io_context will make a copy
+ * of the handler object as required. The function signature of the handler
+ * must be: @code void handler(A1 a1, ... An an); @endcode
+ *
+ * @return A function object that, when invoked, passes the wrapped handler to
+ * the io_context object's dispatch function. Given a function object with the
+ * signature:
+ * @code R f(A1 a1, ... An an); @endcode
+ * If this function object is passed to the wrap function like so:
+ * @code io_context.wrap(f); @endcode
+ * then the return value is a function object with the signature
+ * @code void g(A1 a1, ... An an); @endcode
+ * that, when invoked, executes code equivalent to:
+ * @code io_context.dispatch(boost::bind(f, a1, ... an)); @endcode
+ */
+ template <typename Handler>
+#if defined(GENERATING_DOCUMENTATION)
+ unspecified
+#else
+ detail::wrapped_handler<io_context&, Handler>
+#endif
+ wrap(Handler handler);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+private:
+ // Helper function to add the implementation.
+ BOOST_ASIO_DECL impl_type& add_impl(impl_type* impl);
+
+ // Backwards compatible overload for use with services derived from
+ // io_context::service.
+ template <typename Service>
+ friend Service& use_service(io_context& ioc);
+
+#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
+ detail::winsock_init<> init_;
+#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \
+ || defined(__osf__)
+ detail::signal_init<> init_;
+#endif
+
+ // The implementation.
+ impl_type& impl_;
+};
+
+/// Executor used to submit functions to an io_context.
+class io_context::executor_type
+{
+public:
+ /// Obtain the underlying execution context.
+ io_context& context() const BOOST_ASIO_NOEXCEPT;
+
+ /// Inform the io_context that it has some outstanding work to do.
+ /**
+ * This function is used to inform the io_context that some work has begun.
+ * This ensures that the io_context's run() and run_one() functions do not
+ * exit while the work is underway.
+ */
+ void on_work_started() const BOOST_ASIO_NOEXCEPT;
+
+ /// Inform the io_context that some work is no longer outstanding.
+ /**
+ * This function is used to inform the io_context that some work has
+ * finished. Once the count of unfinished work reaches zero, the io_context
+ * is stopped and the run() and run_one() functions may exit.
+ */
+ void on_work_finished() const BOOST_ASIO_NOEXCEPT;
+
+ /// Request the io_context to invoke the given function object.
+ /**
+ * This function is used to ask the io_context to execute the given function
+ * object. If the current thread is running the io_context, @c dispatch()
+ * executes the function before returning. Otherwise, the function will be
+ * scheduled to run on the io_context.
+ *
+ * @param f The function object to be called. The executor will make a copy
+ * of the handler object as required. The function signature of the function
+ * object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ /// Request the io_context to invoke the given function object.
+ /**
+ * This function is used to ask the io_context to execute the given function
+ * object. The function object will never be executed inside @c post().
+ * Instead, it will be scheduled to run on the io_context.
+ *
+ * @param f The function object to be called. The executor will make a copy
+ * of the handler object as required. The function signature of the function
+ * object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void post(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ /// Request the io_context to invoke the given function object.
+ /**
+ * This function is used to ask the io_context to execute the given function
+ * object. The function object will never be executed inside @c defer().
+ * Instead, it will be scheduled to run on the io_context.
+ *
+ * If the current thread belongs to the io_context, @c defer() will delay
+ * scheduling the function object until the current thread returns control to
+ * the pool.
+ *
+ * @param f The function object to be called. The executor will make a copy
+ * of the handler object as required. The function signature of the function
+ * object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void defer(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ /// Determine whether the io_context is running in the current thread.
+ /**
+ * @return @c true if the current thread is running the io_context. Otherwise
+ * returns @c false.
+ */
+ bool running_in_this_thread() const BOOST_ASIO_NOEXCEPT;
+
+ /// Compare two executors for equality.
+ /**
+ * Two executors are equal if they refer to the same underlying io_context.
+ */
+ friend bool operator==(const executor_type& a,
+ const executor_type& b) BOOST_ASIO_NOEXCEPT
+ {
+ return &a.io_context_ == &b.io_context_;
+ }
+
+ /// Compare two executors for inequality.
+ /**
+ * Two executors are equal if they refer to the same underlying io_context.
+ */
+ friend bool operator!=(const executor_type& a,
+ const executor_type& b) BOOST_ASIO_NOEXCEPT
+ {
+ return &a.io_context_ != &b.io_context_;
+ }
+
+private:
+ friend class io_context;
+
+ // Constructor.
+ explicit executor_type(io_context& i) : io_context_(i) {}
+
+ // The underlying io_context.
+ io_context& io_context_;
+};
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+/// (Deprecated: Use executor_work_guard.) Class to inform the io_context when
+/// it has work to do.
+/**
+ * The work class is used to inform the io_context when work starts and
+ * finishes. This ensures that the io_context object's run() function will not
+ * exit while work is underway, and that it does exit when there is no
+ * unfinished work remaining.
+ *
+ * The work class is copy-constructible so that it may be used as a data member
+ * in a handler class. It is not assignable.
+ */
+class io_context::work
+{
+public:
+ /// Constructor notifies the io_context that work is starting.
+ /**
+ * The constructor is used to inform the io_context that some work has begun.
+ * This ensures that the io_context object's run() function will not exit
+ * while the work is underway.
+ */
+ explicit work(boost::asio::io_context& io_context);
+
+ /// Copy constructor notifies the io_context that work is starting.
+ /**
+ * The constructor is used to inform the io_context that some work has begun.
+ * This ensures that the io_context object's run() function will not exit
+ * while the work is underway.
+ */
+ work(const work& other);
+
+ /// Destructor notifies the io_context that the work is complete.
+ /**
+ * The destructor is used to inform the io_context that some work has
+ * finished. Once the count of unfinished work reaches zero, the io_context
+ * object's run() function is permitted to exit.
+ */
+ ~work();
+
+ /// Get the io_context associated with the work.
+ boost::asio::io_context& get_io_context();
+
+ /// (Deprecated: Use get_io_context().) Get the io_context associated with the
+ /// work.
+ boost::asio::io_context& get_io_service();
+
+private:
+ // Prevent assignment.
+ void operator=(const work& other);
+
+ // The io_context implementation.
+ detail::io_context_impl& io_context_impl_;
+};
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+/// Base class for all io_context services.
+class io_context::service
+ : public execution_context::service
+{
+public:
+ /// Get the io_context object that owns the service.
+ boost::asio::io_context& get_io_context();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// Get the io_context object that owns the service.
+ boost::asio::io_context& get_io_service();
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+private:
+ /// Destroy all user-defined handler objects owned by the service.
+ BOOST_ASIO_DECL virtual void shutdown();
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use shutdown().) Destroy all user-defined handler objects
+ /// owned by the service.
+ BOOST_ASIO_DECL virtual void shutdown_service();
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Handle notification of a fork-related event to perform any necessary
+ /// housekeeping.
+ /**
+ * This function is not a pure virtual so that services only have to
+ * implement it if necessary. The default implementation does nothing.
+ */
+ BOOST_ASIO_DECL virtual void notify_fork(
+ execution_context::fork_event event);
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use notify_fork().) Handle notification of a fork-related
+ /// event to perform any necessary housekeeping.
+ /**
+ * This function is not a pure virtual so that services only have to
+ * implement it if necessary. The default implementation does nothing.
+ */
+ BOOST_ASIO_DECL virtual void fork_service(
+ execution_context::fork_event event);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+protected:
+ /// Constructor.
+ /**
+ * @param owner The io_context object that owns the service.
+ */
+ BOOST_ASIO_DECL service(boost::asio::io_context& owner);
+
+ /// Destructor.
+ BOOST_ASIO_DECL virtual ~service();
+};
+
+namespace detail {
+
+// Special service base class to keep classes header-file only.
+template <typename Type>
+class service_base
+ : public boost::asio::io_context::service
+{
+public:
+ static boost::asio::detail::service_id<Type> id;
+
+ // Constructor.
+ service_base(boost::asio::io_context& io_context)
+ : boost::asio::io_context::service(io_context)
+ {
+ }
+};
+
+template <typename Type>
+boost::asio::detail::service_id<Type> service_base<Type>::id;
+
+} // namespace detail
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/impl/io_context.hpp>
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/impl/io_context.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+// If both io_context.hpp and strand.hpp have been included, automatically
+// include the header file needed for the io_context::strand class.
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+# if defined(BOOST_ASIO_STRAND_HPP)
+# include <boost/asio/io_context_strand.hpp>
+# endif // defined(BOOST_ASIO_STRAND_HPP)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+#endif // BOOST_ASIO_IO_CONTEXT_HPP
diff --git a/boost/asio/io_context_strand.hpp b/boost/asio/io_context_strand.hpp
new file mode 100644
index 0000000000..2190a7b7db
--- /dev/null
+++ b/boost/asio/io_context_strand.hpp
@@ -0,0 +1,384 @@
+//
+// io_context_strand.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IO_CONTEXT_STRAND_HPP
+#define BOOST_ASIO_IO_CONTEXT_STRAND_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/strand_service.hpp>
+#include <boost/asio/detail/wrapped_handler.hpp>
+#include <boost/asio/io_context.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Provides serialised handler execution.
+/**
+ * The io_context::strand class provides the ability to post and dispatch
+ * handlers with the guarantee that none of those handlers will execute
+ * concurrently.
+ *
+ * @par Order of handler invocation
+ * Given:
+ *
+ * @li a strand object @c s
+ *
+ * @li an object @c a meeting completion handler requirements
+ *
+ * @li an object @c a1 which is an arbitrary copy of @c a made by the
+ * implementation
+ *
+ * @li an object @c b meeting completion handler requirements
+ *
+ * @li an object @c b1 which is an arbitrary copy of @c b made by the
+ * implementation
+ *
+ * if any of the following conditions are true:
+ *
+ * @li @c s.post(a) happens-before @c s.post(b)
+ *
+ * @li @c s.post(a) happens-before @c s.dispatch(b), where the latter is
+ * performed outside the strand
+ *
+ * @li @c s.dispatch(a) happens-before @c s.post(b), where the former is
+ * performed outside the strand
+ *
+ * @li @c s.dispatch(a) happens-before @c s.dispatch(b), where both are
+ * performed outside the strand
+ *
+ * then @c asio_handler_invoke(a1, &a1) happens-before
+ * @c asio_handler_invoke(b1, &b1).
+ *
+ * Note that in the following case:
+ * @code async_op_1(..., s.wrap(a));
+ * async_op_2(..., s.wrap(b)); @endcode
+ * the completion of the first async operation will perform @c s.dispatch(a),
+ * and the second will perform @c s.dispatch(b), but the order in which those
+ * are performed is unspecified. That is, you cannot state whether one
+ * happens-before the other. Therefore none of the above conditions are met and
+ * no ordering guarantee is made.
+ *
+ * @note The implementation makes no guarantee that handlers posted or
+ * dispatched through different @c strand objects will be invoked concurrently.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Safe.
+ *
+ * @par Concepts:
+ * Dispatcher.
+ */
+class io_context::strand
+{
+public:
+ /// Constructor.
+ /**
+ * Constructs the strand.
+ *
+ * @param io_context The io_context object that the strand will use to
+ * dispatch handlers that are ready to be run.
+ */
+ explicit strand(boost::asio::io_context& io_context)
+ : service_(boost::asio::use_service<
+ boost::asio::detail::strand_service>(io_context))
+ {
+ service_.construct(impl_);
+ }
+
+ /// Destructor.
+ /**
+ * Destroys a strand.
+ *
+ * Handlers posted through the strand that have not yet been invoked will
+ * still be dispatched in a way that meets the guarantee of non-concurrency.
+ */
+ ~strand()
+ {
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use context().) Get the io_context associated with the
+ /// strand.
+ /**
+ * This function may be used to obtain the io_context object that the strand
+ * uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the strand will use to
+ * dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return service_.get_io_context();
+ }
+
+ /// (Deprecated: Use context().) Get the io_context associated with the
+ /// strand.
+ /**
+ * This function may be used to obtain the io_context object that the strand
+ * uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the strand will use to
+ * dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return service_.get_io_context();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Obtain the underlying execution context.
+ boost::asio::io_context& context() const BOOST_ASIO_NOEXCEPT
+ {
+ return service_.get_io_context();
+ }
+
+ /// Inform the strand that it has some outstanding work to do.
+ /**
+ * The strand delegates this call to its underlying io_context.
+ */
+ void on_work_started() const BOOST_ASIO_NOEXCEPT
+ {
+ context().get_executor().on_work_started();
+ }
+
+ /// Inform the strand that some work is no longer outstanding.
+ /**
+ * The strand delegates this call to its underlying io_context.
+ */
+ void on_work_finished() const BOOST_ASIO_NOEXCEPT
+ {
+ context().get_executor().on_work_finished();
+ }
+
+ /// Request the strand to invoke the given function object.
+ /**
+ * This function is used to ask the strand to execute the given function
+ * object on its underlying io_context. The function object will be executed
+ * inside this function if the strand is not otherwise busy and if the
+ * underlying io_context's executor's @c dispatch() function is also able to
+ * execute the function before returning.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+ {
+ typename decay<Function>::type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
+ service_.dispatch(impl_, tmp);
+ (void)a;
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use boost::asio::dispatch().) Request the strand to invoke
+ /// the given handler.
+ /**
+ * This function is used to ask the strand to execute the given handler.
+ *
+ * The strand object guarantees that handlers posted or dispatched through
+ * the strand will not be executed concurrently. The handler may be executed
+ * inside this function if the guarantee can be met. If this function is
+ * called from within a handler that was posted or dispatched through the same
+ * strand, then the new handler will be executed immediately.
+ *
+ * The strand's guarantee is in addition to the guarantee provided by the
+ * underlying io_context. The io_context guarantees that the handler will only
+ * be called in a thread in which the io_context's run member function is
+ * currently being invoked.
+ *
+ * @param handler The handler to be called. The strand will make a copy of the
+ * handler object as required. The function signature of the handler must be:
+ * @code void handler(); @endcode
+ */
+ template <typename CompletionHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
+ dispatch(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a CompletionHandler.
+ BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
+
+ async_completion<CompletionHandler, void ()> init(handler);
+
+ service_.dispatch(impl_, init.completion_handler);
+
+ return init.result.get();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Request the strand to invoke the given function object.
+ /**
+ * This function is used to ask the executor to execute the given function
+ * object. The function object will never be executed inside this function.
+ * Instead, it will be scheduled to run by the underlying io_context.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void post(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+ {
+ typename decay<Function>::type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
+ service_.post(impl_, tmp);
+ (void)a;
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use boost::asio::post().) Request the strand to invoke the
+ /// given handler and return immediately.
+ /**
+ * This function is used to ask the strand to execute the given handler, but
+ * without allowing the strand to call the handler from inside this function.
+ *
+ * The strand object guarantees that handlers posted or dispatched through
+ * the strand will not be executed concurrently. The strand's guarantee is in
+ * addition to the guarantee provided by the underlying io_context. The
+ * io_context guarantees that the handler will only be called in a thread in
+ * which the io_context's run member function is currently being invoked.
+ *
+ * @param handler The handler to be called. The strand will make a copy of the
+ * handler object as required. The function signature of the handler must be:
+ * @code void handler(); @endcode
+ */
+ template <typename CompletionHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
+ post(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a CompletionHandler.
+ BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
+
+ async_completion<CompletionHandler, void ()> init(handler);
+
+ service_.post(impl_, init.completion_handler);
+
+ return init.result.get();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Request the strand to invoke the given function object.
+ /**
+ * This function is used to ask the executor to execute the given function
+ * object. The function object will never be executed inside this function.
+ * Instead, it will be scheduled to run by the underlying io_context.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void defer(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+ {
+ typename decay<Function>::type tmp(BOOST_ASIO_MOVE_CAST(Function)(f));
+ service_.post(impl_, tmp);
+ (void)a;
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use boost::asio::bind_executor().) Create a new handler that
+ /// automatically dispatches the wrapped handler on the strand.
+ /**
+ * This function is used to create a new handler function object that, when
+ * invoked, will automatically pass the wrapped handler to the strand's
+ * dispatch function.
+ *
+ * @param handler The handler to be wrapped. The strand will make a copy of
+ * the handler object as required. The function signature of the handler must
+ * be: @code void handler(A1 a1, ... An an); @endcode
+ *
+ * @return A function object that, when invoked, passes the wrapped handler to
+ * the strand's dispatch function. Given a function object with the signature:
+ * @code R f(A1 a1, ... An an); @endcode
+ * If this function object is passed to the wrap function like so:
+ * @code strand.wrap(f); @endcode
+ * then the return value is a function object with the signature
+ * @code void g(A1 a1, ... An an); @endcode
+ * that, when invoked, executes code equivalent to:
+ * @code strand.dispatch(boost::bind(f, a1, ... an)); @endcode
+ */
+ template <typename Handler>
+#if defined(GENERATING_DOCUMENTATION)
+ unspecified
+#else
+ detail::wrapped_handler<strand, Handler, detail::is_continuation_if_running>
+#endif
+ wrap(Handler handler)
+ {
+ return detail::wrapped_handler<io_context::strand, Handler,
+ detail::is_continuation_if_running>(*this, handler);
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Determine whether the strand is running in the current thread.
+ /**
+ * @return @c true if the current thread is executing a handler that was
+ * submitted to the strand using post(), dispatch() or wrap(). Otherwise
+ * returns @c false.
+ */
+ bool running_in_this_thread() const BOOST_ASIO_NOEXCEPT
+ {
+ return service_.running_in_this_thread(impl_);
+ }
+
+ /// Compare two strands for equality.
+ /**
+ * Two strands are equal if they refer to the same ordered, non-concurrent
+ * state.
+ */
+ friend bool operator==(const strand& a, const strand& b) BOOST_ASIO_NOEXCEPT
+ {
+ return a.impl_ == b.impl_;
+ }
+
+ /// Compare two strands for inequality.
+ /**
+ * Two strands are equal if they refer to the same ordered, non-concurrent
+ * state.
+ */
+ friend bool operator!=(const strand& a, const strand& b) BOOST_ASIO_NOEXCEPT
+ {
+ return a.impl_ != b.impl_;
+ }
+
+private:
+ boost::asio::detail::strand_service& service_;
+ mutable boost::asio::detail::strand_service::implementation_type impl_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
+#endif // BOOST_ASIO_IO_CONTEXT_STRAND_HPP
diff --git a/boost/asio/io_service.hpp b/boost/asio/io_service.hpp
index f2b4667311..b04424dd69 100644
--- a/boost/asio/io_service.hpp
+++ b/boost/asio/io_service.hpp
@@ -15,758 +15,21 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include <boost/asio/detail/config.hpp>
-#include <cstddef>
-#include <stdexcept>
-#include <typeinfo>
-#include <boost/asio/async_result.hpp>
-#include <boost/asio/detail/noncopyable.hpp>
-#include <boost/asio/detail/wrapped_handler.hpp>
-#include <boost/system/error_code.hpp>
-
-#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
-# include <boost/asio/detail/winsock_init.hpp>
-#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \
- || defined(__osf__)
-# include <boost/asio/detail/signal_init.hpp>
-#endif
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
-class io_service;
-template <typename Service> Service& use_service(io_service& ios);
-template <typename Service> void add_service(io_service& ios, Service* svc);
-template <typename Service> bool has_service(io_service& ios);
-
-namespace detail {
-#if defined(BOOST_ASIO_HAS_IOCP)
- typedef class win_iocp_io_service io_service_impl;
- class win_iocp_overlapped_ptr;
-#else
- typedef class task_io_service io_service_impl;
-#endif
- class service_registry;
-} // namespace detail
-
-/// Provides core I/O functionality.
-/**
- * The io_service class provides the core I/O functionality for users of the
- * asynchronous I/O objects, including:
- *
- * @li boost::asio::ip::tcp::socket
- * @li boost::asio::ip::tcp::acceptor
- * @li boost::asio::ip::udp::socket
- * @li boost::asio::deadline_timer.
- *
- * The io_service class also includes facilities intended for developers of
- * custom asynchronous services.
- *
- * @par Thread Safety
- * @e Distinct @e objects: Safe.@n
- * @e Shared @e objects: Safe, with the specific exceptions of the reset() and
- * notify_fork() functions. Calling reset() while there are unfinished run(),
- * run_one(), poll() or poll_one() calls results in undefined behaviour. The
- * notify_fork() function should not be called while any io_service function,
- * or any function on an I/O object that is associated with the io_service, is
- * being called in another thread.
- *
- * @par Concepts:
- * Dispatcher.
- *
- * @par Synchronous and asynchronous operations
- *
- * Synchronous operations on I/O objects implicitly run the io_service object
- * for an individual operation. The io_service functions run(), run_one(),
- * poll() or poll_one() must be called for the io_service to perform
- * asynchronous operations on behalf of a C++ program. Notification that an
- * asynchronous operation has completed is delivered by invocation of the
- * associated handler. Handlers are invoked only by a thread that is currently
- * calling any overload of run(), run_one(), poll() or poll_one() for the
- * io_service.
- *
- * @par Effect of exceptions thrown from handlers
- *
- * If an exception is thrown from a handler, the exception is allowed to
- * propagate through the throwing thread's invocation of run(), run_one(),
- * poll() or poll_one(). No other threads that are calling any of these
- * functions are affected. It is then the responsibility of the application to
- * catch the exception.
- *
- * After the exception has been caught, the run(), run_one(), poll() or
- * poll_one() call may be restarted @em without the need for an intervening
- * call to reset(). This allows the thread to rejoin the io_service object's
- * thread pool without impacting any other threads in the pool.
- *
- * For example:
- *
- * @code
- * boost::asio::io_service io_service;
- * ...
- * for (;;)
- * {
- * try
- * {
- * io_service.run();
- * break; // run() exited normally
- * }
- * catch (my_exception& e)
- * {
- * // Deal with exception as appropriate.
- * }
- * }
- * @endcode
- *
- * @par Stopping the io_service from running out of work
- *
- * Some applications may need to prevent an io_service object's run() call from
- * returning when there is no more work to do. For example, the io_service 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 object of type boost::asio::io_service::work:
- *
- * @code boost::asio::io_service io_service;
- * boost::asio::io_service::work work(io_service);
- * ... @endcode
- *
- * To effect a shutdown, the application will then need to call the io_service
- * object's stop() member function. This will cause the io_service run() call
- * to return as soon as possible, abandoning unfinished operations and without
- * permitting ready handlers to be dispatched.
- *
- * Alternatively, if the application requires that all operations and handlers
- * be allowed to finish normally, the work object may be explicitly destroyed.
- *
- * @code boost::asio::io_service io_service;
- * auto_ptr<boost::asio::io_service::work> work(
- * new boost::asio::io_service::work(io_service));
- * ...
- * work.reset(); // Allow run() to exit. @endcode
- *
- * @par The io_service class and I/O services
- *
- * Class io_service implements an extensible, type-safe, polymorphic set of I/O
- * services, indexed by service type. An object of class io_service must be
- * initialised before I/O objects such as sockets, resolvers and timers can be
- * used. These I/O objects are distinguished by having constructors that accept
- * an @c io_service& parameter.
- *
- * I/O services exist to manage the logical interface to the operating system on
- * behalf of the I/O objects. In particular, there are resources that are shared
- * across a class of I/O objects. For example, timers may be implemented in
- * terms of a single timer queue. The I/O services manage these shared
- * resources.
- *
- * Access to the services of an io_service is via three function templates,
- * use_service(), add_service() and has_service().
- *
- * In a call to @c use_service<Service>(), the type argument chooses a service,
- * making available all members of the named type. If @c Service is not present
- * in an io_service, an object of type @c Service is created and added to the
- * io_service. A C++ program can check if an io_service implements a
- * particular service with the function template @c has_service<Service>().
- *
- * Service objects may be explicitly added to an io_service using the function
- * template @c add_service<Service>(). If the @c Service is already present, the
- * service_already_exists exception is thrown. If the owner of the service is
- * not the same object as the io_service parameter, the invalid_service_owner
- * exception is thrown.
- *
- * Once a service reference is obtained from an io_service object by calling
- * use_service(), that reference remains usable as long as the owning io_service
- * object exists.
- *
- * All I/O service implementations have io_service::service as a public base
- * class. Custom I/O services may be implemented by deriving from this class and
- * then added to an io_service using the facilities described above.
- */
-class io_service
- : private noncopyable
-{
-private:
- typedef detail::io_service_impl impl_type;
-#if defined(BOOST_ASIO_HAS_IOCP)
- friend class detail::win_iocp_overlapped_ptr;
-#endif
-
-public:
- class work;
- friend class work;
-
- class id;
-
- class service;
-
- class strand;
-
- /// Constructor.
- BOOST_ASIO_DECL io_service();
-
- /// Constructor.
- /**
- * Construct with a hint about the required level of concurrency.
- *
- * @param concurrency_hint A suggestion to the implementation on how many
- * threads it should allow to run simultaneously.
- */
- BOOST_ASIO_DECL explicit io_service(std::size_t concurrency_hint);
-
- /// Destructor.
- /**
- * On destruction, the io_service performs the following sequence of
- * operations:
- *
- * @li For each service object @c svc in the io_service set, in reverse order
- * of the beginning of service object lifetime, performs
- * @c svc->shutdown_service().
- *
- * @li Uninvoked handler objects that were scheduled for deferred invocation
- * on the io_service, or any associated strand, are destroyed.
- *
- * @li For each service object @c svc in the io_service set, in reverse order
- * of the beginning of service object lifetime, performs
- * <tt>delete static_cast<io_service::service*>(svc)</tt>.
- *
- * @note The destruction sequence described above permits programs to
- * simplify their resource management by using @c shared_ptr<>. Where an
- * object's lifetime is tied to the lifetime of a connection (or some other
- * sequence of asynchronous operations), a @c shared_ptr to the object would
- * be bound into the handlers for all asynchronous operations associated with
- * it. This works as follows:
- *
- * @li When a single connection ends, all associated asynchronous operations
- * complete. The corresponding handler objects are destroyed, and all
- * @c shared_ptr references to the objects are destroyed.
- *
- * @li To shut down the whole program, the io_service function stop() is
- * called to terminate any run() calls as soon as possible. The io_service
- * destructor defined above destroys all handlers, causing all @c shared_ptr
- * references to all connection objects to be destroyed.
- */
- BOOST_ASIO_DECL ~io_service();
-
- /// Run the io_service object's event processing loop.
- /**
- * The run() function blocks until all work has finished and there are no
- * more handlers to be dispatched, or until the io_service has been stopped.
- *
- * Multiple threads may call the run() function to set up a pool of threads
- * from which the io_service may execute handlers. All threads that are
- * waiting in the pool are equivalent and the io_service may choose any one
- * of them to invoke a handler.
- *
- * A normal exit from the run() function implies that the io_service object
- * is stopped (the stopped() function returns @c true). Subsequent calls to
- * run(), run_one(), poll() or poll_one() will return immediately unless there
- * is a prior call to reset().
- *
- * @return The number of handlers that were executed.
- *
- * @throws boost::system::system_error Thrown on failure.
- *
- * @note The run() function must not be called from a thread that is currently
- * calling one of run(), run_one(), poll() or poll_one() on the same
- * io_service object.
- *
- * The poll() function may also be used to dispatch ready handlers, but
- * without blocking.
- */
- BOOST_ASIO_DECL std::size_t run();
-
- /// Run the io_service object's event processing loop.
- /**
- * The run() function blocks until all work has finished and there are no
- * more handlers to be dispatched, or until the io_service has been stopped.
- *
- * Multiple threads may call the run() function to set up a pool of threads
- * from which the io_service may execute handlers. All threads that are
- * waiting in the pool are equivalent and the io_service may choose any one
- * of them to invoke a handler.
- *
- * A normal exit from the run() function implies that the io_service object
- * is stopped (the stopped() function returns @c true). Subsequent calls to
- * run(), run_one(), poll() or poll_one() will return immediately unless there
- * is a prior call to reset().
- *
- * @param ec Set to indicate what error occurred, if any.
- *
- * @return The number of handlers that were executed.
- *
- * @note The run() function must not be called from a thread that is currently
- * calling one of run(), run_one(), poll() or poll_one() on the same
- * io_service object.
- *
- * The poll() function may also be used to dispatch ready handlers, but
- * without blocking.
- */
- BOOST_ASIO_DECL std::size_t run(boost::system::error_code& ec);
-
- /// Run the io_service object's event processing loop to execute at most one
- /// handler.
- /**
- * The run_one() function blocks until one handler has been dispatched, or
- * until the io_service has been stopped.
- *
- * @return The number of handlers that were executed. A zero return value
- * implies that the io_service object is stopped (the stopped() function
- * returns @c true). Subsequent calls to run(), run_one(), poll() or
- * poll_one() will return immediately unless there is a prior call to
- * reset().
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- BOOST_ASIO_DECL std::size_t run_one();
-
- /// Run the io_service object's event processing loop to execute at most one
- /// handler.
- /**
- * The run_one() function blocks until one handler has been dispatched, or
- * until the io_service has been stopped.
- *
- * @return The number of handlers that were executed. A zero return value
- * implies that the io_service object is stopped (the stopped() function
- * returns @c true). Subsequent calls to run(), run_one(), poll() or
- * poll_one() will return immediately unless there is a prior call to
- * reset().
- *
- * @return The number of handlers that were executed.
- */
- BOOST_ASIO_DECL std::size_t run_one(boost::system::error_code& ec);
-
- /// Run the io_service object's event processing loop to execute ready
- /// handlers.
- /**
- * The poll() function runs handlers that are ready to run, without blocking,
- * until the io_service has been stopped or there are no more ready handlers.
- *
- * @return The number of handlers that were executed.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- BOOST_ASIO_DECL std::size_t poll();
-
- /// Run the io_service object's event processing loop to execute ready
- /// handlers.
- /**
- * The poll() function runs handlers that are ready to run, without blocking,
- * until the io_service has been stopped or there are no more ready handlers.
- *
- * @param ec Set to indicate what error occurred, if any.
- *
- * @return The number of handlers that were executed.
- */
- BOOST_ASIO_DECL std::size_t poll(boost::system::error_code& ec);
-
- /// Run the io_service object's event processing loop to execute one ready
- /// handler.
- /**
- * The poll_one() function runs at most one handler that is ready to run,
- * without blocking.
- *
- * @return The number of handlers that were executed.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- BOOST_ASIO_DECL std::size_t poll_one();
-
- /// Run the io_service object's event processing loop to execute one ready
- /// handler.
- /**
- * The poll_one() function runs at most one handler that is ready to run,
- * without blocking.
- *
- * @param ec Set to indicate what error occurred, if any.
- *
- * @return The number of handlers that were executed.
- */
- BOOST_ASIO_DECL std::size_t poll_one(boost::system::error_code& ec);
-
- /// Stop the io_service object's event processing loop.
- /**
- * This function does not block, but instead simply signals the io_service to
- * stop. All invocations of its run() or run_one() member functions should
- * return as soon as possible. Subsequent calls to run(), run_one(), poll()
- * or poll_one() will return immediately until reset() is called.
- */
- BOOST_ASIO_DECL void stop();
-
- /// Determine whether the io_service object has been stopped.
- /**
- * This function is used to determine whether an io_service object has been
- * stopped, either through an explicit call to stop(), or due to running out
- * of work. When an io_service object is stopped, calls to run(), run_one(),
- * poll() or poll_one() will return immediately without invoking any
- * handlers.
- *
- * @return @c true if the io_service object is stopped, otherwise @c false.
- */
- BOOST_ASIO_DECL bool stopped() const;
-
- /// Reset the io_service in preparation for a subsequent run() invocation.
- /**
- * This function must be called prior to any second or later set of
- * invocations of the run(), run_one(), poll() or poll_one() functions when a
- * previous invocation of these functions returned due to the io_service
- * being stopped or running out of work. After a call to reset(), the
- * io_service object's stopped() function will return @c false.
- *
- * This function must not be called while there are any unfinished calls to
- * the run(), run_one(), poll() or poll_one() functions.
- */
- BOOST_ASIO_DECL void reset();
-
- /// Request the io_service to invoke the given handler.
- /**
- * This function is used to ask the io_service to execute the given handler.
- *
- * The io_service guarantees that the handler will only be called in a thread
- * in which the run(), run_one(), poll() or poll_one() member functions is
- * currently being invoked. The handler may be executed inside this function
- * if the guarantee can be met.
- *
- * @param handler The handler to be called. The io_service will make
- * a copy of the handler object as required. The function signature of the
- * handler must be: @code void handler(); @endcode
- *
- * @note This function throws an exception only if:
- *
- * @li the handler's @c asio_handler_allocate function; or
- *
- * @li the handler's copy constructor
- *
- * throws an exception.
- */
- template <typename CompletionHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
- dispatch(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler);
-
- /// Request the io_service to invoke the given handler and return immediately.
- /**
- * This function is used to ask the io_service to execute the given handler,
- * but without allowing the io_service to call the handler from inside this
- * function.
- *
- * The io_service guarantees that the handler will only be called in a thread
- * in which the run(), run_one(), poll() or poll_one() member functions is
- * currently being invoked.
- *
- * @param handler The handler to be called. The io_service will make
- * a copy of the handler object as required. The function signature of the
- * handler must be: @code void handler(); @endcode
- *
- * @note This function throws an exception only if:
- *
- * @li the handler's @c asio_handler_allocate function; or
- *
- * @li the handler's copy constructor
- *
- * throws an exception.
- */
- template <typename CompletionHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
- post(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler);
-
- /// Create a new handler that automatically dispatches the wrapped handler
- /// on the io_service.
- /**
- * This function is used to create a new handler function object that, when
- * invoked, will automatically pass the wrapped handler to the io_service
- * object's dispatch function.
- *
- * @param handler The handler to be wrapped. The io_service will make a copy
- * of the handler object as required. The function signature of the handler
- * must be: @code void handler(A1 a1, ... An an); @endcode
- *
- * @return A function object that, when invoked, passes the wrapped handler to
- * the io_service object's dispatch function. Given a function object with the
- * signature:
- * @code R f(A1 a1, ... An an); @endcode
- * If this function object is passed to the wrap function like so:
- * @code io_service.wrap(f); @endcode
- * then the return value is a function object with the signature
- * @code void g(A1 a1, ... An an); @endcode
- * that, when invoked, executes code equivalent to:
- * @code io_service.dispatch(boost::bind(f, a1, ... an)); @endcode
- */
- template <typename Handler>
-#if defined(GENERATING_DOCUMENTATION)
- unspecified
-#else
- detail::wrapped_handler<io_service&, Handler>
-#endif
- wrap(Handler handler);
-
- /// Fork-related event notifications.
- enum fork_event
- {
- /// Notify the io_service that the process is about to fork.
- fork_prepare,
-
- /// Notify the io_service that the process has forked and is the parent.
- fork_parent,
-
- /// Notify the io_service that the process has forked and is the child.
- fork_child
- };
-
- /// Notify the io_service of a fork-related event.
- /**
- * This function is used to inform the io_service that the process is about
- * to fork, or has just forked. This allows the io_service, and the services
- * it contains, to perform any necessary housekeeping to ensure correct
- * operation following a fork.
- *
- * This function must not be called while any other io_service function, or
- * any function on an I/O object associated with the io_service, is being
- * called in another thread. It is, however, safe to call this function from
- * within a completion handler, provided no other thread is accessing the
- * io_service.
- *
- * @param event A fork-related event.
- *
- * @throws boost::system::system_error Thrown on failure. If the notification
- * fails the io_service object should no longer be used and should be
- * destroyed.
- *
- * @par Example
- * The following code illustrates how to incorporate the notify_fork()
- * function:
- * @code my_io_service.notify_fork(boost::asio::io_service::fork_prepare);
- * if (fork() == 0)
- * {
- * // This is the child process.
- * my_io_service.notify_fork(boost::asio::io_service::fork_child);
- * }
- * else
- * {
- * // This is the parent process.
- * my_io_service.notify_fork(boost::asio::io_service::fork_parent);
- * } @endcode
- *
- * @note For each service object @c svc in the io_service set, performs
- * <tt>svc->fork_service();</tt>. When processing the fork_prepare event,
- * services are visited in reverse order of the beginning of service object
- * lifetime. Otherwise, services are visited in order of the beginning of
- * service object lifetime.
- */
- BOOST_ASIO_DECL void notify_fork(boost::asio::io_service::fork_event event);
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+/// Typedef for backwards compatibility.
+typedef io_context io_service;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
- /// Obtain the service object corresponding to the given type.
- /**
- * This function is used to locate a service object that corresponds to
- * the given service type. If there is no existing implementation of the
- * service, then the io_service will create a new instance of the service.
- *
- * @param ios The io_service object that owns the service.
- *
- * @return The service interface implementing the specified service type.
- * Ownership of the service interface is not transferred to the caller.
- */
- template <typename Service>
- friend Service& use_service(io_service& ios);
-
- /// Add a service object to the io_service.
- /**
- * This function is used to add a service to the io_service.
- *
- * @param ios The io_service object that owns the service.
- *
- * @param svc The service object. On success, ownership of the service object
- * is transferred to the io_service. When the io_service object is destroyed,
- * it will destroy the service object by performing:
- * @code delete static_cast<io_service::service*>(svc) @endcode
- *
- * @throws boost::asio::service_already_exists Thrown if a service of the
- * given type is already present in the io_service.
- *
- * @throws boost::asio::invalid_service_owner Thrown if the service's owning
- * io_service is not the io_service object specified by the ios parameter.
- */
- template <typename Service>
- friend void add_service(io_service& ios, Service* svc);
-
- /// Determine if an io_service contains a specified service type.
- /**
- * This function is used to determine whether the io_service contains a
- * service object corresponding to the given service type.
- *
- * @param ios The io_service object that owns the service.
- *
- * @return A boolean indicating whether the io_service contains the service.
- */
- template <typename Service>
- friend bool has_service(io_service& ios);
-
-private:
-#if defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
- detail::winsock_init<> init_;
-#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \
- || defined(__osf__)
- detail::signal_init<> init_;
-#endif
-
- // The service registry.
- boost::asio::detail::service_registry* service_registry_;
-
- // The implementation.
- impl_type& impl_;
-};
-
-/// Class to inform the io_service when it has work to do.
-/**
- * The work class is used to inform the io_service when work starts and
- * finishes. This ensures that the io_service object's run() function will not
- * exit while work is underway, and that it does exit when there is no
- * unfinished work remaining.
- *
- * The work class is copy-constructible so that it may be used as a data member
- * in a handler class. It is not assignable.
- */
-class io_service::work
-{
-public:
- /// Constructor notifies the io_service that work is starting.
- /**
- * The constructor is used to inform the io_service that some work has begun.
- * This ensures that the io_service object's run() function will not exit
- * while the work is underway.
- */
- explicit work(boost::asio::io_service& io_service);
-
- /// Copy constructor notifies the io_service that work is starting.
- /**
- * The constructor is used to inform the io_service that some work has begun.
- * This ensures that the io_service object's run() function will not exit
- * while the work is underway.
- */
- work(const work& other);
-
- /// Destructor notifies the io_service that the work is complete.
- /**
- * The destructor is used to inform the io_service that some work has
- * finished. Once the count of unfinished work reaches zero, the io_service
- * object's run() function is permitted to exit.
- */
- ~work();
-
- /// Get the io_service associated with the work.
- boost::asio::io_service& get_io_service();
-
-private:
- // Prevent assignment.
- void operator=(const work& other);
-
- // The io_service implementation.
- detail::io_service_impl& io_service_impl_;
-};
-
-/// Class used to uniquely identify a service.
-class io_service::id
- : private noncopyable
-{
-public:
- /// Constructor.
- id() {}
-};
-
-/// Base class for all io_service services.
-class io_service::service
- : private noncopyable
-{
-public:
- /// Get the io_service object that owns the service.
- boost::asio::io_service& get_io_service();
-
-protected:
- /// Constructor.
- /**
- * @param owner The io_service object that owns the service.
- */
- BOOST_ASIO_DECL service(boost::asio::io_service& owner);
-
- /// Destructor.
- BOOST_ASIO_DECL virtual ~service();
-
-private:
- /// Destroy all user-defined handler objects owned by the service.
- virtual void shutdown_service() = 0;
-
- /// Handle notification of a fork-related event to perform any necessary
- /// housekeeping.
- /**
- * This function is not a pure virtual so that services only have to
- * implement it if necessary. The default implementation does nothing.
- */
- BOOST_ASIO_DECL virtual void fork_service(
- boost::asio::io_service::fork_event event);
-
- friend class boost::asio::detail::service_registry;
- struct key
- {
- key() : type_info_(0), id_(0) {}
- const std::type_info* type_info_;
- const boost::asio::io_service::id* id_;
- } key_;
-
- boost::asio::io_service& owner_;
- service* next_;
-};
-
-/// Exception thrown when trying to add a duplicate service to an io_service.
-class service_already_exists
- : public std::logic_error
-{
-public:
- BOOST_ASIO_DECL service_already_exists();
-};
-
-/// Exception thrown when trying to add a service object to an io_service where
-/// the service has a different owner.
-class invalid_service_owner
- : public std::logic_error
-{
-public:
- BOOST_ASIO_DECL invalid_service_owner();
-};
-
-namespace detail {
-
-// Special derived service id type to keep classes header-file only.
-template <typename Type>
-class service_id
- : public boost::asio::io_service::id
-{
-};
-
-// Special service base class to keep classes header-file only.
-template <typename Type>
-class service_base
- : public boost::asio::io_service::service
-{
-public:
- static boost::asio::detail::service_id<Type> id;
-
- // Constructor.
- service_base(boost::asio::io_service& io_service)
- : boost::asio::io_service::service(io_service)
- {
- }
-};
-
-template <typename Type>
-boost::asio::detail::service_id<Type> service_base<Type>::id;
-
-} // namespace detail
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
-#include <boost/asio/impl/io_service.hpp>
-#if defined(BOOST_ASIO_HEADER_ONLY)
-# include <boost/asio/impl/io_service.ipp>
-#endif // defined(BOOST_ASIO_HEADER_ONLY)
-
#endif // BOOST_ASIO_IO_SERVICE_HPP
diff --git a/boost/asio/io_service_strand.hpp b/boost/asio/io_service_strand.hpp
new file mode 100644
index 0000000000..af7224a5a1
--- /dev/null
+++ b/boost/asio/io_service_strand.hpp
@@ -0,0 +1,20 @@
+//
+// io_service_strand.hpp
+// ~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IO_SERVICE_STRAND_HPP
+#define BOOST_ASIO_IO_SERVICE_STRAND_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/io_context_strand.hpp>
+
+#endif // BOOST_ASIO_IO_SERVICE_STRAND_HPP
diff --git a/boost/asio/ip/address.hpp b/boost/asio/ip/address.hpp
index 6e1b19e650..6d654b61b7 100644
--- a/boost/asio/ip/address.hpp
+++ b/boost/asio/ip/address.hpp
@@ -17,9 +17,13 @@
#include <boost/asio/detail/config.hpp>
#include <string>
+#include <boost/asio/detail/throw_exception.hpp>
+#include <boost/asio/detail/string_view.hpp>
+#include <boost/asio/detail/type_traits.hpp>
#include <boost/system/error_code.hpp>
#include <boost/asio/ip/address_v4.hpp>
#include <boost/asio/ip/address_v6.hpp>
+#include <boost/asio/ip/bad_address_cast.hpp>
#if !defined(BOOST_ASIO_NO_IOSTREAM)
# include <iosfwd>
@@ -94,29 +98,34 @@ public:
/// Get the address as an IP version 6 address.
BOOST_ASIO_DECL boost::asio::ip::address_v6 to_v6() const;
- /// Get the address as a string in dotted decimal format.
+ /// Get the address as a string.
BOOST_ASIO_DECL std::string to_string() const;
- /// Get the address as a string in dotted decimal format.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use other overload.) Get the address as a string.
BOOST_ASIO_DECL std::string to_string(boost::system::error_code& ec) const;
- /// Create an address from an IPv4 address string in dotted decimal form,
- /// or from an IPv6 address in hexadecimal notation.
- BOOST_ASIO_DECL static address from_string(const char* str);
-
- /// Create an address from an IPv4 address string in dotted decimal form,
- /// or from an IPv6 address in hexadecimal notation.
- BOOST_ASIO_DECL static address from_string(
- const char* str, boost::system::error_code& ec);
-
- /// Create an address from an IPv4 address string in dotted decimal form,
- /// or from an IPv6 address in hexadecimal notation.
- BOOST_ASIO_DECL static address from_string(const std::string& str);
-
- /// Create an address from an IPv4 address string in dotted decimal form,
- /// or from an IPv6 address in hexadecimal notation.
- BOOST_ASIO_DECL static address from_string(
+ /// (Deprecated: Use make_address().) Create an address from an IPv4 address
+ /// string in dotted decimal form, or from an IPv6 address in hexadecimal
+ /// notation.
+ static address from_string(const char* str);
+
+ /// (Deprecated: Use make_address().) Create an address from an IPv4 address
+ /// string in dotted decimal form, or from an IPv6 address in hexadecimal
+ /// notation.
+ static address from_string(const char* str, boost::system::error_code& ec);
+
+ /// (Deprecated: Use make_address().) Create an address from an IPv4 address
+ /// string in dotted decimal form, or from an IPv6 address in hexadecimal
+ /// notation.
+ static address from_string(const std::string& str);
+
+ /// (Deprecated: Use make_address().) Create an address from an IPv4 address
+ /// string in dotted decimal form, or from an IPv6 address in hexadecimal
+ /// notation.
+ static address from_string(
const std::string& str, boost::system::error_code& ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Determine whether the address is a loopback address.
BOOST_ASIO_DECL bool is_loopback() const;
@@ -168,6 +177,57 @@ private:
boost::asio::ip::address_v6 ipv6_address_;
};
+/// Create an address from an IPv4 address string in dotted decimal form,
+/// or from an IPv6 address in hexadecimal notation.
+/**
+ * @relates address
+ */
+BOOST_ASIO_DECL address make_address(const char* str);
+
+/// Create an address from an IPv4 address string in dotted decimal form,
+/// or from an IPv6 address in hexadecimal notation.
+/**
+ * @relates address
+ */
+BOOST_ASIO_DECL address make_address(
+ const char* str, boost::system::error_code& ec);
+
+/// Create an address from an IPv4 address string in dotted decimal form,
+/// or from an IPv6 address in hexadecimal notation.
+/**
+ * @relates address
+ */
+BOOST_ASIO_DECL address make_address(const std::string& str);
+
+/// Create an address from an IPv4 address string in dotted decimal form,
+/// or from an IPv6 address in hexadecimal notation.
+/**
+ * @relates address
+ */
+BOOST_ASIO_DECL address make_address(
+ const std::string& str, boost::system::error_code& ec);
+
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW) \
+ || defined(GENERATING_DOCUMENTATION)
+
+/// Create an address from an IPv4 address string in dotted decimal form,
+/// or from an IPv6 address in hexadecimal notation.
+/**
+ * @relates address
+ */
+BOOST_ASIO_DECL address make_address(string_view str);
+
+/// Create an address from an IPv4 address string in dotted decimal form,
+/// or from an IPv6 address in hexadecimal notation.
+/**
+ * @relates address
+ */
+BOOST_ASIO_DECL address make_address(
+ string_view str, boost::system::error_code& ec);
+
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ // || defined(GENERATING_DOCUMENTATION)
+
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// Output an address as a string.
diff --git a/boost/asio/ip/address_v4.hpp b/boost/asio/ip/address_v4.hpp
index 3db4d4c825..399c051910 100644
--- a/boost/asio/ip/address_v4.hpp
+++ b/boost/asio/ip/address_v4.hpp
@@ -18,7 +18,9 @@
#include <boost/asio/detail/config.hpp>
#include <string>
#include <boost/asio/detail/array.hpp>
+#include <boost/asio/detail/cstdint.hpp>
#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/string_view.hpp>
#include <boost/asio/detail/winsock_init.hpp>
#include <boost/system/error_code.hpp>
@@ -44,6 +46,9 @@ namespace ip {
class address_v4
{
public:
+ /// The type used to represent an address as an unsigned integer.
+ typedef uint_least32_t uint_type;
+
/// The type used to represent an address as an array of bytes.
/**
* @note This type is defined in terms of the C++0x template @c std::array
@@ -64,8 +69,8 @@ public:
/// Construct an address from raw bytes.
BOOST_ASIO_DECL explicit address_v4(const bytes_type& bytes);
- /// Construct an address from a unsigned long in host byte order.
- BOOST_ASIO_DECL explicit address_v4(unsigned long addr);
+ /// Construct an address from an unsigned integer in host byte order.
+ BOOST_ASIO_DECL explicit address_v4(uint_type addr);
/// Copy constructor.
address_v4(const address_v4& other)
@@ -100,28 +105,40 @@ public:
/// Get the address in bytes, in network byte order.
BOOST_ASIO_DECL bytes_type to_bytes() const;
+ /// Get the address as an unsigned integer in host byte order
+ BOOST_ASIO_DECL uint_type to_uint() const;
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
/// Get the address as an unsigned long in host byte order
BOOST_ASIO_DECL unsigned long to_ulong() const;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Get the address as a string in dotted decimal format.
BOOST_ASIO_DECL std::string to_string() const;
- /// Get the address as a string in dotted decimal format.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use other overload.) Get the address as a string in dotted
+ /// decimal format.
BOOST_ASIO_DECL std::string to_string(boost::system::error_code& ec) const;
- /// Create an address from an IP address string in dotted decimal form.
- BOOST_ASIO_DECL static address_v4 from_string(const char* str);
+ /// (Deprecated: Use make_address_v4().) Create an address from an IP address
+ /// string in dotted decimal form.
+ static address_v4 from_string(const char* str);
- /// Create an address from an IP address string in dotted decimal form.
- BOOST_ASIO_DECL static address_v4 from_string(
+ /// (Deprecated: Use make_address_v4().) Create an address from an IP address
+ /// string in dotted decimal form.
+ static address_v4 from_string(
const char* str, boost::system::error_code& ec);
- /// Create an address from an IP address string in dotted decimal form.
- BOOST_ASIO_DECL static address_v4 from_string(const std::string& str);
+ /// (Deprecated: Use make_address_v4().) Create an address from an IP address
+ /// string in dotted decimal form.
+ static address_v4 from_string(const std::string& str);
- /// Create an address from an IP address string in dotted decimal form.
- BOOST_ASIO_DECL static address_v4 from_string(
+ /// (Deprecated: Use make_address_v4().) Create an address from an IP address
+ /// string in dotted decimal form.
+ static address_v4 from_string(
const std::string& str, boost::system::error_code& ec);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Determine whether the address is a loopback address.
BOOST_ASIO_DECL bool is_loopback() const;
@@ -129,14 +146,19 @@ public:
/// Determine whether the address is unspecified.
BOOST_ASIO_DECL bool is_unspecified() const;
- /// Determine whether the address is a class A address.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use network_v4 class.) Determine whether the address is a
+ /// class A address.
BOOST_ASIO_DECL bool is_class_a() const;
- /// Determine whether the address is a class B address.
+ /// (Deprecated: Use network_v4 class.) Determine whether the address is a
+ /// class B address.
BOOST_ASIO_DECL bool is_class_b() const;
- /// Determine whether the address is a class C address.
+ /// (Deprecated: Use network_v4 class.) Determine whether the address is a
+ /// class C address.
BOOST_ASIO_DECL bool is_class_c() const;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Determine whether the address is a multicast address.
BOOST_ASIO_DECL bool is_multicast() const;
@@ -156,25 +178,25 @@ public:
/// Compare addresses for ordering.
friend bool operator<(const address_v4& a1, const address_v4& a2)
{
- return a1.to_ulong() < a2.to_ulong();
+ return a1.to_uint() < a2.to_uint();
}
/// Compare addresses for ordering.
friend bool operator>(const address_v4& a1, const address_v4& a2)
{
- return a1.to_ulong() > a2.to_ulong();
+ return a1.to_uint() > a2.to_uint();
}
/// Compare addresses for ordering.
friend bool operator<=(const address_v4& a1, const address_v4& a2)
{
- return a1.to_ulong() <= a2.to_ulong();
+ return a1.to_uint() <= a2.to_uint();
}
/// Compare addresses for ordering.
friend bool operator>=(const address_v4& a1, const address_v4& a2)
{
- return a1.to_ulong() >= a2.to_ulong();
+ return a1.to_uint() >= a2.to_uint();
}
/// Obtain an address object that represents any address.
@@ -195,20 +217,86 @@ public:
return address_v4(0xFFFFFFFF);
}
- /// Obtain an address object that represents the broadcast address that
- /// corresponds to the specified address and netmask.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use network_v4 class.) Obtain an address object that
+ /// represents the broadcast address that corresponds to the specified
+ /// address and netmask.
BOOST_ASIO_DECL static address_v4 broadcast(
const address_v4& addr, const address_v4& mask);
- /// Obtain the netmask that corresponds to the address, based on its address
- /// class.
+ /// (Deprecated: Use network_v4 class.) Obtain the netmask that corresponds
+ /// to the address, based on its address class.
BOOST_ASIO_DECL static address_v4 netmask(const address_v4& addr);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
private:
// The underlying IPv4 address.
boost::asio::detail::in4_addr_type addr_;
};
+/// Create an IPv4 address from raw bytes in network order.
+/**
+ * @relates address_v4
+ */
+inline address_v4 make_address_v4(const address_v4::bytes_type& bytes)
+{
+ return address_v4(bytes);
+}
+
+/// Create an IPv4 address from an unsigned integer in host byte order.
+/**
+ * @relates address_v4
+ */
+inline address_v4 make_address_v4(address_v4::uint_type addr)
+{
+ return address_v4(addr);
+}
+
+/// Create an IPv4 address from an IP address string in dotted decimal form.
+/**
+ * @relates address_v4
+ */
+BOOST_ASIO_DECL address_v4 make_address_v4(const char* str);
+
+/// Create an IPv4 address from an IP address string in dotted decimal form.
+/**
+ * @relates address_v4
+ */
+BOOST_ASIO_DECL address_v4 make_address_v4(
+ const char* str, boost::system::error_code& ec);
+
+/// Create an IPv4 address from an IP address string in dotted decimal form.
+/**
+ * @relates address_v4
+ */
+BOOST_ASIO_DECL address_v4 make_address_v4(const std::string& str);
+
+/// Create an IPv4 address from an IP address string in dotted decimal form.
+/**
+ * @relates address_v4
+ */
+BOOST_ASIO_DECL address_v4 make_address_v4(
+ const std::string& str, boost::system::error_code& ec);
+
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW) \
+ || defined(GENERATING_DOCUMENTATION)
+
+/// Create an IPv4 address from an IP address string in dotted decimal form.
+/**
+ * @relates address_v4
+ */
+BOOST_ASIO_DECL address_v4 make_address_v4(string_view str);
+
+/// Create an IPv4 address from an IP address string in dotted decimal form.
+/**
+ * @relates address_v4
+ */
+BOOST_ASIO_DECL address_v4 make_address_v4(
+ string_view str, boost::system::error_code& ec);
+
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ // || defined(GENERATING_DOCUMENTATION)
+
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// Output an address as a string.
diff --git a/boost/asio/ip/address_v4_iterator.hpp b/boost/asio/ip/address_v4_iterator.hpp
new file mode 100644
index 0000000000..a2ccfc3748
--- /dev/null
+++ b/boost/asio/ip/address_v4_iterator.hpp
@@ -0,0 +1,164 @@
+//
+// ip/address_v4_iterator.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_ADDRESS_V4_ITERATOR_HPP
+#define BOOST_ASIO_IP_ADDRESS_V4_ITERATOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+template <typename> class basic_address_iterator;
+
+/// An input iterator that can be used for traversing IPv4 addresses.
+/**
+ * In addition to satisfying the input iterator requirements, this iterator
+ * also supports decrement.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <> class basic_address_iterator<address_v4>
+{
+public:
+ /// The type of the elements pointed to by the iterator.
+ typedef address_v4 value_type;
+
+ /// Distance between two iterators.
+ typedef std::ptrdiff_t difference_type;
+
+ /// The type of a pointer to an element pointed to by the iterator.
+ typedef const address_v4* pointer;
+
+ /// The type of a reference to an element pointed to by the iterator.
+ typedef const address_v4& reference;
+
+ /// Denotes that the iterator satisfies the input iterator requirements.
+ typedef std::input_iterator_tag iterator_category;
+
+ /// Construct an iterator that points to the specified address.
+ basic_address_iterator(const address_v4& addr) BOOST_ASIO_NOEXCEPT
+ : address_(addr)
+ {
+ }
+
+ /// Copy constructor.
+ basic_address_iterator(
+ const basic_address_iterator& other) BOOST_ASIO_NOEXCEPT
+ : address_(other.address_)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move constructor.
+ basic_address_iterator(basic_address_iterator&& other) BOOST_ASIO_NOEXCEPT
+ : address_(BOOST_ASIO_MOVE_CAST(address_v4)(other.address_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Assignment operator.
+ basic_address_iterator& operator=(
+ const basic_address_iterator& other) BOOST_ASIO_NOEXCEPT
+ {
+ address_ = other.address_;
+ return *this;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move assignment operator.
+ basic_address_iterator& operator=(
+ basic_address_iterator&& other) BOOST_ASIO_NOEXCEPT
+ {
+ address_ = BOOST_ASIO_MOVE_CAST(address_v4)(other.address_);
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Dereference the iterator.
+ const address_v4& operator*() const BOOST_ASIO_NOEXCEPT
+ {
+ return address_;
+ }
+
+ /// Dereference the iterator.
+ const address_v4* operator->() const BOOST_ASIO_NOEXCEPT
+ {
+ return &address_;
+ }
+
+ /// Pre-increment operator.
+ basic_address_iterator& operator++() BOOST_ASIO_NOEXCEPT
+ {
+ address_ = address_v4((address_.to_uint() + 1) & 0xFFFFFFFF);
+ return *this;
+ }
+
+ /// Post-increment operator.
+ basic_address_iterator operator++(int) BOOST_ASIO_NOEXCEPT
+ {
+ basic_address_iterator tmp(*this);
+ ++*this;
+ return tmp;
+ }
+
+ /// Pre-decrement operator.
+ basic_address_iterator& operator--() BOOST_ASIO_NOEXCEPT
+ {
+ address_ = address_v4((address_.to_uint() - 1) & 0xFFFFFFFF);
+ return *this;
+ }
+
+ /// Post-decrement operator.
+ basic_address_iterator operator--(int)
+ {
+ basic_address_iterator tmp(*this);
+ --*this;
+ return tmp;
+ }
+
+ /// Compare two addresses for equality.
+ friend bool operator==(const basic_address_iterator& a,
+ const basic_address_iterator& b)
+ {
+ return a.address_ == b.address_;
+ }
+
+ /// Compare two addresses for inequality.
+ friend bool operator!=(const basic_address_iterator& a,
+ const basic_address_iterator& b)
+ {
+ return a.address_ != b.address_;
+ }
+
+private:
+ address_v4 address_;
+};
+
+/// An input iterator that can be used for traversing IPv4 addresses.
+typedef basic_address_iterator<address_v4> address_v4_iterator;
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_ADDRESS_V4_ITERATOR_HPP
diff --git a/boost/asio/ip/address_v4_range.hpp b/boost/asio/ip/address_v4_range.hpp
new file mode 100644
index 0000000000..1e2afeaf5a
--- /dev/null
+++ b/boost/asio/ip/address_v4_range.hpp
@@ -0,0 +1,136 @@
+//
+// ip/address_v4_range.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_ADDRESS_V4_RANGE_HPP
+#define BOOST_ASIO_IP_ADDRESS_V4_RANGE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/ip/address_v4_iterator.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+template <typename> class basic_address_range;
+
+/// Represents a range of IPv4 addresses.
+/**
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <> class basic_address_range<address_v4>
+{
+public:
+ /// The type of an iterator that points into the range.
+ typedef basic_address_iterator<address_v4> iterator;
+
+ /// Construct an empty range.
+ basic_address_range() BOOST_ASIO_NOEXCEPT
+ : begin_(address_v4()),
+ end_(address_v4())
+ {
+ }
+
+ /// Construct an range that represents the given range of addresses.
+ explicit basic_address_range(const iterator& first,
+ const iterator& last) BOOST_ASIO_NOEXCEPT
+ : begin_(first),
+ end_(last)
+ {
+ }
+
+ /// Copy constructor.
+ basic_address_range(const basic_address_range& other) BOOST_ASIO_NOEXCEPT
+ : begin_(other.begin_),
+ end_(other.end_)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move constructor.
+ basic_address_range(basic_address_range&& other) BOOST_ASIO_NOEXCEPT
+ : begin_(BOOST_ASIO_MOVE_CAST(iterator)(other.begin_)),
+ end_(BOOST_ASIO_MOVE_CAST(iterator)(other.end_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Assignment operator.
+ basic_address_range& operator=(
+ const basic_address_range& other) BOOST_ASIO_NOEXCEPT
+ {
+ begin_ = other.begin_;
+ end_ = other.end_;
+ return *this;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move assignment operator.
+ basic_address_range& operator=(
+ basic_address_range&& other) BOOST_ASIO_NOEXCEPT
+ {
+ begin_ = BOOST_ASIO_MOVE_CAST(iterator)(other.begin_);
+ end_ = BOOST_ASIO_MOVE_CAST(iterator)(other.end_);
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Obtain an iterator that points to the start of the range.
+ iterator begin() const BOOST_ASIO_NOEXCEPT
+ {
+ return begin_;
+ }
+
+ /// Obtain an iterator that points to the end of the range.
+ iterator end() const BOOST_ASIO_NOEXCEPT
+ {
+ return end_;
+ }
+
+ /// Determine whether the range is empty.
+ bool empty() const BOOST_ASIO_NOEXCEPT
+ {
+ return size() == 0;
+ }
+
+ /// Return the size of the range.
+ std::size_t size() const BOOST_ASIO_NOEXCEPT
+ {
+ return end_->to_uint() - begin_->to_uint();
+ }
+
+ /// Find an address in the range.
+ iterator find(const address_v4& addr) const BOOST_ASIO_NOEXCEPT
+ {
+ return addr >= *begin_ && addr < *end_ ? iterator(addr) : end_;
+ }
+
+private:
+ iterator begin_;
+ iterator end_;
+};
+
+/// Represents a range of IPv4 addresses.
+typedef basic_address_range<address_v4> address_v4_range;
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_ADDRESS_V4_RANGE_HPP
diff --git a/boost/asio/ip/address_v6.hpp b/boost/asio/ip/address_v6.hpp
index 10e9bc1594..496a1df323 100644
--- a/boost/asio/ip/address_v6.hpp
+++ b/boost/asio/ip/address_v6.hpp
@@ -19,6 +19,7 @@
#include <string>
#include <boost/asio/detail/array.hpp>
#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/detail/string_view.hpp>
#include <boost/asio/detail/winsock_init.hpp>
#include <boost/system/error_code.hpp>
#include <boost/asio/ip/address_v4.hpp>
@@ -33,6 +34,8 @@ namespace boost {
namespace asio {
namespace ip {
+template <typename> class basic_address_iterator;
+
/// Implements IP version 6 style addresses.
/**
* The boost::asio::ip::address_v6 class provides the ability to use and
@@ -103,25 +106,32 @@ public:
/// Get the address as a string.
BOOST_ASIO_DECL std::string to_string() const;
- /// Get the address as a string.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use other overload.) Get the address as a string.
BOOST_ASIO_DECL std::string to_string(boost::system::error_code& ec) const;
- /// Create an address from an IP address string.
- BOOST_ASIO_DECL static address_v6 from_string(const char* str);
+ /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP
+ /// address string.
+ static address_v6 from_string(const char* str);
- /// Create an address from an IP address string.
- BOOST_ASIO_DECL static address_v6 from_string(
+ /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP
+ /// address string.
+ static address_v6 from_string(
const char* str, boost::system::error_code& ec);
- /// Create an address from an IP address string.
- BOOST_ASIO_DECL static address_v6 from_string(const std::string& str);
+ /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP
+ /// address string.
+ static address_v6 from_string(const std::string& str);
- /// Create an address from an IP address string.
- BOOST_ASIO_DECL static address_v6 from_string(
+ /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP
+ /// address string.
+ static address_v6 from_string(
const std::string& str, boost::system::error_code& ec);
- /// Converts an IPv4-mapped or IPv4-compatible address to an IPv4 address.
+ /// (Deprecated: Use make_address_v4().) Converts an IPv4-mapped or
+ /// IPv4-compatible address to an IPv4 address.
BOOST_ASIO_DECL address_v4 to_v4() const;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Determine whether the address is a loopback address.
BOOST_ASIO_DECL bool is_loopback() const;
@@ -138,8 +148,11 @@ public:
/// Determine whether the address is a mapped IPv4 address.
BOOST_ASIO_DECL bool is_v4_mapped() const;
- /// Determine whether the address is an IPv4-compatible address.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: No replacement.) Determine whether the address is an
+ /// IPv4-compatible address.
BOOST_ASIO_DECL bool is_v4_compatible() const;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Determine whether the address is a multicast address.
BOOST_ASIO_DECL bool is_multicast() const;
@@ -200,13 +213,17 @@ public:
/// Obtain an address object that represents the loopback address.
BOOST_ASIO_DECL static address_v6 loopback();
- /// Create an IPv4-mapped IPv6 address.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use make_address_v6().) Create an IPv4-mapped IPv6 address.
BOOST_ASIO_DECL static address_v6 v4_mapped(const address_v4& addr);
- /// Create an IPv4-compatible IPv6 address.
+ /// (Deprecated: No replacement.) Create an IPv4-compatible IPv6 address.
BOOST_ASIO_DECL static address_v6 v4_compatible(const address_v4& addr);
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
private:
+ friend class basic_address_iterator<address_v6>;
+
// The underlying IPv6 address.
boost::asio::detail::in6_addr_type addr_;
@@ -214,6 +231,79 @@ private:
unsigned long scope_id_;
};
+/// Create an IPv6 address from raw bytes and scope ID.
+/**
+ * @relates address_v6
+ */
+inline address_v6 make_address_v6(const address_v6::bytes_type& bytes,
+ unsigned long scope_id = 0)
+{
+ return address_v6(bytes, scope_id);
+}
+
+/// Create an IPv6 address from an IP address string.
+/**
+ * @relates address_v6
+ */
+BOOST_ASIO_DECL address_v6 make_address_v6(const char* str);
+
+/// Create an IPv6 address from an IP address string.
+/**
+ * @relates address_v6
+ */
+BOOST_ASIO_DECL address_v6 make_address_v6(
+ const char* str, boost::system::error_code& ec);
+
+/// Createan IPv6 address from an IP address string.
+/**
+ * @relates address_v6
+ */
+BOOST_ASIO_DECL address_v6 make_address_v6(const std::string& str);
+
+/// Create an IPv6 address from an IP address string.
+/**
+ * @relates address_v6
+ */
+BOOST_ASIO_DECL address_v6 make_address_v6(
+ const std::string& str, boost::system::error_code& ec);
+
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW) \
+ || defined(GENERATING_DOCUMENTATION)
+
+/// Create an IPv6 address from an IP address string.
+/**
+ * @relates address_v6
+ */
+BOOST_ASIO_DECL address_v6 make_address_v6(string_view str);
+
+/// Create an IPv6 address from an IP address string.
+/**
+ * @relates address_v6
+ */
+BOOST_ASIO_DECL address_v6 make_address_v6(
+ string_view str, boost::system::error_code& ec);
+
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ // || defined(GENERATING_DOCUMENTATION)
+
+/// Tag type used for distinguishing overloads that deal in IPv4-mapped IPv6
+/// addresses.
+enum v4_mapped_t { v4_mapped };
+
+/// Create an IPv4 address from a IPv4-mapped IPv6 address.
+/**
+ * @relates address_v4
+ */
+BOOST_ASIO_DECL address_v4 make_address_v4(
+ v4_mapped_t, const address_v6& v6_addr);
+
+/// Create an IPv4-mapped IPv6 address from an IPv4 address.
+/**
+ * @relates address_v6
+ */
+BOOST_ASIO_DECL address_v6 make_address_v6(
+ v4_mapped_t, const address_v4& v4_addr);
+
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// Output an address as a string.
diff --git a/boost/asio/ip/address_v6_iterator.hpp b/boost/asio/ip/address_v6_iterator.hpp
new file mode 100644
index 0000000000..4518996b3c
--- /dev/null
+++ b/boost/asio/ip/address_v6_iterator.hpp
@@ -0,0 +1,185 @@
+//
+// ip/address_v6_iterator.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 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
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IP_ADDRESS_V6_ITERATOR_HPP
+#define BOOST_ASIO_IP_ADDRESS_V6_ITERATOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/ip/address_v6.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+template <typename> class basic_address_iterator;
+
+/// An input iterator that can be used for traversing IPv6 addresses.
+/**
+ * In addition to satisfying the input iterator requirements, this iterator
+ * also supports decrement.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <> class basic_address_iterator<address_v6>
+{
+public:
+ /// The type of the elements pointed to by the iterator.
+ typedef address_v6 value_type;
+
+ /// Distance between two iterators.
+ typedef std::ptrdiff_t difference_type;
+
+ /// The type of a pointer to an element pointed to by the iterator.
+ typedef const address_v6* pointer;
+
+ /// The type of a reference to an element pointed to by the iterator.
+ typedef const address_v6& reference;
+
+ /// Denotes that the iterator satisfies the input iterator requirements.
+ typedef std::input_iterator_tag iterator_category;
+
+ /// Construct an iterator that points to the specified address.
+ basic_address_iterator(const address_v6& addr) BOOST_ASIO_NOEXCEPT
+ : address_(addr)
+ {
+ }
+
+ /// Copy constructor.
+ basic_address_iterator(
+ const basic_address_iterator& other) BOOST_ASIO_NOEXCEPT
+ : address_(other.address_)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move constructor.
+ basic_address_iterator(basic_address_iterator&& other) BOOST_ASIO_NOEXCEPT
+ : address_(BOOST_ASIO_MOVE_CAST(address_v6)(other.address_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Assignment operator.
+ basic_address_iterator& operator=(
+ const basic_address_iterator& other) BOOST_ASIO_NOEXCEPT
+ {
+ address_ = other.address_;
+ return *this;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move assignment operator.
+ basic_address_iterator& operator=(
+ basic_address_iterator&& other) BOOST_ASIO_NOEXCEPT
+ {
+ address_ = BOOST_ASIO_MOVE_CAST(address_v6)(other.address_);
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Dereference the iterator.
+ const address_v6& operator*() const BOOST_ASIO_NOEXCEPT
+ {
+ return address_;
+ }
+
+ /// Dereference the iterator.
+ const address_v6* operator->() const BOOST_ASIO_NOEXCEPT
+ {
+ return &address_;
+ }
+
+ /// Pre-increment operator.
+ basic_address_iterator& operator++() BOOST_ASIO_NOEXCEPT
+ {
+ for (int i = 15; i >= 0; --i)
+ {
+ if (address_.addr_.s6_addr[i] < 0xFF)
+ {
+ ++address_.addr_.s6_addr[i];
+ break;
+ }
+
+ address_.addr_.s6_addr[i] = 0;
+ }
+
+ return *this;
+ }
+
+ /// Post-increment operator.
+ basic_address_iterator operator++(int) BOOST_ASIO_NOEXCEPT
+ {
+ basic_address_iterator tmp(*this);
+ ++*this;
+ return tmp;
+ }
+
+ /// Pre-decrement operator.
+ basic_address_iterator& operator--() BOOST_ASIO_NOEXCEPT
+ {
+ for (int i = 15; i >= 0; --i)
+ {
+ if (address_.addr_.s6_addr[i] > 0)
+ {
+ --address_.addr_.s6_addr[i];
+ break;
+ }
+
+ address_.addr_.s6_addr[i] = 0xFF;
+ }
+
+ return *this;
+ }
+
+ /// Post-decrement operator.
+ basic_address_iterator operator--(int)
+ {
+ basic_address_iterator tmp(*this);
+ --*this;
+ return tmp;
+ }
+
+ /// Compare two addresses for equality.
+ friend bool operator==(const basic_address_iterator& a,
+ const basic_address_iterator& b)
+ {
+ return a.address_ == b.address_;
+ }
+
+ /// Compare two addresses for inequality.
+ friend bool operator!=(const basic_address_iterator& a,
+ const basic_address_iterator& b)
+ {
+ return a.address_ != b.address_;
+ }
+
+private:
+ address_v6 address_;
+};
+
+/// An input iterator that can be used for traversing IPv6 addresses.
+typedef basic_address_iterator<address_v6> address_v6_iterator;
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_ADDRESS_V6_ITERATOR_HPP
diff --git a/boost/asio/ip/address_v6_range.hpp b/boost/asio/ip/address_v6_range.hpp
new file mode 100644
index 0000000000..68b987d7c9
--- /dev/null
+++ b/boost/asio/ip/address_v6_range.hpp
@@ -0,0 +1,131 @@
+//
+// ip/address_v6_range.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 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
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IP_ADDRESS_V6_RANGE_HPP
+#define BOOST_ASIO_IP_ADDRESS_V6_RANGE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/ip/address_v6_iterator.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+template <typename> class basic_address_range;
+
+/// Represents a range of IPv6 addresses.
+/**
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <> class basic_address_range<address_v6>
+{
+public:
+ /// The type of an iterator that points into the range.
+ typedef basic_address_iterator<address_v6> iterator;
+
+ /// Construct an empty range.
+ basic_address_range() BOOST_ASIO_NOEXCEPT
+ : begin_(address_v6()),
+ end_(address_v6())
+ {
+ }
+
+ /// Construct an range that represents the given range of addresses.
+ explicit basic_address_range(const iterator& first,
+ const iterator& last) BOOST_ASIO_NOEXCEPT
+ : begin_(first),
+ end_(last)
+ {
+ }
+
+ /// Copy constructor.
+ basic_address_range(const basic_address_range& other) BOOST_ASIO_NOEXCEPT
+ : begin_(other.begin_),
+ end_(other.end_)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move constructor.
+ basic_address_range(basic_address_range&& other) BOOST_ASIO_NOEXCEPT
+ : begin_(BOOST_ASIO_MOVE_CAST(iterator)(other.begin_)),
+ end_(BOOST_ASIO_MOVE_CAST(iterator)(other.end_))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Assignment operator.
+ basic_address_range& operator=(
+ const basic_address_range& other) BOOST_ASIO_NOEXCEPT
+ {
+ begin_ = other.begin_;
+ end_ = other.end_;
+ return *this;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move assignment operator.
+ basic_address_range& operator=(
+ basic_address_range&& other) BOOST_ASIO_NOEXCEPT
+ {
+ begin_ = BOOST_ASIO_MOVE_CAST(iterator)(other.begin_);
+ end_ = BOOST_ASIO_MOVE_CAST(iterator)(other.end_);
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Obtain an iterator that points to the start of the range.
+ iterator begin() const BOOST_ASIO_NOEXCEPT
+ {
+ return begin_;
+ }
+
+ /// Obtain an iterator that points to the end of the range.
+ iterator end() const BOOST_ASIO_NOEXCEPT
+ {
+ return end_;
+ }
+
+ /// Determine whether the range is empty.
+ bool empty() const BOOST_ASIO_NOEXCEPT
+ {
+ return begin_ == end_;
+ }
+
+ /// Find an address in the range.
+ iterator find(const address_v6& addr) const BOOST_ASIO_NOEXCEPT
+ {
+ return addr >= *begin_ && addr < *end_ ? iterator(addr) : end_;
+ }
+
+private:
+ iterator begin_;
+ iterator end_;
+};
+
+/// Represents a range of IPv6 addresses.
+typedef basic_address_range<address_v6> address_v6_range;
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_ADDRESS_V6_RANGE_HPP
diff --git a/boost/asio/ip/bad_address_cast.hpp b/boost/asio/ip/bad_address_cast.hpp
new file mode 100644
index 0000000000..9c82fdfeb3
--- /dev/null
+++ b/boost/asio/ip/bad_address_cast.hpp
@@ -0,0 +1,50 @@
+//
+// ip/bad_address_cast.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_BAD_ADDRESS_CAST_HPP
+#define BOOST_ASIO_IP_BAD_ADDRESS_CAST_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <typeinfo>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Thrown to indicate a failed address conversion.
+class bad_address_cast : public std::bad_cast
+{
+public:
+ /// Default constructor.
+ bad_address_cast() {}
+
+ /// Destructor.
+ virtual ~bad_address_cast() BOOST_ASIO_NOEXCEPT_OR_NOTHROW {}
+
+ /// Get the message associated with the exception.
+ virtual const char* what() const BOOST_ASIO_NOEXCEPT_OR_NOTHROW
+ {
+ return "bad address cast";
+ }
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_ADDRESS_HPP
diff --git a/boost/asio/ip/basic_endpoint.hpp b/boost/asio/ip/basic_endpoint.hpp
index 235b178589..7a9f72ba36 100644
--- a/boost/asio/ip/basic_endpoint.hpp
+++ b/boost/asio/ip/basic_endpoint.hpp
@@ -98,13 +98,13 @@ public:
{
}
-#if defined(BOOST_ASIO_HAS_MOVE)
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move constructor.
basic_endpoint(basic_endpoint&& other)
: impl_(other.impl_)
{
}
-#endif // defined(BOOST_ASIO_HAS_MOVE)
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Assign from another endpoint.
basic_endpoint& operator=(const basic_endpoint& other)
@@ -113,14 +113,14 @@ public:
return *this;
}
-#if defined(BOOST_ASIO_HAS_MOVE)
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move-assign from another endpoint.
basic_endpoint& operator=(basic_endpoint&& other)
{
impl_ = other.impl_;
return *this;
}
-#endif // defined(BOOST_ASIO_HAS_MOVE)
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// The protocol associated with the endpoint.
protocol_type protocol() const
diff --git a/boost/asio/ip/basic_resolver.hpp b/boost/asio/ip/basic_resolver.hpp
index c5941de4f1..714e950832 100644
--- a/boost/asio/ip/basic_resolver.hpp
+++ b/boost/asio/ip/basic_resolver.hpp
@@ -16,13 +16,36 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+#include <string>
+#include <boost/asio/async_result.hpp>
#include <boost/asio/basic_io_object.hpp>
#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/string_view.hpp>
#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/basic_resolver_iterator.hpp>
#include <boost/asio/ip/basic_resolver_query.hpp>
-#include <boost/asio/ip/resolver_service.hpp>
+#include <boost/asio/ip/basic_resolver_results.hpp>
+#include <boost/asio/ip/resolver_base.hpp>
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/ip/resolver_service.hpp>
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/winrt_resolver_service.hpp>
+# define BOOST_ASIO_SVC_T \
+ boost::asio::detail::winrt_resolver_service<InternetProtocol>
+# else
+# include <boost/asio/detail/resolver_service.hpp>
+# define BOOST_ASIO_SVC_T \
+ boost::asio::detail::resolver_service<InternetProtocol>
+# endif
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
#include <boost/asio/detail/push_options.hpp>
@@ -39,35 +62,130 @@ namespace ip {
* @e Distinct @e objects: Safe.@n
* @e Shared @e objects: Unsafe.
*/
-template <typename InternetProtocol,
- typename ResolverService = resolver_service<InternetProtocol> >
+template <typename InternetProtocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= resolver_service<InternetProtocol>)>
class basic_resolver
- : public basic_io_object<ResolverService>
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>,
+ public resolver_base
{
public:
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
+
/// The protocol type.
typedef InternetProtocol protocol_type;
/// The endpoint type.
typedef typename InternetProtocol::endpoint endpoint_type;
- /// The query type.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated.) The query type.
typedef basic_resolver_query<InternetProtocol> query;
- /// The iterator type.
+ /// (Deprecated.) The iterator type.
typedef basic_resolver_iterator<InternetProtocol> iterator;
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// The results type.
+ typedef basic_resolver_results<InternetProtocol> results_type;
/// Constructor.
/**
* This constructor creates a basic_resolver.
*
- * @param io_service The io_service object that the resolver will use to
- * dispatch handlers for any asynchronous operations performed on the timer.
+ * @param io_context The io_context object that the resolver will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * resolver.
+ */
+ explicit basic_resolver(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// 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(io_context&) constructor.
+ */
+ basic_resolver(basic_resolver&& other)
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
+ {
+ }
+
+ /// 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(io_context&) constructor.
+ */
+ basic_resolver& operator=(basic_resolver&& other)
+ {
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroys the resolver.
+ /**
+ * This function destroys the resolver, cancelling any outstanding
+ * asynchronous wait operations associated with the resolver as if by calling
+ * @c cancel.
+ */
+ ~basic_resolver()
+ {
+ }
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ // These functions are provided by basic_io_object<>.
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
*/
- explicit basic_resolver(boost::asio::io_service& io_service)
- : basic_io_object<ResolverService>(io_service)
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
{
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
}
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
/// Cancel any asynchronous operations that are waiting on the resolver.
/**
@@ -77,56 +195,414 @@ public:
*/
void cancel()
{
- return this->service.cancel(this->implementation);
+ return this->get_service().cancel(this->get_implementation());
}
- /// Perform forward resolution of a query to a list of entries.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated.) Perform forward resolution of a query to a list of entries.
/**
* This function is used to resolve a query into a list of endpoint entries.
*
* @param q A query object that determines what endpoints will be returned.
*
- * @returns A forward-only iterator that can be used to traverse the list
- * of endpoint entries.
+ * @returns A range object representing the list of endpoint entries. A
+ * successful call to this function is guaranteed to return a non-empty
+ * range.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ results_type resolve(const query& q)
+ {
+ boost::system::error_code ec;
+ results_type r = this->get_service().resolve(
+ this->get_implementation(), q, ec);
+ boost::asio::detail::throw_error(ec, "resolve");
+ return r;
+ }
+
+ /// (Deprecated.) Perform forward resolution of a query to a list of entries.
+ /**
+ * This function is used to resolve a query into a list of endpoint entries.
+ *
+ * @param q A query object that determines what endpoints will be returned.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns A range object representing the list of endpoint entries. An
+ * empty range is returned if an error occurs. A successful call to this
+ * function is guaranteed to return a non-empty range.
+ */
+ results_type resolve(const query& q, boost::system::error_code& ec)
+ {
+ return this->get_service().resolve(this->get_implementation(), q, ec);
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// 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.
+ *
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * be an empty string, in which case all resolved endpoints will have a port
+ * number of 0.
+ *
+ * @returns A range object representing the list of endpoint entries. A
+ * successful call to this function is guaranteed to return a non-empty
+ * range.
*
* @throws boost::system::system_error Thrown on failure.
*
- * @note A default constructed iterator represents the end of the list.
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
*
- * A successful call to this function is guaranteed to return at least one
- * entry.
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
*/
- iterator resolve(const query& q)
+ results_type resolve(BOOST_ASIO_STRING_VIEW_PARAM host,
+ BOOST_ASIO_STRING_VIEW_PARAM service)
+ {
+ return resolve(host, service, resolver_base::flags());
+ }
+
+ /// 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.
+ *
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * be an empty string, in which case all resolved endpoints will have a port
+ * number of 0.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns A range object representing the list of endpoint entries. An
+ * empty range is returned if an error occurs. A successful call to this
+ * function is guaranteed to return a non-empty range.
+ *
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
+ *
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
+ */
+ results_type resolve(BOOST_ASIO_STRING_VIEW_PARAM host,
+ BOOST_ASIO_STRING_VIEW_PARAM service, boost::system::error_code& ec)
+ {
+ return resolve(host, service, resolver_base::flags(), ec);
+ }
+
+ /// 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.
+ *
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * be an empty string, in which case all resolved endpoints will have a port
+ * number of 0.
+ *
+ * @param resolve_flags A set of flags that determine how name resolution
+ * should be performed. The default flags are suitable for communication with
+ * remote hosts.
+ *
+ * @returns A range object representing the list of endpoint entries. A
+ * successful call to this function is guaranteed to return a non-empty
+ * range.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
+ *
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
+ */
+ results_type resolve(BOOST_ASIO_STRING_VIEW_PARAM host,
+ BOOST_ASIO_STRING_VIEW_PARAM service, resolver_base::flags resolve_flags)
{
boost::system::error_code ec;
- iterator i = this->service.resolve(this->implementation, q, ec);
+ basic_resolver_query<protocol_type> q(static_cast<std::string>(host),
+ static_cast<std::string>(service), resolve_flags);
+ results_type r = this->get_service().resolve(
+ this->get_implementation(), q, ec);
boost::asio::detail::throw_error(ec, "resolve");
- return i;
+ return r;
}
/// Perform forward resolution of a query to a list of entries.
/**
- * This function is used to resolve a query into a list of endpoint entries.
+ * This function is used to resolve host and service names into a list of
+ * endpoint entries.
*
- * @param q A query object that determines what endpoints will be returned.
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * be an empty string, in which case all resolved endpoints will have a port
+ * number of 0.
+ *
+ * @param resolve_flags A set of flags that determine how name resolution
+ * should be performed. The default flags are suitable for communication with
+ * remote hosts.
*
* @param ec Set to indicate what error occurred, if any.
*
- * @returns A forward-only iterator that can be used to traverse the list
- * of endpoint entries. Returns a default constructed iterator if an error
- * occurs.
+ * @returns A range object representing the list of endpoint entries. An
+ * empty range is returned if an error occurs. A successful call to this
+ * function is guaranteed to return a non-empty range.
*
- * @note A default constructed iterator represents the end of the list.
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
*
- * A successful call to this function is guaranteed to return at least one
- * entry.
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
*/
- iterator resolve(const query& q, boost::system::error_code& ec)
+ results_type resolve(BOOST_ASIO_STRING_VIEW_PARAM host,
+ BOOST_ASIO_STRING_VIEW_PARAM service, resolver_base::flags resolve_flags,
+ boost::system::error_code& ec)
{
- return this->service.resolve(this->implementation, q, ec);
+ basic_resolver_query<protocol_type> q(static_cast<std::string>(host),
+ static_cast<std::string>(service), resolve_flags);
+ return this->get_service().resolve(this->get_implementation(), q, ec);
}
- /// Asynchronously perform forward resolution of a query to a list of entries.
+ /// 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.
+ *
+ * @param protocol A protocol object, normally representing either the IPv4 or
+ * IPv6 version of an internet protocol.
+ *
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * be an empty string, in which case all resolved endpoints will have a port
+ * number of 0.
+ *
+ * @returns A range object representing the list of endpoint entries. A
+ * successful call to this function is guaranteed to return a non-empty
+ * range.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
+ *
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
+ */
+ results_type resolve(const protocol_type& protocol,
+ BOOST_ASIO_STRING_VIEW_PARAM host, BOOST_ASIO_STRING_VIEW_PARAM service)
+ {
+ return resolve(protocol, host, service, resolver_base::flags());
+ }
+
+ /// 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.
+ *
+ * @param protocol A protocol object, normally representing either the IPv4 or
+ * IPv6 version of an internet protocol.
+ *
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * be an empty string, in which case all resolved endpoints will have a port
+ * number of 0.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns A range object representing the list of endpoint entries. An
+ * empty range is returned if an error occurs. A successful call to this
+ * function is guaranteed to return a non-empty range.
+ *
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
+ *
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
+ */
+ results_type resolve(const protocol_type& protocol,
+ BOOST_ASIO_STRING_VIEW_PARAM host, BOOST_ASIO_STRING_VIEW_PARAM service,
+ boost::system::error_code& ec)
+ {
+ return resolve(protocol, host, service, resolver_base::flags(), ec);
+ }
+
+ /// 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.
+ *
+ * @param protocol A protocol object, normally representing either the IPv4 or
+ * IPv6 version of an internet protocol.
+ *
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * be an empty string, in which case all resolved endpoints will have a port
+ * number of 0.
+ *
+ * @param resolve_flags A set of flags that determine how name resolution
+ * should be performed. The default flags are suitable for communication with
+ * remote hosts.
+ *
+ * @returns A range object representing the list of endpoint entries. A
+ * successful call to this function is guaranteed to return a non-empty
+ * range.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
+ *
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
+ */
+ results_type resolve(const protocol_type& protocol,
+ BOOST_ASIO_STRING_VIEW_PARAM host, BOOST_ASIO_STRING_VIEW_PARAM service,
+ resolver_base::flags resolve_flags)
+ {
+ boost::system::error_code ec;
+ basic_resolver_query<protocol_type> q(
+ protocol, static_cast<std::string>(host),
+ static_cast<std::string>(service), resolve_flags);
+ results_type r = this->get_service().resolve(
+ this->get_implementation(), q, ec);
+ boost::asio::detail::throw_error(ec, "resolve");
+ return r;
+ }
+
+ /// 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.
+ *
+ * @param protocol A protocol object, normally representing either the IPv4 or
+ * IPv6 version of an internet protocol.
+ *
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * be an empty string, in which case all resolved endpoints will have a port
+ * number of 0.
+ *
+ * @param resolve_flags A set of flags that determine how name resolution
+ * should be performed. The default flags are suitable for communication with
+ * remote hosts.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns A range object representing the list of endpoint entries. An
+ * empty range is returned if an error occurs. A successful call to this
+ * function is guaranteed to return a non-empty range.
+ *
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
+ *
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
+ */
+ results_type resolve(const protocol_type& protocol,
+ BOOST_ASIO_STRING_VIEW_PARAM host, BOOST_ASIO_STRING_VIEW_PARAM service,
+ resolver_base::flags resolve_flags, boost::system::error_code& ec)
+ {
+ basic_resolver_query<protocol_type> q(
+ protocol, static_cast<std::string>(host),
+ static_cast<std::string>(service), resolve_flags);
+ return this->get_service().resolve(this->get_implementation(), q, ec);
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated.) 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.
@@ -138,35 +614,307 @@ public:
* signature of the handler must be:
* @code void handler(
* const boost::system::error_code& error, // Result of operation.
- * resolver::iterator iterator // Forward-only iterator that can
- * // be used to traverse the list
- * // of endpoint entries.
+ * 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. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
- * @note A default constructed iterator represents the end of the list.
- *
- * A successful resolve operation is guaranteed to pass at least one entry to
+ * A successful resolve operation is guaranteed to pass a non-empty range to
* the handler.
*/
template <typename ResolveHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ResolveHandler,
- void (boost::system::error_code, iterator))
+ void (boost::system::error_code, results_type))
async_resolve(const query& q,
BOOST_ASIO_MOVE_ARG(ResolveHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ResolveHandler.
BOOST_ASIO_RESOLVE_HANDLER_CHECK(
- ResolveHandler, handler, iterator) type_check;
+ ResolveHandler, handler, results_type) type_check;
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_resolve(this->get_implementation(), q,
+ BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ boost::asio::async_completion<ResolveHandler,
+ void (boost::system::error_code, results_type)> init(handler);
+
+ this->get_service().async_resolve(
+ this->get_implementation(), q, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// 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.
+ *
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * 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:
+ * @code void handler(
+ * const boost::system::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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * A successful resolve operation is guaranteed to pass a non-empty range to
+ * the handler.
+ *
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
+ *
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
+ */
+ template <typename ResolveHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ResolveHandler,
+ void (boost::system::error_code, results_type))
+ async_resolve(BOOST_ASIO_STRING_VIEW_PARAM host,
+ BOOST_ASIO_STRING_VIEW_PARAM service,
+ BOOST_ASIO_MOVE_ARG(ResolveHandler) handler)
+ {
+ return async_resolve(host, service, resolver_base::flags(),
+ BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler));
+ }
+
+ /// 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.
+ *
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * be an empty string, in which case all resolved endpoints will have a port
+ * number of 0.
+ *
+ * @param resolve_flags A set of flags that determine how name resolution
+ * should be performed. The default flags are suitable for communication with
+ * remote hosts.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * A successful resolve operation is guaranteed to pass a non-empty range to
+ * the handler.
+ *
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
+ *
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
+ */
+ template <typename ResolveHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ResolveHandler,
+ void (boost::system::error_code, results_type))
+ async_resolve(BOOST_ASIO_STRING_VIEW_PARAM host,
+ BOOST_ASIO_STRING_VIEW_PARAM service,
+ resolver_base::flags resolve_flags,
+ BOOST_ASIO_MOVE_ARG(ResolveHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ResolveHandler.
+ BOOST_ASIO_RESOLVE_HANDLER_CHECK(
+ ResolveHandler, handler, results_type) type_check;
- return this->service.async_resolve(this->implementation, q,
+ basic_resolver_query<protocol_type> q(static_cast<std::string>(host),
+ static_cast<std::string>(service), resolve_flags);
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_resolve(this->get_implementation(), q,
+ BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ boost::asio::async_completion<ResolveHandler,
+ void (boost::system::error_code, results_type)> init(handler);
+
+ this->get_service().async_resolve(
+ this->get_implementation(), q, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
+ /// 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.
+ *
+ * @param protocol A protocol object, normally representing either the IPv4 or
+ * IPv6 version of an internet protocol.
+ *
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * 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:
+ * @code void handler(
+ * const boost::system::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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * A successful resolve operation is guaranteed to pass a non-empty range to
+ * the handler.
+ *
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
+ *
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
+ */
+ template <typename ResolveHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ResolveHandler,
+ void (boost::system::error_code, results_type))
+ async_resolve(const protocol_type& protocol,
+ BOOST_ASIO_STRING_VIEW_PARAM host, BOOST_ASIO_STRING_VIEW_PARAM service,
+ BOOST_ASIO_MOVE_ARG(ResolveHandler) handler)
+ {
+ return async_resolve(protocol, host, service, resolver_base::flags(),
BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler));
}
+ /// 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.
+ *
+ * @param protocol A protocol object, normally representing either the IPv4 or
+ * IPv6 version of an internet protocol.
+ *
+ * @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
+ * specified, the resolved endpoints are suitable for local service binding.
+ * If an empty string and passive is not specified, the resolved endpoints
+ * will use the loopback address.
+ *
+ * @param service A string identifying the requested service. This may be a
+ * descriptive name or a numeric string corresponding to a port number. May
+ * be an empty string, in which case all resolved endpoints will have a port
+ * number of 0.
+ *
+ * @param resolve_flags A set of flags that determine how name resolution
+ * should be performed. The default flags are suitable for communication with
+ * remote hosts.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * A successful resolve operation is guaranteed to pass a non-empty range to
+ * the handler.
+ *
+ * @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
+ * resolution is performed using DNS. Operating systems may use additional
+ * locations when resolving host names (such as NETBIOS names on Windows).
+ *
+ * On POSIX systems, service names are typically defined in the file
+ * <tt>/etc/services</tt>. On Windows, service names may be found in the file
+ * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems
+ * may use additional locations when resolving service names.
+ */
+ template <typename ResolveHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ResolveHandler,
+ void (boost::system::error_code, results_type))
+ async_resolve(const protocol_type& protocol,
+ BOOST_ASIO_STRING_VIEW_PARAM host, BOOST_ASIO_STRING_VIEW_PARAM service,
+ resolver_base::flags resolve_flags,
+ BOOST_ASIO_MOVE_ARG(ResolveHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ResolveHandler.
+ BOOST_ASIO_RESOLVE_HANDLER_CHECK(
+ ResolveHandler, handler, results_type) type_check;
+
+ basic_resolver_query<protocol_type> q(
+ protocol, static_cast<std::string>(host),
+ static_cast<std::string>(service), resolve_flags);
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_resolve(this->get_implementation(), q,
+ BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ boost::asio::async_completion<ResolveHandler,
+ void (boost::system::error_code, results_type)> init(handler);
+
+ this->get_service().async_resolve(
+ this->get_implementation(), q, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ }
+
/// Perform reverse resolution of an endpoint to a list of entries.
/**
* This function is used to resolve an endpoint into a list of endpoint
@@ -175,20 +923,17 @@ public:
* @param e An endpoint object that determines what endpoints will be
* returned.
*
- * @returns A forward-only iterator that can be used to traverse the list
- * of endpoint entries.
+ * @returns A range object representing the list of endpoint entries. A
+ * successful call to this function is guaranteed to return a non-empty
+ * range.
*
* @throws boost::system::system_error Thrown on failure.
- *
- * @note A default constructed iterator represents the end of the list.
- *
- * A successful call to this function is guaranteed to return at least one
- * entry.
*/
- iterator resolve(const endpoint_type& e)
+ results_type resolve(const endpoint_type& e)
{
boost::system::error_code ec;
- iterator i = this->service.resolve(this->implementation, e, ec);
+ results_type i = this->get_service().resolve(
+ this->get_implementation(), e, ec);
boost::asio::detail::throw_error(ec, "resolve");
return i;
}
@@ -203,18 +948,13 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*
- * @returns A forward-only iterator that can be used to traverse the list
- * of endpoint entries. Returns a default constructed iterator if an error
- * occurs.
- *
- * @note A default constructed iterator represents the end of the list.
- *
- * A successful call to this function is guaranteed to return at least one
- * entry.
+ * @returns A range object representing the list of endpoint entries. An
+ * empty range is returned if an error occurs. A successful call to this
+ * function is guaranteed to return a non-empty range.
*/
- iterator resolve(const endpoint_type& e, boost::system::error_code& ec)
+ results_type resolve(const endpoint_type& e, boost::system::error_code& ec)
{
- return this->service.resolve(this->implementation, e, ec);
+ return this->get_service().resolve(this->get_implementation(), e, ec);
}
/// Asynchronously perform reverse resolution of an endpoint to a list of
@@ -231,33 +971,39 @@ public:
* signature of the handler must be:
* @code void handler(
* const boost::system::error_code& error, // Result of operation.
- * resolver::iterator iterator // Forward-only iterator that can
- * // be used to traverse the list
- * // of endpoint entries.
+ * 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. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
- * @note A default constructed iterator represents the end of the list.
- *
- * A successful resolve operation is guaranteed to pass at least one entry to
+ * A successful resolve operation is guaranteed to pass a non-empty range to
* the handler.
*/
template <typename ResolveHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ResolveHandler,
- void (boost::system::error_code, iterator))
+ void (boost::system::error_code, results_type))
async_resolve(const endpoint_type& e,
BOOST_ASIO_MOVE_ARG(ResolveHandler) handler)
{
// If you get an error on the following line it means that your handler does
// not meet the documented type requirements for a ResolveHandler.
BOOST_ASIO_RESOLVE_HANDLER_CHECK(
- ResolveHandler, handler, iterator) type_check;
+ ResolveHandler, handler, results_type) type_check;
- return this->service.async_resolve(this->implementation, e,
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ return this->get_service().async_resolve(this->get_implementation(), e,
BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler));
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+ boost::asio::async_completion<ResolveHandler,
+ void (boost::system::error_code, results_type)> init(handler);
+
+ this->get_service().async_resolve(
+ this->get_implementation(), e, init.completion_handler);
+
+ return init.result.get();
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
}
};
@@ -267,4 +1013,8 @@ public:
#include <boost/asio/detail/pop_options.hpp>
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# undef BOOST_ASIO_SVC_T
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_IP_BASIC_RESOLVER_HPP
diff --git a/boost/asio/ip/basic_resolver_entry.hpp b/boost/asio/ip/basic_resolver_entry.hpp
index 05c8547a0c..ec6c7bd6d5 100644
--- a/boost/asio/ip/basic_resolver_entry.hpp
+++ b/boost/asio/ip/basic_resolver_entry.hpp
@@ -17,6 +17,7 @@
#include <boost/asio/detail/config.hpp>
#include <string>
+#include <boost/asio/detail/string_view.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -50,10 +51,10 @@ public:
/// Construct with specified endpoint, host name and service name.
basic_resolver_entry(const endpoint_type& ep,
- const std::string& host, const std::string& service)
+ BOOST_ASIO_STRING_VIEW_PARAM host, BOOST_ASIO_STRING_VIEW_PARAM service)
: endpoint_(ep),
- host_name_(host),
- service_name_(service)
+ host_name_(static_cast<std::string>(host)),
+ service_name_(static_cast<std::string>(service))
{
}
@@ -75,12 +76,30 @@ public:
return host_name_;
}
+ /// Get the host name associated with the entry.
+ template <class Allocator>
+ std::basic_string<char, std::char_traits<char>, Allocator> host_name(
+ const Allocator& alloc = Allocator()) const
+ {
+ return std::basic_string<char, std::char_traits<char>, Allocator>(
+ host_name_.c_str(), alloc);
+ }
+
/// Get the service name associated with the entry.
std::string service_name() const
{
return service_name_;
}
+ /// Get the service name associated with the entry.
+ template <class Allocator>
+ std::basic_string<char, std::char_traits<char>, Allocator> service_name(
+ const Allocator& alloc = Allocator()) const
+ {
+ return std::basic_string<char, std::char_traits<char>, Allocator>(
+ service_name_.c_str(), alloc);
+ }
+
private:
endpoint_type endpoint_;
std::string host_name_;
diff --git a/boost/asio/ip/basic_resolver_iterator.hpp b/boost/asio/ip/basic_resolver_iterator.hpp
index b7deb77364..6571fdd982 100644
--- a/boost/asio/ip/basic_resolver_iterator.hpp
+++ b/boost/asio/ip/basic_resolver_iterator.hpp
@@ -21,7 +21,7 @@
#include <iterator>
#include <string>
#include <vector>
-#include <boost/asio/detail/shared_ptr.hpp>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/socket_ops.hpp>
#include <boost/asio/detail/socket_types.hpp>
#include <boost/asio/ip/basic_resolver_entry.hpp>
@@ -73,114 +73,45 @@ public:
{
}
- /// Create an iterator from an addrinfo list returned by getaddrinfo.
- static basic_resolver_iterator create(
- boost::asio::detail::addrinfo_type* address_info,
- const std::string& host_name, const std::string& service_name)
+ /// Copy constructor.
+ basic_resolver_iterator(const basic_resolver_iterator& other)
+ : values_(other.values_),
+ index_(other.index_)
{
- basic_resolver_iterator iter;
- if (!address_info)
- return iter;
-
- std::string actual_host_name = host_name;
- if (address_info->ai_canonname)
- actual_host_name = address_info->ai_canonname;
-
- iter.values_.reset(new values_type);
-
- while (address_info)
- {
- if (address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET)
- || address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET6))
- {
- using namespace std; // For memcpy.
- typename InternetProtocol::endpoint endpoint;
- endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen));
- memcpy(endpoint.data(), address_info->ai_addr,
- address_info->ai_addrlen);
- iter.values_->push_back(
- basic_resolver_entry<InternetProtocol>(endpoint,
- actual_host_name, service_name));
- }
- address_info = address_info->ai_next;
- }
-
- return iter;
}
- /// Create an iterator from an endpoint, host name and service name.
- static basic_resolver_iterator create(
- const typename InternetProtocol::endpoint& endpoint,
- const std::string& host_name, const std::string& service_name)
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move constructor.
+ basic_resolver_iterator(basic_resolver_iterator&& other)
+ : values_(BOOST_ASIO_MOVE_CAST(values_ptr_type)(other.values_)),
+ index_(other.index_)
{
- basic_resolver_iterator iter;
- iter.values_.reset(new values_type);
- iter.values_->push_back(
- basic_resolver_entry<InternetProtocol>(
- endpoint, host_name, service_name));
- return iter;
+ other.index_ = 0;
}
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
- /// Create an iterator from a sequence of endpoints, host and service name.
- template <typename EndpointIterator>
- static basic_resolver_iterator create(
- EndpointIterator begin, EndpointIterator end,
- const std::string& host_name, const std::string& service_name)
+ /// Assignment operator.
+ basic_resolver_iterator& operator=(const basic_resolver_iterator& other)
{
- basic_resolver_iterator iter;
- if (begin != end)
- {
- iter.values_.reset(new values_type);
- for (EndpointIterator ep_iter = begin; ep_iter != end; ++ep_iter)
- {
- iter.values_->push_back(
- basic_resolver_entry<InternetProtocol>(
- *ep_iter, host_name, service_name));
- }
- }
- return iter;
+ values_ = other.values_;
+ index_ = other.index_;
+ return *this;
}
-#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
- /// Create an iterator from a Windows Runtime list of EndpointPair objects.
- static basic_resolver_iterator create(
- Windows::Foundation::Collections::IVectorView<
- Windows::Networking::EndpointPair^>^ endpoints,
- const boost::asio::detail::addrinfo_type& hints,
- const std::string& host_name, const std::string& service_name)
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-assignment operator.
+ basic_resolver_iterator& operator=(basic_resolver_iterator&& other)
{
- basic_resolver_iterator iter;
- if (endpoints->Size)
+ if (this != &other)
{
- iter.values_.reset(new values_type);
- for (unsigned int i = 0; i < endpoints->Size; ++i)
- {
- auto pair = endpoints->GetAt(i);
-
- if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET)
- && pair->RemoteHostName->Type
- != Windows::Networking::HostNameType::Ipv4)
- continue;
-
- if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET6)
- && pair->RemoteHostName->Type
- != Windows::Networking::HostNameType::Ipv6)
- continue;
-
- iter.values_->push_back(
- basic_resolver_entry<InternetProtocol>(
- typename InternetProtocol::endpoint(
- ip::address::from_string(
- boost::asio::detail::winrt_utils::string(
- pair->RemoteHostName->CanonicalName)),
- boost::asio::detail::winrt_utils::integer(
- pair->RemoteServiceName)),
- host_name, service_name));
- }
+ values_ = BOOST_ASIO_MOVE_CAST(values_ptr_type)(other.values_);
+ index_ = other.index_;
+ other.index_ = 0;
}
- return iter;
+
+ return *this;
}
-#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Dereference an iterator.
const basic_resolver_entry<InternetProtocol>& operator*() const
@@ -223,7 +154,7 @@ public:
return !a.equal(b);
}
-private:
+protected:
void increment()
{
if (++index_ == values_->size())
@@ -249,7 +180,8 @@ private:
}
typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
- boost::asio::detail::shared_ptr<values_type> values_;
+ typedef boost::asio::detail::shared_ptr<values_type> values_ptr_type;
+ values_ptr_type values_;
std::size_t index_;
};
diff --git a/boost/asio/ip/basic_resolver_results.hpp b/boost/asio/ip/basic_resolver_results.hpp
new file mode 100644
index 0000000000..bd3248a1a9
--- /dev/null
+++ b/boost/asio/ip/basic_resolver_results.hpp
@@ -0,0 +1,313 @@
+//
+// ip/basic_resolver_results.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_BASIC_RESOLVER_RESULTS_HPP
+#define BOOST_ASIO_IP_BASIC_RESOLVER_RESULTS_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <cstddef>
+#include <cstring>
+#include <boost/asio/detail/socket_ops.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/ip/basic_resolver_iterator.hpp>
+
+#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+# include <boost/asio/detail/winrt_utils.hpp>
+#endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// A range of entries produced by a resolver.
+/**
+ * The boost::asio::ip::basic_resolver_results class template is used to define
+ * a range over the results returned by a resolver.
+ *
+ * The iterator's value_type, obtained when a results iterator is dereferenced,
+ * is: @code const basic_resolver_entry<InternetProtocol> @endcode
+ *
+ * @note For backward compatibility, basic_resolver_results is derived from
+ * basic_resolver_iterator. This derivation is deprecated.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+template <typename InternetProtocol>
+class basic_resolver_results
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ : public basic_resolver_iterator<InternetProtocol>
+#else // !defined(BOOST_ASIO_NO_DEPRECATED)
+ : private basic_resolver_iterator<InternetProtocol>
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+{
+public:
+ /// The protocol type associated with the results.
+ typedef InternetProtocol protocol_type;
+
+ /// The endpoint type associated with the results.
+ typedef typename protocol_type::endpoint endpoint_type;
+
+ /// The type of a value in the results range.
+ typedef basic_resolver_entry<endpoint_type> value_type;
+
+ /// The type of a const reference to a value in the range.
+ typedef const value_type& const_reference;
+
+ /// The type of a non-const reference to a value in the range.
+ typedef value_type& reference;
+
+ /// The type of an iterator into the range.
+ typedef basic_resolver_iterator<protocol_type> const_iterator;
+
+ /// The type of an iterator into the range.
+ typedef const_iterator iterator;
+
+ /// Type used to represent the distance between two iterators in the range.
+ typedef std::ptrdiff_t difference_type;
+
+ /// Type used to represent a count of the elements in the range.
+ typedef std::size_t size_type;
+
+ /// Default constructor creates an empty range.
+ basic_resolver_results()
+ {
+ }
+
+ /// Copy constructor.
+ basic_resolver_results(const basic_resolver_results& other)
+ : basic_resolver_iterator<InternetProtocol>(other)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move constructor.
+ basic_resolver_results(basic_resolver_results&& other)
+ : basic_resolver_iterator<InternetProtocol>(
+ BOOST_ASIO_MOVE_CAST(basic_resolver_results)(other))
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Assignment operator.
+ basic_resolver_results& operator=(const basic_resolver_results& other)
+ {
+ basic_resolver_iterator<InternetProtocol>::operator=(other);
+ return *this;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-assignment operator.
+ basic_resolver_results& operator=(basic_resolver_results&& other)
+ {
+ basic_resolver_iterator<InternetProtocol>::operator=(
+ BOOST_ASIO_MOVE_CAST(basic_resolver_results)(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+#if !defined(GENERATING_DOCUMENTATION)
+ // Create results from an addrinfo list returned by getaddrinfo.
+ static basic_resolver_results create(
+ boost::asio::detail::addrinfo_type* address_info,
+ const std::string& host_name, const std::string& service_name)
+ {
+ basic_resolver_results results;
+ if (!address_info)
+ return results;
+
+ std::string actual_host_name = host_name;
+ if (address_info->ai_canonname)
+ actual_host_name = address_info->ai_canonname;
+
+ results.values_.reset(new values_type);
+
+ while (address_info)
+ {
+ if (address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET)
+ || address_info->ai_family == BOOST_ASIO_OS_DEF(AF_INET6))
+ {
+ using namespace std; // For memcpy.
+ typename InternetProtocol::endpoint endpoint;
+ endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen));
+ memcpy(endpoint.data(), address_info->ai_addr,
+ address_info->ai_addrlen);
+ results.values_->push_back(
+ basic_resolver_entry<InternetProtocol>(endpoint,
+ actual_host_name, service_name));
+ }
+ address_info = address_info->ai_next;
+ }
+
+ return results;
+ }
+
+ // Create results from an endpoint, host name and service name.
+ static basic_resolver_results create(const endpoint_type& endpoint,
+ const std::string& host_name, const std::string& service_name)
+ {
+ basic_resolver_results results;
+ results.values_.reset(new values_type);
+ results.values_->push_back(
+ basic_resolver_entry<InternetProtocol>(
+ endpoint, host_name, service_name));
+ return results;
+ }
+
+ // Create results from a sequence of endpoints, host and service name.
+ template <typename EndpointIterator>
+ static basic_resolver_results create(
+ EndpointIterator begin, EndpointIterator end,
+ const std::string& host_name, const std::string& service_name)
+ {
+ basic_resolver_results results;
+ if (begin != end)
+ {
+ results.values_.reset(new values_type);
+ for (EndpointIterator ep_iter = begin; ep_iter != end; ++ep_iter)
+ {
+ results.values_->push_back(
+ basic_resolver_entry<InternetProtocol>(
+ *ep_iter, host_name, service_name));
+ }
+ }
+ return results;
+ }
+
+# if defined(BOOST_ASIO_WINDOWS_RUNTIME)
+ // Create results from a Windows Runtime list of EndpointPair objects.
+ static basic_resolver_results create(
+ Windows::Foundation::Collections::IVectorView<
+ Windows::Networking::EndpointPair^>^ endpoints,
+ const boost::asio::detail::addrinfo_type& hints,
+ const std::string& host_name, const std::string& service_name)
+ {
+ basic_resolver_results results;
+ if (endpoints->Size)
+ {
+ results.values_.reset(new values_type);
+ for (unsigned int i = 0; i < endpoints->Size; ++i)
+ {
+ auto pair = endpoints->GetAt(i);
+
+ if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET)
+ && pair->RemoteHostName->Type
+ != Windows::Networking::HostNameType::Ipv4)
+ continue;
+
+ if (hints.ai_family == BOOST_ASIO_OS_DEF(AF_INET6)
+ && pair->RemoteHostName->Type
+ != Windows::Networking::HostNameType::Ipv6)
+ continue;
+
+ results.values_->push_back(
+ basic_resolver_entry<InternetProtocol>(
+ typename InternetProtocol::endpoint(
+ ip::make_address(
+ boost::asio::detail::winrt_utils::string(
+ pair->RemoteHostName->CanonicalName)),
+ boost::asio::detail::winrt_utils::integer(
+ pair->RemoteServiceName)),
+ host_name, service_name));
+ }
+ }
+ return results;
+ }
+# endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+ /// Get the number of entries in the results range.
+ size_type size() const BOOST_ASIO_NOEXCEPT
+ {
+ return this->values_->size();
+ }
+
+ /// Get the maximum number of entries permitted in a results range.
+ size_type max_size() const BOOST_ASIO_NOEXCEPT
+ {
+ return this->values_->max_size();
+ }
+
+ /// Determine whether the results range is empty.
+ bool empty() const BOOST_ASIO_NOEXCEPT
+ {
+ return this->values_->empty();
+ }
+
+ /// Obtain a begin iterator for the results range.
+ const_iterator begin() const
+ {
+ basic_resolver_results tmp(*this);
+ tmp.index_ = 0;
+ return tmp;
+ }
+
+ /// Obtain an end iterator for the results range.
+ const_iterator end() const
+ {
+ return const_iterator();
+ }
+
+ /// Obtain a begin iterator for the results range.
+ const_iterator cbegin() const
+ {
+ return begin();
+ }
+
+ /// Obtain an end iterator for the results range.
+ const_iterator cend() const
+ {
+ return end();
+ }
+
+ /// Swap the results range with another.
+ void swap(basic_resolver_results& that) BOOST_ASIO_NOEXCEPT
+ {
+ if (this != &that)
+ {
+ this->values_.swap(that.values_);
+ std::size_t index = this->index_;
+ this->index_ = that.index_;
+ that.index_ = index;
+ }
+ }
+
+ /// Test two iterators for equality.
+ friend bool operator==(const basic_resolver_results& a,
+ const basic_resolver_results& b)
+ {
+ return a.equal(b);
+ }
+
+ /// Test two iterators for inequality.
+ friend bool operator!=(const basic_resolver_results& a,
+ const basic_resolver_results& b)
+ {
+ return !a.equal(b);
+ }
+
+private:
+ typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_BASIC_RESOLVER_RESULTS_HPP
diff --git a/boost/asio/ip/detail/endpoint.hpp b/boost/asio/ip/detail/endpoint.hpp
index 0a354e12a9..69a83a9e96 100644
--- a/boost/asio/ip/detail/endpoint.hpp
+++ b/boost/asio/ip/detail/endpoint.hpp
@@ -114,7 +114,7 @@ public:
#if !defined(BOOST_ASIO_NO_IOSTREAM)
// Convert to a string.
- BOOST_ASIO_DECL std::string to_string(boost::system::error_code& ec) const;
+ BOOST_ASIO_DECL std::string to_string() const;
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
private:
diff --git a/boost/asio/ip/detail/impl/endpoint.ipp b/boost/asio/ip/detail/impl/endpoint.ipp
index f1f9309af5..9908479327 100644
--- a/boost/asio/ip/detail/impl/endpoint.ipp
+++ b/boost/asio/ip/detail/impl/endpoint.ipp
@@ -81,8 +81,7 @@ endpoint::endpoint(const boost::asio::ip::address& addr,
boost::asio::detail::socket_ops::host_to_network_short(port_num);
data_.v4.sin_addr.s_addr =
boost::asio::detail::socket_ops::host_to_network_long(
- static_cast<boost::asio::detail::u_long_type>(
- addr.to_v4().to_ulong()));
+ addr.to_v4().to_uint());
}
else
{
@@ -178,18 +177,14 @@ bool operator<(const endpoint& e1, const endpoint& e2)
}
#if !defined(BOOST_ASIO_NO_IOSTREAM)
-std::string endpoint::to_string(boost::system::error_code& ec) const
+std::string endpoint::to_string() const
{
- std::string a = address().to_string(ec);
- if (ec)
- return std::string();
-
std::ostringstream tmp_os;
tmp_os.imbue(std::locale::classic());
if (is_v4())
- tmp_os << a;
+ tmp_os << address();
else
- tmp_os << '[' << a << ']';
+ tmp_os << '[' << address() << ']';
tmp_os << ':' << port();
return tmp_os.str();
diff --git a/boost/asio/ip/detail/socket_option.hpp b/boost/asio/ip/detail/socket_option.hpp
index e8849fda92..e246ca0ef5 100644
--- a/boost/asio/ip/detail/socket_option.hpp
+++ b/boost/asio/ip/detail/socket_option.hpp
@@ -392,15 +392,15 @@ public:
}
// Construct with multicast address only.
- explicit multicast_request(const boost::asio::ip::address& multicast_address)
+ explicit multicast_request(const address& multicast_address)
: ipv4_value_(), // Zero-initialisation gives the "any" address.
ipv6_value_() // Zero-initialisation gives the "any" address.
{
if (multicast_address.is_v6())
{
using namespace std; // For memcpy.
- boost::asio::ip::address_v6 ipv6_address = multicast_address.to_v6();
- boost::asio::ip::address_v6::bytes_type bytes = ipv6_address.to_bytes();
+ address_v6 ipv6_address = multicast_address.to_v6();
+ address_v6::bytes_type bytes = ipv6_address.to_bytes();
memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.data(), 16);
ipv6_value_.ipv6mr_interface = ipv6_address.scope_id();
}
@@ -408,37 +408,34 @@ public:
{
ipv4_value_.imr_multiaddr.s_addr =
boost::asio::detail::socket_ops::host_to_network_long(
- multicast_address.to_v4().to_ulong());
+ multicast_address.to_v4().to_uint());
ipv4_value_.imr_interface.s_addr =
boost::asio::detail::socket_ops::host_to_network_long(
- boost::asio::ip::address_v4::any().to_ulong());
+ address_v4::any().to_uint());
}
}
// Construct with multicast address and IPv4 address specifying an interface.
- explicit multicast_request(
- const boost::asio::ip::address_v4& multicast_address,
- const boost::asio::ip::address_v4& network_interface
- = boost::asio::ip::address_v4::any())
+ explicit multicast_request(const address_v4& multicast_address,
+ const address_v4& network_interface = address_v4::any())
: ipv6_value_() // Zero-initialisation gives the "any" address.
{
ipv4_value_.imr_multiaddr.s_addr =
boost::asio::detail::socket_ops::host_to_network_long(
- multicast_address.to_ulong());
+ multicast_address.to_uint());
ipv4_value_.imr_interface.s_addr =
boost::asio::detail::socket_ops::host_to_network_long(
- network_interface.to_ulong());
+ network_interface.to_uint());
}
// Construct with multicast address and IPv6 network interface index.
explicit multicast_request(
- const boost::asio::ip::address_v6& multicast_address,
+ const address_v6& multicast_address,
unsigned long network_interface = 0)
: ipv4_value_() // Zero-initialisation gives the "any" address.
{
using namespace std; // For memcpy.
- boost::asio::ip::address_v6::bytes_type bytes =
- multicast_address.to_bytes();
+ address_v6::bytes_type bytes = multicast_address.to_bytes();
memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.data(), 16);
if (network_interface)
ipv6_value_.ipv6mr_interface = network_interface;
@@ -497,16 +494,16 @@ public:
{
ipv4_value_.s_addr =
boost::asio::detail::socket_ops::host_to_network_long(
- boost::asio::ip::address_v4::any().to_ulong());
+ address_v4::any().to_uint());
ipv6_value_ = 0;
}
// Construct with IPv4 interface.
- explicit network_interface(const boost::asio::ip::address_v4& ipv4_interface)
+ explicit network_interface(const address_v4& ipv4_interface)
{
ipv4_value_.s_addr =
boost::asio::detail::socket_ops::host_to_network_long(
- ipv4_interface.to_ulong());
+ ipv4_interface.to_uint());
ipv6_value_ = 0;
}
@@ -515,7 +512,7 @@ public:
{
ipv4_value_.s_addr =
boost::asio::detail::socket_ops::host_to_network_long(
- boost::asio::ip::address_v4::any().to_ulong());
+ address_v4::any().to_uint());
ipv6_value_ = ipv6_interface;
}
diff --git a/boost/asio/ip/impl/address.hpp b/boost/asio/ip/impl/address.hpp
index e595d7063b..552cb5fd6d 100644
--- a/boost/asio/ip/impl/address.hpp
+++ b/boost/asio/ip/impl/address.hpp
@@ -25,23 +25,37 @@ namespace boost {
namespace asio {
namespace ip {
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+inline address address::from_string(const char* str)
+{
+ return boost::asio::ip::make_address(str);
+}
+
+inline address address::from_string(
+ const char* str, boost::system::error_code& ec)
+{
+ return boost::asio::ip::make_address(str, ec);
+}
+
+inline address address::from_string(const std::string& str)
+{
+ return boost::asio::ip::make_address(str);
+}
+
+inline address address::from_string(
+ const std::string& str, boost::system::error_code& ec)
+{
+ return boost::asio::ip::make_address(str, ec);
+}
+
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(
std::basic_ostream<Elem, Traits>& os, const address& addr)
{
- boost::system::error_code ec;
- std::string s = addr.to_string(ec);
- if (ec)
- {
- if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
- boost::asio::detail::throw_error(ec);
- else
- os.setstate(std::basic_ostream<Elem, Traits>::failbit);
- }
- else
- for (std::string::iterator i = s.begin(); i != s.end(); ++i)
- os << os.widen(*i);
- return os;
+ return os << addr.to_string().c_str();
}
} // namespace ip
diff --git a/boost/asio/ip/impl/address.ipp b/boost/asio/ip/impl/address.ipp
index 5eda3e9ecf..6c615592e5 100644
--- a/boost/asio/ip/impl/address.ipp
+++ b/boost/asio/ip/impl/address.ipp
@@ -21,6 +21,7 @@
#include <boost/asio/detail/throw_exception.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/ip/address.hpp>
+#include <boost/asio/ip/bad_address_cast.hpp>
#include <boost/system/system_error.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -100,11 +101,60 @@ address& address::operator=(const boost::asio::ip::address_v6& ipv6_address)
return *this;
}
+address make_address(const char* str)
+{
+ boost::system::error_code ec;
+ address addr = make_address(str, ec);
+ boost::asio::detail::throw_error(ec);
+ return addr;
+}
+
+address make_address(const char* str, boost::system::error_code& ec)
+{
+ boost::asio::ip::address_v6 ipv6_address =
+ boost::asio::ip::make_address_v6(str, ec);
+ if (!ec)
+ return address(ipv6_address);
+
+ boost::asio::ip::address_v4 ipv4_address =
+ boost::asio::ip::make_address_v4(str, ec);
+ if (!ec)
+ return address(ipv4_address);
+
+ return address();
+}
+
+address make_address(const std::string& str)
+{
+ return make_address(str.c_str());
+}
+
+address make_address(const std::string& str,
+ boost::system::error_code& ec)
+{
+ return make_address(str.c_str(), ec);
+}
+
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
+address make_address(string_view str)
+{
+ return make_address(static_cast<std::string>(str));
+}
+
+address make_address(string_view str,
+ boost::system::error_code& ec)
+{
+ return make_address(static_cast<std::string>(str), ec);
+}
+
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
boost::asio::ip::address_v4 address::to_v4() const
{
if (type_ != ipv4)
{
- std::bad_cast ex;
+ bad_address_cast ex;
boost::asio::detail::throw_exception(ex);
}
return ipv4_address_;
@@ -114,7 +164,7 @@ boost::asio::ip::address_v6 address::to_v6() const
{
if (type_ != ipv6)
{
- std::bad_cast ex;
+ bad_address_cast ex;
boost::asio::detail::throw_exception(ex);
}
return ipv6_address_;
@@ -127,56 +177,14 @@ std::string address::to_string() const
return ipv4_address_.to_string();
}
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
std::string address::to_string(boost::system::error_code& ec) const
{
if (type_ == ipv6)
return ipv6_address_.to_string(ec);
return ipv4_address_.to_string(ec);
}
-
-address address::from_string(const char* str)
-{
- boost::system::error_code ec;
- address addr = from_string(str, ec);
- boost::asio::detail::throw_error(ec);
- return addr;
-}
-
-address address::from_string(const char* str, boost::system::error_code& ec)
-{
- boost::asio::ip::address_v6 ipv6_address =
- boost::asio::ip::address_v6::from_string(str, ec);
- if (!ec)
- {
- address tmp;
- tmp.type_ = ipv6;
- tmp.ipv6_address_ = ipv6_address;
- return tmp;
- }
-
- boost::asio::ip::address_v4 ipv4_address =
- boost::asio::ip::address_v4::from_string(str, ec);
- if (!ec)
- {
- address tmp;
- tmp.type_ = ipv4;
- tmp.ipv4_address_ = ipv4_address;
- return tmp;
- }
-
- return address();
-}
-
-address address::from_string(const std::string& str)
-{
- return from_string(str.c_str());
-}
-
-address address::from_string(const std::string& str,
- boost::system::error_code& ec)
-{
- return from_string(str.c_str(), ec);
-}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
bool address::is_loopback() const
{
diff --git a/boost/asio/ip/impl/address_v4.hpp b/boost/asio/ip/impl/address_v4.hpp
index 028b69b676..a273f5e73e 100644
--- a/boost/asio/ip/impl/address_v4.hpp
+++ b/boost/asio/ip/impl/address_v4.hpp
@@ -25,23 +25,37 @@ namespace boost {
namespace asio {
namespace ip {
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+inline address_v4 address_v4::from_string(const char* str)
+{
+ return boost::asio::ip::make_address_v4(str);
+}
+
+inline address_v4 address_v4::from_string(
+ const char* str, boost::system::error_code& ec)
+{
+ return boost::asio::ip::make_address_v4(str, ec);
+}
+
+inline address_v4 address_v4::from_string(const std::string& str)
+{
+ return boost::asio::ip::make_address_v4(str);
+}
+
+inline address_v4 address_v4::from_string(
+ const std::string& str, boost::system::error_code& ec)
+{
+ return boost::asio::ip::make_address_v4(str, ec);
+}
+
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(
std::basic_ostream<Elem, Traits>& os, const address_v4& addr)
{
- boost::system::error_code ec;
- std::string s = addr.to_string(ec);
- if (ec)
- {
- if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
- boost::asio::detail::throw_error(ec);
- else
- os.setstate(std::basic_ostream<Elem, Traits>::failbit);
- }
- else
- for (std::string::iterator i = s.begin(); i != s.end(); ++i)
- os << os.widen(*i);
- return os;
+ return os << addr.to_string().c_str();
}
} // namespace ip
diff --git a/boost/asio/ip/impl/address_v4.ipp b/boost/asio/ip/impl/address_v4.ipp
index 440217bcb2..d6db61f80d 100644
--- a/boost/asio/ip/impl/address_v4.ipp
+++ b/boost/asio/ip/impl/address_v4.ipp
@@ -17,6 +17,7 @@
#include <boost/asio/detail/config.hpp>
#include <climits>
+#include <limits>
#include <stdexcept>
#include <boost/asio/error.hpp>
#include <boost/asio/detail/socket_ops.hpp>
@@ -45,15 +46,13 @@ address_v4::address_v4(const address_v4::bytes_type& bytes)
memcpy(&addr_.s_addr, bytes.data(), 4);
}
-address_v4::address_v4(unsigned long addr)
+address_v4::address_v4(address_v4::uint_type addr)
{
-#if ULONG_MAX > 0xFFFFFFFF
- if (addr > 0xFFFFFFFF)
+ if ((std::numeric_limits<uint_type>::max)() > 0xFFFFFFFF)
{
- std::out_of_range ex("address_v4 from unsigned long");
+ std::out_of_range ex("address_v4 from unsigned integer");
boost::asio::detail::throw_exception(ex);
}
-#endif // ULONG_MAX > 0xFFFFFFFF
addr_.s_addr = boost::asio::detail::socket_ops::host_to_network_long(
static_cast<boost::asio::detail::u_long_type>(addr));
@@ -71,19 +70,32 @@ address_v4::bytes_type address_v4::to_bytes() const
return bytes;
}
+address_v4::uint_type address_v4::to_uint() const
+{
+ return boost::asio::detail::socket_ops::network_to_host_long(addr_.s_addr);
+}
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
unsigned long address_v4::to_ulong() const
{
return boost::asio::detail::socket_ops::network_to_host_long(addr_.s_addr);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
std::string address_v4::to_string() const
{
boost::system::error_code ec;
- std::string addr = to_string(ec);
- boost::asio::detail::throw_error(ec);
+ char addr_str[boost::asio::detail::max_addr_v4_str_len];
+ const char* addr =
+ boost::asio::detail::socket_ops::inet_ntop(
+ BOOST_ASIO_OS_DEF(AF_INET), &addr_, addr_str,
+ boost::asio::detail::max_addr_v4_str_len, 0, ec);
+ if (addr == 0)
+ boost::asio::detail::throw_error(ec);
return addr;
}
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
std::string address_v4::to_string(boost::system::error_code& ec) const
{
char addr_str[boost::asio::detail::max_addr_v4_str_len];
@@ -95,69 +107,44 @@ std::string address_v4::to_string(boost::system::error_code& ec) const
return std::string();
return addr;
}
-
-address_v4 address_v4::from_string(const char* str)
-{
- boost::system::error_code ec;
- address_v4 addr = from_string(str, ec);
- boost::asio::detail::throw_error(ec);
- return addr;
-}
-
-address_v4 address_v4::from_string(
- const char* str, boost::system::error_code& ec)
-{
- address_v4 tmp;
- if (boost::asio::detail::socket_ops::inet_pton(
- BOOST_ASIO_OS_DEF(AF_INET), str, &tmp.addr_, 0, ec) <= 0)
- return address_v4();
- return tmp;
-}
-
-address_v4 address_v4::from_string(const std::string& str)
-{
- return from_string(str.c_str());
-}
-
-address_v4 address_v4::from_string(
- const std::string& str, boost::system::error_code& ec)
-{
- return from_string(str.c_str(), ec);
-}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
bool address_v4::is_loopback() const
{
- return (to_ulong() & 0xFF000000) == 0x7F000000;
+ return (to_uint() & 0xFF000000) == 0x7F000000;
}
bool address_v4::is_unspecified() const
{
- return to_ulong() == 0;
+ return to_uint() == 0;
}
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
bool address_v4::is_class_a() const
{
- return (to_ulong() & 0x80000000) == 0;
+ return (to_uint() & 0x80000000) == 0;
}
bool address_v4::is_class_b() const
{
- return (to_ulong() & 0xC0000000) == 0x80000000;
+ return (to_uint() & 0xC0000000) == 0x80000000;
}
bool address_v4::is_class_c() const
{
- return (to_ulong() & 0xE0000000) == 0xC0000000;
+ return (to_uint() & 0xE0000000) == 0xC0000000;
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
bool address_v4::is_multicast() const
{
- return (to_ulong() & 0xF0000000) == 0xE0000000;
+ return (to_uint() & 0xF0000000) == 0xE0000000;
}
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
address_v4 address_v4::broadcast(const address_v4& addr, const address_v4& mask)
{
- return address_v4(addr.to_ulong() | (mask.to_ulong() ^ 0xFFFFFFFF));
+ return address_v4(addr.to_uint() | (mask.to_uint() ^ 0xFFFFFFFF));
}
address_v4 address_v4::netmask(const address_v4& addr)
@@ -170,6 +157,51 @@ address_v4 address_v4::netmask(const address_v4& addr)
return address_v4(0xFFFFFF00);
return address_v4(0xFFFFFFFF);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+address_v4 make_address_v4(const char* str)
+{
+ boost::system::error_code ec;
+ address_v4 addr = make_address_v4(str, ec);
+ boost::asio::detail::throw_error(ec);
+ return addr;
+}
+
+address_v4 make_address_v4(
+ const char* str, boost::system::error_code& ec)
+{
+ address_v4::bytes_type bytes;
+ if (boost::asio::detail::socket_ops::inet_pton(
+ BOOST_ASIO_OS_DEF(AF_INET), str, &bytes, 0, ec) <= 0)
+ return address_v4();
+ return address_v4(bytes);
+}
+
+address_v4 make_address_v4(const std::string& str)
+{
+ return make_address_v4(str.c_str());
+}
+
+address_v4 make_address_v4(
+ const std::string& str, boost::system::error_code& ec)
+{
+ return make_address_v4(str.c_str(), ec);
+}
+
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
+address_v4 make_address_v4(string_view str)
+{
+ return make_address_v4(static_cast<std::string>(str));
+}
+
+address_v4 make_address_v4(string_view str,
+ boost::system::error_code& ec)
+{
+ return make_address_v4(static_cast<std::string>(str), ec);
+}
+
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
} // namespace ip
} // namespace asio
diff --git a/boost/asio/ip/impl/address_v6.hpp b/boost/asio/ip/impl/address_v6.hpp
index 4b88129c50..e1d9932d30 100644
--- a/boost/asio/ip/impl/address_v6.hpp
+++ b/boost/asio/ip/impl/address_v6.hpp
@@ -25,23 +25,37 @@ namespace boost {
namespace asio {
namespace ip {
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+
+inline address_v6 address_v6::from_string(const char* str)
+{
+ return boost::asio::ip::make_address_v6(str);
+}
+
+inline address_v6 address_v6::from_string(
+ const char* str, boost::system::error_code& ec)
+{
+ return boost::asio::ip::make_address_v6(str, ec);
+}
+
+inline address_v6 address_v6::from_string(const std::string& str)
+{
+ return boost::asio::ip::make_address_v6(str);
+}
+
+inline address_v6 address_v6::from_string(
+ const std::string& str, boost::system::error_code& ec)
+{
+ return boost::asio::ip::make_address_v6(str, ec);
+}
+
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
template <typename Elem, typename Traits>
std::basic_ostream<Elem, Traits>& operator<<(
std::basic_ostream<Elem, Traits>& os, const address_v6& addr)
{
- boost::system::error_code ec;
- std::string s = addr.to_string(ec);
- if (ec)
- {
- if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
- boost::asio::detail::throw_error(ec);
- else
- os.setstate(std::basic_ostream<Elem, Traits>::failbit);
- }
- else
- for (std::string::iterator i = s.begin(); i != s.end(); ++i)
- os << os.widen(*i);
- return os;
+ return os << addr.to_string().c_str();
}
} // namespace ip
diff --git a/boost/asio/ip/impl/address_v6.ipp b/boost/asio/ip/impl/address_v6.ipp
index 2d1a1974bf..1741bbcf79 100644
--- a/boost/asio/ip/impl/address_v6.ipp
+++ b/boost/asio/ip/impl/address_v6.ipp
@@ -24,6 +24,7 @@
#include <boost/asio/detail/throw_exception.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/ip/address_v6.hpp>
+#include <boost/asio/ip/bad_address_cast.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -101,11 +102,17 @@ address_v6::bytes_type address_v6::to_bytes() const
std::string address_v6::to_string() const
{
boost::system::error_code ec;
- std::string addr = to_string(ec);
- boost::asio::detail::throw_error(ec);
+ char addr_str[boost::asio::detail::max_addr_v6_str_len];
+ const char* addr =
+ boost::asio::detail::socket_ops::inet_ntop(
+ BOOST_ASIO_OS_DEF(AF_INET6), &addr_, addr_str,
+ boost::asio::detail::max_addr_v6_str_len, scope_id_, ec);
+ if (addr == 0)
+ boost::asio::detail::throw_error(ec);
return addr;
}
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
std::string address_v6::to_string(boost::system::error_code& ec) const
{
char addr_str[boost::asio::detail::max_addr_v6_str_len];
@@ -118,40 +125,11 @@ std::string address_v6::to_string(boost::system::error_code& ec) const
return addr;
}
-address_v6 address_v6::from_string(const char* str)
-{
- boost::system::error_code ec;
- address_v6 addr = from_string(str, ec);
- boost::asio::detail::throw_error(ec);
- return addr;
-}
-
-address_v6 address_v6::from_string(
- const char* str, boost::system::error_code& ec)
-{
- address_v6 tmp;
- if (boost::asio::detail::socket_ops::inet_pton(
- BOOST_ASIO_OS_DEF(AF_INET6), str, &tmp.addr_, &tmp.scope_id_, ec) <= 0)
- return address_v6();
- return tmp;
-}
-
-address_v6 address_v6::from_string(const std::string& str)
-{
- return from_string(str.c_str());
-}
-
-address_v6 address_v6::from_string(
- const std::string& str, boost::system::error_code& ec)
-{
- return from_string(str.c_str(), ec);
-}
-
address_v4 address_v6::to_v4() const
{
if (!is_v4_mapped() && !is_v4_compatible())
{
- std::bad_cast ex;
+ bad_address_cast ex;
boost::asio::detail::throw_exception(ex);
}
@@ -159,6 +137,7 @@ address_v4 address_v6::to_v4() const
addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } };
return address_v4(v4_bytes);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
bool address_v6::is_loopback() const
{
@@ -204,6 +183,7 @@ bool address_v6::is_v4_mapped() const
&& (addr_.s6_addr[10] == 0xff) && (addr_.s6_addr[11] == 0xff));
}
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
bool address_v6::is_v4_compatible() const
{
return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)
@@ -217,6 +197,7 @@ bool address_v6::is_v4_compatible() const
&& (addr_.s6_addr[14] == 0)
&& ((addr_.s6_addr[15] == 0) || (addr_.s6_addr[15] == 1))));
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
bool address_v6::is_multicast() const
{
@@ -275,6 +256,7 @@ address_v6 address_v6::loopback()
return tmp;
}
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
address_v6 address_v6::v4_mapped(const address_v4& addr)
{
address_v4::bytes_type v4_bytes = addr.to_bytes();
@@ -290,6 +272,76 @@ address_v6 address_v6::v4_compatible(const address_v4& addr)
v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
return address_v6(v6_bytes);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+address_v6 make_address_v6(const char* str)
+{
+ boost::system::error_code ec;
+ address_v6 addr = make_address_v6(str, ec);
+ boost::asio::detail::throw_error(ec);
+ return addr;
+}
+
+address_v6 make_address_v6(
+ const char* str, boost::system::error_code& ec)
+{
+ address_v6::bytes_type bytes;
+ unsigned long scope_id = 0;
+ if (boost::asio::detail::socket_ops::inet_pton(
+ BOOST_ASIO_OS_DEF(AF_INET6), str, &bytes[0], &scope_id, ec) <= 0)
+ return address_v6();
+ return address_v6(bytes, scope_id);
+}
+
+address_v6 make_address_v6(const std::string& str)
+{
+ return make_address_v6(str.c_str());
+}
+
+address_v6 make_address_v6(
+ const std::string& str, boost::system::error_code& ec)
+{
+ return make_address_v6(str.c_str(), ec);
+}
+
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
+address_v6 make_address_v6(string_view str)
+{
+ return make_address_v6(static_cast<std::string>(str));
+}
+
+address_v6 make_address_v6(string_view str,
+ boost::system::error_code& ec)
+{
+ return make_address_v6(static_cast<std::string>(str), ec);
+}
+
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
+address_v4 make_address_v4(
+ v4_mapped_t, const address_v6& v6_addr)
+{
+ if (!v6_addr.is_v4_mapped())
+ {
+ bad_address_cast ex;
+ boost::asio::detail::throw_exception(ex);
+ }
+
+ address_v6::bytes_type v6_bytes = v6_addr.to_bytes();
+ address_v4::bytes_type v4_bytes = { { v6_bytes[12],
+ v6_bytes[13], v6_bytes[14], v6_bytes[15] } };
+ return address_v4(v4_bytes);
+}
+
+address_v6 make_address_v6(
+ v4_mapped_t, const address_v4& v4_addr)
+{
+ address_v4::bytes_type v4_bytes = v4_addr.to_bytes();
+ address_v6::bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0xFF, 0xFF, v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };
+ return address_v6(v6_bytes);
+}
} // namespace ip
} // namespace asio
diff --git a/boost/asio/ip/impl/basic_endpoint.hpp b/boost/asio/ip/impl/basic_endpoint.hpp
index 4d9c4505c3..590e9748f3 100644
--- a/boost/asio/ip/impl/basic_endpoint.hpp
+++ b/boost/asio/ip/impl/basic_endpoint.hpp
@@ -31,19 +31,7 @@ std::basic_ostream<Elem, Traits>& operator<<(
const basic_endpoint<InternetProtocol>& endpoint)
{
boost::asio::ip::detail::endpoint tmp_ep(endpoint.address(), endpoint.port());
- boost::system::error_code ec;
- std::string s = tmp_ep.to_string(ec);
- if (ec)
- {
- if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
- boost::asio::detail::throw_error(ec);
- else
- os.setstate(std::basic_ostream<Elem, Traits>::failbit);
- }
- else
- for (std::string::iterator i = s.begin(); i != s.end(); ++i)
- os << os.widen(*i);
- return os;
+ return os << tmp_ep.to_string().c_str();
}
} // namespace ip
diff --git a/boost/asio/ip/impl/network_v4.hpp b/boost/asio/ip/impl/network_v4.hpp
new file mode 100644
index 0000000000..6d9ebaa184
--- /dev/null
+++ b/boost/asio/ip/impl/network_v4.hpp
@@ -0,0 +1,56 @@
+//
+// ip/impl/network_v4.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 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
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IP_IMPL_NETWORK_V4_HPP
+#define BOOST_ASIO_IP_IMPL_NETWORK_V4_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
+#include <boost/asio/detail/throw_error.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os, const network_v4& addr)
+{
+ boost::system::error_code ec;
+ std::string s = addr.to_string(ec);
+ if (ec)
+ {
+ if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
+ boost::asio::detail::throw_error(ec);
+ else
+ os.setstate(std::basic_ostream<Elem, Traits>::failbit);
+ }
+ else
+ for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+ os << os.widen(*i);
+ return os;
+}
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+
+#endif // BOOST_ASIO_IP_IMPL_NETWORK_V4_HPP
diff --git a/boost/asio/ip/impl/network_v4.ipp b/boost/asio/ip/impl/network_v4.ipp
new file mode 100644
index 0000000000..f59949d9f0
--- /dev/null
+++ b/boost/asio/ip/impl/network_v4.ipp
@@ -0,0 +1,217 @@
+//
+// ip/impl/network_v4.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 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
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IP_IMPL_NETWORK_V4_IPP
+#define BOOST_ASIO_IP_IMPL_NETWORK_V4_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <stdexcept>
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/throw_exception.hpp>
+#include <boost/asio/ip/network_v4.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+network_v4::network_v4(const address_v4& addr, unsigned short prefix_len)
+ : address_(addr),
+ prefix_length_(prefix_len)
+{
+ if (prefix_len > 32)
+ {
+ std::out_of_range ex("prefix length too large");
+ boost::asio::detail::throw_exception(ex);
+ }
+}
+
+network_v4::network_v4(const address_v4& addr, const address_v4& mask)
+ : address_(addr),
+ prefix_length_(0)
+{
+ address_v4::bytes_type mask_bytes = mask.to_bytes();
+ bool finished = false;
+ for (std::size_t i = 0; i < mask_bytes.size(); ++i)
+ {
+ if (finished)
+ {
+ if (mask_bytes[i])
+ {
+ std::invalid_argument ex("non-contiguous netmask");
+ boost::asio::detail::throw_exception(ex);
+ }
+ continue;
+ }
+ else
+ {
+ switch (mask_bytes[i])
+ {
+ case 255:
+ prefix_length_ += 8;
+ break;
+ case 254: // prefix_length_ += 7
+ prefix_length_ += 1;
+ case 252: // prefix_length_ += 6
+ prefix_length_ += 1;
+ case 248: // prefix_length_ += 5
+ prefix_length_ += 1;
+ case 240: // prefix_length_ += 4
+ prefix_length_ += 1;
+ case 224: // prefix_length_ += 3
+ prefix_length_ += 1;
+ case 192: // prefix_length_ += 2
+ prefix_length_ += 1;
+ case 128: // prefix_length_ += 1
+ prefix_length_ += 1;
+ case 0: // nbits += 0
+ finished = true;
+ break;
+ default:
+ std::out_of_range ex("non-contiguous netmask");
+ boost::asio::detail::throw_exception(ex);
+ }
+ }
+ }
+}
+
+address_v4 network_v4::netmask() const BOOST_ASIO_NOEXCEPT
+{
+ uint32_t nmbits = 0xffffffff;
+ if (prefix_length_ == 0)
+ nmbits = 0;
+ else
+ nmbits = nmbits << (32 - prefix_length_);
+ return address_v4(nmbits);
+}
+
+address_v4_range network_v4::hosts() const BOOST_ASIO_NOEXCEPT
+{
+ return is_host()
+ ? address_v4_range(address_, address_v4(address_.to_uint() + 1))
+ : address_v4_range(address_v4(network().to_uint() + 1), broadcast());
+}
+
+bool network_v4::is_subnet_of(const network_v4& other) const
+{
+ if (other.prefix_length_ >= prefix_length_)
+ return false; // Only real subsets are allowed.
+ const network_v4 me(address_, other.prefix_length_);
+ return other.canonical() == me.canonical();
+}
+
+std::string network_v4::to_string() const
+{
+ boost::system::error_code ec;
+ std::string addr = to_string(ec);
+ boost::asio::detail::throw_error(ec);
+ return addr;
+}
+
+std::string network_v4::to_string(boost::system::error_code& ec) const
+{
+ ec = boost::system::error_code();
+ char prefix_len[16];
+#if defined(BOOST_ASIO_HAS_SECURE_RTL)
+ sprintf_s(prefix_len, sizeof(prefix_len), "/%u", prefix_length_);
+#else // defined(BOOST_ASIO_HAS_SECURE_RTL)
+ sprintf(prefix_len, "/%u", prefix_length_);
+#endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
+ return address_.to_string() + prefix_len;
+}
+
+network_v4 make_network_v4(const char* str)
+{
+ return make_network_v4(std::string(str));
+}
+
+network_v4 make_network_v4(const char* str, boost::system::error_code& ec)
+{
+ return make_network_v4(std::string(str), ec);
+}
+
+network_v4 make_network_v4(const std::string& str)
+{
+ boost::system::error_code ec;
+ network_v4 net = make_network_v4(str, ec);
+ boost::asio::detail::throw_error(ec);
+ return net;
+}
+
+network_v4 make_network_v4(const std::string& str,
+ boost::system::error_code& ec)
+{
+ std::string::size_type pos = str.find_first_of("/");
+
+ if (pos == std::string::npos)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return network_v4();
+ }
+
+ if (pos == str.size() - 1)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return network_v4();
+ }
+
+ std::string::size_type end = str.find_first_not_of("0123456789", pos + 1);
+ if (end != std::string::npos)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return network_v4();
+ }
+
+ const address_v4 addr = make_address_v4(str.substr(0, pos), ec);
+ if (ec)
+ return network_v4();
+
+ const int prefix_len = std::atoi(str.substr(pos + 1).c_str());
+ if (prefix_len < 0 || prefix_len > 32)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return network_v4();
+ }
+
+ return network_v4(addr, static_cast<unsigned short>(prefix_len));
+}
+
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
+network_v4 make_network_v4(string_view str)
+{
+ return make_network_v4(static_cast<std::string>(str));
+}
+
+network_v4 make_network_v4(string_view str,
+ boost::system::error_code& ec)
+{
+ return make_network_v4(static_cast<std::string>(str), ec);
+}
+
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_IMPL_NETWORK_V4_IPP
diff --git a/boost/asio/ip/impl/network_v6.hpp b/boost/asio/ip/impl/network_v6.hpp
new file mode 100644
index 0000000000..c6bac2d2db
--- /dev/null
+++ b/boost/asio/ip/impl/network_v6.hpp
@@ -0,0 +1,55 @@
+//
+// ip/impl/network_v6.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_IMPL_NETWORK_V6_HPP
+#define BOOST_ASIO_IP_IMPL_NETWORK_V6_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
+#include <boost/asio/detail/throw_error.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os, const network_v6& addr)
+{
+ boost::system::error_code ec;
+ std::string s = addr.to_string(ec);
+ if (ec)
+ {
+ if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)
+ boost::asio::detail::throw_error(ec);
+ else
+ os.setstate(std::basic_ostream<Elem, Traits>::failbit);
+ }
+ else
+ for (std::string::iterator i = s.begin(); i != s.end(); ++i)
+ os << os.widen(*i);
+ return os;
+}
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+
+#endif // BOOST_ASIO_IP_IMPL_NETWORK_V6_HPP
diff --git a/boost/asio/ip/impl/network_v6.ipp b/boost/asio/ip/impl/network_v6.ipp
new file mode 100644
index 0000000000..2fb28a2fbc
--- /dev/null
+++ b/boost/asio/ip/impl/network_v6.ipp
@@ -0,0 +1,186 @@
+//
+// ip/impl/network_v6.ipp
+// ~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 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
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IP_IMPL_NETWORK_V6_IPP
+#define BOOST_ASIO_IP_IMPL_NETWORK_V6_IPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <stdexcept>
+#include <boost/asio/error.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/throw_exception.hpp>
+#include <boost/asio/ip/network_v6.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+network_v6::network_v6(const address_v6& addr, unsigned short prefix_len)
+ : address_(addr),
+ prefix_length_(prefix_len)
+{
+ if (prefix_len > 128)
+ {
+ std::out_of_range ex("prefix length too large");
+ boost::asio::detail::throw_exception(ex);
+ }
+}
+
+BOOST_ASIO_DECL address_v6 network_v6::network() const BOOST_ASIO_NOEXCEPT
+{
+ address_v6::bytes_type bytes(address_.to_bytes());
+ for (std::size_t i = 0; i < 16; ++i)
+ {
+ if (prefix_length_ <= i * 8)
+ bytes[i] = 0;
+ else if (prefix_length_ < (i + 1) * 8)
+ bytes[i] &= 0xFF00 >> (prefix_length_ % 8);
+ }
+ return address_v6(bytes, address_.scope_id());
+}
+
+address_v6_range network_v6::hosts() const BOOST_ASIO_NOEXCEPT
+{
+ address_v6::bytes_type begin_bytes(address_.to_bytes());
+ address_v6::bytes_type end_bytes(address_.to_bytes());
+ for (std::size_t i = 0; i < 16; ++i)
+ {
+ if (prefix_length_ <= i * 8)
+ {
+ begin_bytes[i] = 0;
+ end_bytes[i] = 0xFF;
+ }
+ else if (prefix_length_ < (i + 1) * 8)
+ {
+ begin_bytes[i] &= 0xFF00 >> (prefix_length_ % 8);
+ end_bytes[i] |= 0xFF >> (prefix_length_ % 8);
+ }
+ }
+ return address_v6_range(
+ address_v6_iterator(address_v6(begin_bytes, address_.scope_id())),
+ ++address_v6_iterator(address_v6(end_bytes, address_.scope_id())));
+}
+
+bool network_v6::is_subnet_of(const network_v6& other) const
+{
+ if (other.prefix_length_ >= prefix_length_)
+ return false; // Only real subsets are allowed.
+ const network_v6 me(address_, other.prefix_length_);
+ return other.canonical() == me.canonical();
+}
+
+std::string network_v6::to_string() const
+{
+ boost::system::error_code ec;
+ std::string addr = to_string(ec);
+ boost::asio::detail::throw_error(ec);
+ return addr;
+}
+
+std::string network_v6::to_string(boost::system::error_code& ec) const
+{
+ ec = boost::system::error_code();
+ char prefix_len[16];
+#if defined(BOOST_ASIO_HAS_SECURE_RTL)
+ sprintf_s(prefix_len, sizeof(prefix_len), "/%u", prefix_length_);
+#else // defined(BOOST_ASIO_HAS_SECURE_RTL)
+ sprintf(prefix_len, "/%u", prefix_length_);
+#endif // defined(BOOST_ASIO_HAS_SECURE_RTL)
+ return address_.to_string() + prefix_len;
+}
+
+network_v6 make_network_v6(const char* str)
+{
+ return make_network_v6(std::string(str));
+}
+
+network_v6 make_network_v6(const char* str, boost::system::error_code& ec)
+{
+ return make_network_v6(std::string(str), ec);
+}
+
+network_v6 make_network_v6(const std::string& str)
+{
+ boost::system::error_code ec;
+ network_v6 net = make_network_v6(str, ec);
+ boost::asio::detail::throw_error(ec);
+ return net;
+}
+
+network_v6 make_network_v6(const std::string& str,
+ boost::system::error_code& ec)
+{
+ std::string::size_type pos = str.find_first_of("/");
+
+ if (pos == std::string::npos)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return network_v6();
+ }
+
+ if (pos == str.size() - 1)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return network_v6();
+ }
+
+ std::string::size_type end = str.find_first_not_of("0123456789", pos + 1);
+ if (end != std::string::npos)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return network_v6();
+ }
+
+ const address_v6 addr = make_address_v6(str.substr(0, pos), ec);
+ if (ec)
+ return network_v6();
+
+ const int prefix_len = std::atoi(str.substr(pos + 1).c_str());
+ if (prefix_len < 0 || prefix_len > 128)
+ {
+ ec = boost::asio::error::invalid_argument;
+ return network_v6();
+ }
+
+ return network_v6(addr, static_cast<unsigned short>(prefix_len));
+}
+
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
+network_v6 make_network_v6(string_view str)
+{
+ return make_network_v6(static_cast<std::string>(str));
+}
+
+network_v6 make_network_v6(string_view str,
+ boost::system::error_code& ec)
+{
+ return make_network_v6(static_cast<std::string>(str), ec);
+}
+
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_IMPL_NETWORK_V6_IPP
diff --git a/boost/asio/ip/multicast.hpp b/boost/asio/ip/multicast.hpp
index d82e442116..86c6389096 100644
--- a/boost/asio/ip/multicast.hpp
+++ b/boost/asio/ip/multicast.hpp
@@ -33,7 +33,7 @@ namespace multicast {
* @par Examples
* Setting the option to join a multicast group:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::ip::address multicast_address =
* boost::asio::ip::address::from_string("225.0.0.1");
@@ -61,7 +61,7 @@ typedef boost::asio::ip::detail::socket_option::multicast_request<
* @par Examples
* Setting the option to leave a multicast group:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::ip::address multicast_address =
* boost::asio::ip::address::from_string("225.0.0.1");
@@ -89,7 +89,7 @@ typedef boost::asio::ip::detail::socket_option::multicast_request<
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::ip::address_v4 local_interface =
* boost::asio::ip::address_v4::from_string("1.2.3.4");
@@ -117,7 +117,7 @@ typedef boost::asio::ip::detail::socket_option::network_interface<
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::ip::multicast::hops option(4);
* socket.set_option(option);
@@ -126,7 +126,7 @@ typedef boost::asio::ip::detail::socket_option::network_interface<
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::ip::multicast::hops option;
* socket.get_option(option);
@@ -154,7 +154,7 @@ typedef boost::asio::ip::detail::socket_option::multicast_hops<
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::ip::multicast::enable_loopback option(true);
* socket.set_option(option);
@@ -163,7 +163,7 @@ typedef boost::asio::ip::detail::socket_option::multicast_hops<
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::ip::multicast::enable_loopback option;
* socket.get_option(option);
diff --git a/boost/asio/ip/network_v4.hpp b/boost/asio/ip/network_v4.hpp
new file mode 100644
index 0000000000..f0b8ecb164
--- /dev/null
+++ b/boost/asio/ip/network_v4.hpp
@@ -0,0 +1,263 @@
+//
+// ip/network_v4.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 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
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IP_NETWORK_V4_HPP
+#define BOOST_ASIO_IP_NETWORK_V4_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <string>
+#include <boost/asio/detail/string_view.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/asio/ip/address_v4_range.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Represents an IPv4 network.
+/**
+ * The boost::asio::ip::network_v4 class provides the ability to use and
+ * manipulate IP version 4 networks.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+class network_v4
+{
+public:
+ /// Default constructor.
+ network_v4() BOOST_ASIO_NOEXCEPT
+ : address_(),
+ prefix_length_(0)
+ {
+ }
+
+ /// Construct a network based on the specified address and prefix length.
+ BOOST_ASIO_DECL network_v4(const address_v4& addr,
+ unsigned short prefix_len);
+
+ /// Construct network based on the specified address and netmask.
+ BOOST_ASIO_DECL network_v4(const address_v4& addr,
+ const address_v4& mask);
+
+ /// Copy constructor.
+ network_v4(const network_v4& other) BOOST_ASIO_NOEXCEPT
+ : address_(other.address_),
+ prefix_length_(other.prefix_length_)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move constructor.
+ network_v4(network_v4&& other) BOOST_ASIO_NOEXCEPT
+ : address_(BOOST_ASIO_MOVE_CAST(address_v4)(other.address_)),
+ prefix_length_(other.prefix_length_)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Assign from another network.
+ network_v4& operator=(const network_v4& other) BOOST_ASIO_NOEXCEPT
+ {
+ address_ = other.address_;
+ prefix_length_ = other.prefix_length_;
+ return *this;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move-assign from another network.
+ network_v4& operator=(network_v4&& other) BOOST_ASIO_NOEXCEPT
+ {
+ address_ = BOOST_ASIO_MOVE_CAST(address_v4)(other.address_);
+ prefix_length_ = other.prefix_length_;
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Obtain the address object specified when the network object was created.
+ address_v4 address() const BOOST_ASIO_NOEXCEPT
+ {
+ return address_;
+ }
+
+ /// Obtain the prefix length that was specified when the network object was
+ /// created.
+ unsigned short prefix_length() const BOOST_ASIO_NOEXCEPT
+ {
+ return prefix_length_;
+ }
+
+ /// Obtain the netmask that was specified when the network object was created.
+ BOOST_ASIO_DECL address_v4 netmask() const BOOST_ASIO_NOEXCEPT;
+
+ /// Obtain an address object that represents the network address.
+ address_v4 network() const BOOST_ASIO_NOEXCEPT
+ {
+ return address_v4(address_.to_uint() & netmask().to_uint());
+ }
+
+ /// Obtain an address object that represents the network's broadcast address.
+ address_v4 broadcast() const BOOST_ASIO_NOEXCEPT
+ {
+ return address_v4(network().to_uint() | (netmask().to_uint() ^ 0xFFFFFFFF));
+ }
+
+ /// Obtain an address range corresponding to the hosts in the network.
+ BOOST_ASIO_DECL address_v4_range hosts() const BOOST_ASIO_NOEXCEPT;
+
+ /// Obtain the true network address, omitting any host bits.
+ network_v4 canonical() const BOOST_ASIO_NOEXCEPT
+ {
+ return network_v4(network(), netmask());
+ }
+
+ /// Test if network is a valid host address.
+ bool is_host() const BOOST_ASIO_NOEXCEPT
+ {
+ return prefix_length_ == 32;
+ }
+
+ /// Test if a network is a real subnet of another network.
+ BOOST_ASIO_DECL bool is_subnet_of(const network_v4& other) const;
+
+ /// Get the network as an address in dotted decimal format.
+ BOOST_ASIO_DECL std::string to_string() const;
+
+ /// Get the network as an address in dotted decimal format.
+ BOOST_ASIO_DECL std::string to_string(boost::system::error_code& ec) const;
+
+ /// Compare two networks for equality.
+ friend bool operator==(const network_v4& a, const network_v4& b)
+ {
+ return a.address_ == b.address_ && a.prefix_length_ == b.prefix_length_;
+ }
+
+ /// Compare two networks for inequality.
+ friend bool operator!=(const network_v4& a, const network_v4& b)
+ {
+ return !(a == b);
+ }
+
+private:
+ address_v4 address_;
+ unsigned short prefix_length_;
+};
+
+/// Create an IPv4 network from an address and prefix length.
+/**
+ * @relates address_v4
+ */
+inline network_v4 make_network_v4(
+ const address_v4& addr, unsigned short prefix_len)
+{
+ return network_v4(addr, prefix_len);
+}
+
+/// Create an IPv4 network from an address and netmask.
+/**
+ * @relates address_v4
+ */
+inline network_v4 make_network_v4(
+ const address_v4& addr, const address_v4& mask)
+{
+ return network_v4(addr, mask);
+}
+
+/// Create an IPv4 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v4
+ */
+BOOST_ASIO_DECL network_v4 make_network_v4(const char* str);
+
+/// Create an IPv4 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v4
+ */
+BOOST_ASIO_DECL network_v4 make_network_v4(
+ const char* str, boost::system::error_code& ec);
+
+/// Create an IPv4 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v4
+ */
+BOOST_ASIO_DECL network_v4 make_network_v4(const std::string& str);
+
+/// Create an IPv4 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v4
+ */
+BOOST_ASIO_DECL network_v4 make_network_v4(
+ const std::string& str, boost::system::error_code& ec);
+
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW) \
+ || defined(GENERATING_DOCUMENTATION)
+
+/// Create an IPv4 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v4
+ */
+BOOST_ASIO_DECL network_v4 make_network_v4(string_view str);
+
+/// Create an IPv4 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v4
+ */
+BOOST_ASIO_DECL network_v4 make_network_v4(
+ string_view str, boost::system::error_code& ec);
+
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
+/// Output a network as a string.
+/**
+ * Used to output a human-readable string for a specified network.
+ *
+ * @param os The output stream to which the string will be written.
+ *
+ * @param net The network to be written.
+ *
+ * @return The output stream.
+ *
+ * @relates boost::asio::ip::address_v4
+ */
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os, const network_v4& net);
+
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/ip/impl/network_v4.hpp>
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/ip/impl/network_v4.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_ASIO_IP_NETWORK_V4_HPP
diff --git a/boost/asio/ip/network_v6.hpp b/boost/asio/ip/network_v6.hpp
new file mode 100644
index 0000000000..83e67338e6
--- /dev/null
+++ b/boost/asio/ip/network_v6.hpp
@@ -0,0 +1,237 @@
+//
+// ip/network_v6.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 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
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef BOOST_ASIO_IP_NETWORK_V6_HPP
+#define BOOST_ASIO_IP_NETWORK_V6_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <string>
+#include <boost/asio/detail/string_view.hpp>
+#include <boost/system/error_code.hpp>
+#include <boost/asio/ip/address_v6_range.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// Represents an IPv6 network.
+/**
+ * The boost::asio::ip::network_v6 class provides the ability to use and
+ * manipulate IP version 6 networks.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+class network_v6
+{
+public:
+ /// Default constructor.
+ network_v6() BOOST_ASIO_NOEXCEPT
+ : address_(),
+ prefix_length_(0)
+ {
+ }
+
+ /// Construct a network based on the specified address and prefix length.
+ BOOST_ASIO_DECL network_v6(const address_v6& addr,
+ unsigned short prefix_len);
+
+ /// Copy constructor.
+ network_v6(const network_v6& other) BOOST_ASIO_NOEXCEPT
+ : address_(other.address_),
+ prefix_length_(other.prefix_length_)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move constructor.
+ network_v6(network_v6&& other) BOOST_ASIO_NOEXCEPT
+ : address_(BOOST_ASIO_MOVE_CAST(address_v6)(other.address_)),
+ prefix_length_(other.prefix_length_)
+ {
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Assign from another network.
+ network_v6& operator=(const network_v6& other) BOOST_ASIO_NOEXCEPT
+ {
+ address_ = other.address_;
+ prefix_length_ = other.prefix_length_;
+ return *this;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Move-assign from another network.
+ network_v6& operator=(network_v6&& other) BOOST_ASIO_NOEXCEPT
+ {
+ address_ = BOOST_ASIO_MOVE_CAST(address_v6)(other.address_);
+ prefix_length_ = other.prefix_length_;
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+ /// Obtain the address object specified when the network object was created.
+ address_v6 address() const BOOST_ASIO_NOEXCEPT
+ {
+ return address_;
+ }
+
+ /// Obtain the prefix length that was specified when the network object was
+ /// created.
+ unsigned short prefix_length() const BOOST_ASIO_NOEXCEPT
+ {
+ return prefix_length_;
+ }
+
+ /// Obtain an address object that represents the network address.
+ BOOST_ASIO_DECL address_v6 network() const BOOST_ASIO_NOEXCEPT;
+
+ /// Obtain an address range corresponding to the hosts in the network.
+ BOOST_ASIO_DECL address_v6_range hosts() const BOOST_ASIO_NOEXCEPT;
+
+ /// Obtain the true network address, omitting any host bits.
+ network_v6 canonical() const BOOST_ASIO_NOEXCEPT
+ {
+ return network_v6(network(), prefix_length());
+ }
+
+ /// Test if network is a valid host address.
+ bool is_host() const BOOST_ASIO_NOEXCEPT
+ {
+ return prefix_length_ == 128;
+ }
+
+ /// Test if a network is a real subnet of another network.
+ BOOST_ASIO_DECL bool is_subnet_of(const network_v6& other) const;
+
+ /// Get the network as an address in dotted decimal format.
+ BOOST_ASIO_DECL std::string to_string() const;
+
+ /// Get the network as an address in dotted decimal format.
+ BOOST_ASIO_DECL std::string to_string(boost::system::error_code& ec) const;
+
+ /// Compare two networks for equality.
+ friend bool operator==(const network_v6& a, const network_v6& b)
+ {
+ return a.address_ == b.address_ && a.prefix_length_ == b.prefix_length_;
+ }
+
+ /// Compare two networks for inequality.
+ friend bool operator!=(const network_v6& a, const network_v6& b)
+ {
+ return !(a == b);
+ }
+
+private:
+ address_v6 address_;
+ unsigned short prefix_length_;
+};
+
+/// Create an IPv6 network from an address and prefix length.
+/**
+ * @relates address_v6
+ */
+inline network_v6 make_network_v6(
+ const address_v6& addr, unsigned short prefix_len)
+{
+ return network_v6(addr, prefix_len);
+}
+
+/// Create an IPv6 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v6
+ */
+BOOST_ASIO_DECL network_v6 make_network_v6(const char* str);
+
+/// Create an IPv6 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v6
+ */
+BOOST_ASIO_DECL network_v6 make_network_v6(
+ const char* str, boost::system::error_code& ec);
+
+/// Create an IPv6 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v6
+ */
+BOOST_ASIO_DECL network_v6 make_network_v6(const std::string& str);
+
+/// Create an IPv6 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v6
+ */
+BOOST_ASIO_DECL network_v6 make_network_v6(
+ const std::string& str, boost::system::error_code& ec);
+
+#if defined(BOOST_ASIO_HAS_STD_STRING_VIEW) \
+ || defined(GENERATING_DOCUMENTATION)
+
+/// Create an IPv6 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v6
+ */
+BOOST_ASIO_DECL network_v6 make_network_v6(string_view str);
+
+/// Create an IPv6 network from a string containing IP address and prefix
+/// length.
+/**
+ * @relates network_v6
+ */
+BOOST_ASIO_DECL network_v6 make_network_v6(
+ string_view str, boost::system::error_code& ec);
+
+#endif // defined(BOOST_ASIO_HAS_STD_STRING_VIEW)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
+/// Output a network as a string.
+/**
+ * Used to output a human-readable string for a specified network.
+ *
+ * @param os The output stream to which the string will be written.
+ *
+ * @param net The network to be written.
+ *
+ * @return The output stream.
+ *
+ * @relates boost::asio::ip::address_v6
+ */
+template <typename Elem, typename Traits>
+std::basic_ostream<Elem, Traits>& operator<<(
+ std::basic_ostream<Elem, Traits>& os, const network_v6& net);
+
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/ip/impl/network_v6.hpp>
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/ip/impl/network_v6.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_ASIO_IP_NETWORK_V6_HPP
diff --git a/boost/asio/ip/resolver_base.hpp b/boost/asio/ip/resolver_base.hpp
new file mode 100644
index 0000000000..596a8221dc
--- /dev/null
+++ b/boost/asio/ip/resolver_base.hpp
@@ -0,0 +1,131 @@
+//
+// ip/resolver_base.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IP_RESOLVER_BASE_HPP
+#define BOOST_ASIO_IP_RESOLVER_BASE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/socket_types.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace ip {
+
+/// The resolver_base class is used as a base for the basic_resolver class
+/// templates to provide a common place to define the flag constants.
+class resolver_base
+{
+public:
+#if defined(GENERATING_DOCUMENTATION)
+ /// A bitmask type (C++ Std [lib.bitmask.types]).
+ typedef unspecified flags;
+
+ /// Determine the canonical name of the host specified in the query.
+ static const flags canonical_name = implementation_defined;
+
+ /// Indicate that returned endpoint is intended for use as a locally bound
+ /// socket endpoint.
+ static const flags passive = implementation_defined;
+
+ /// Host name should be treated as a numeric string defining an IPv4 or IPv6
+ /// address and no name resolution should be attempted.
+ static const flags numeric_host = implementation_defined;
+
+ /// Service name should be treated as a numeric string defining a port number
+ /// and no name resolution should be attempted.
+ static const flags numeric_service = implementation_defined;
+
+ /// If the query protocol family is specified as IPv6, return IPv4-mapped
+ /// IPv6 addresses on finding no IPv6 addresses.
+ static const flags v4_mapped = implementation_defined;
+
+ /// If used with v4_mapped, return all matching IPv6 and IPv4 addresses.
+ static const flags all_matching = implementation_defined;
+
+ /// Only return IPv4 addresses if a non-loopback IPv4 address is configured
+ /// for the system. Only return IPv6 addresses if a non-loopback IPv6 address
+ /// is configured for the system.
+ static const flags address_configured = implementation_defined;
+#else
+ enum flags
+ {
+ canonical_name = BOOST_ASIO_OS_DEF(AI_CANONNAME),
+ passive = BOOST_ASIO_OS_DEF(AI_PASSIVE),
+ numeric_host = BOOST_ASIO_OS_DEF(AI_NUMERICHOST),
+ numeric_service = BOOST_ASIO_OS_DEF(AI_NUMERICSERV),
+ v4_mapped = BOOST_ASIO_OS_DEF(AI_V4MAPPED),
+ all_matching = BOOST_ASIO_OS_DEF(AI_ALL),
+ address_configured = BOOST_ASIO_OS_DEF(AI_ADDRCONFIG)
+ };
+
+ // 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
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ ~resolver_base()
+ {
+ }
+};
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IP_RESOLVER_BASE_HPP
diff --git a/boost/asio/ip/resolver_query_base.hpp b/boost/asio/ip/resolver_query_base.hpp
index fd74059772..99d6e29f39 100644
--- a/boost/asio/ip/resolver_query_base.hpp
+++ b/boost/asio/ip/resolver_query_base.hpp
@@ -16,7 +16,7 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/detail/socket_types.hpp>
+#include <boost/asio/ip/resolver_base.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -27,95 +27,8 @@ namespace ip {
/// The resolver_query_base class is used as a base for the
/// basic_resolver_query class templates to provide a common place to define
/// the flag constants.
-class resolver_query_base
+class resolver_query_base : public resolver_base
{
-public:
-#if defined(GENERATING_DOCUMENTATION)
- /// A bitmask type (C++ Std [lib.bitmask.types]).
- typedef unspecified flags;
-
- /// Determine the canonical name of the host specified in the query.
- static const flags canonical_name = implementation_defined;
-
- /// Indicate that returned endpoint is intended for use as a locally bound
- /// socket endpoint.
- static const flags passive = implementation_defined;
-
- /// Host name should be treated as a numeric string defining an IPv4 or IPv6
- /// address and no name resolution should be attempted.
- static const flags numeric_host = implementation_defined;
-
- /// Service name should be treated as a numeric string defining a port number
- /// and no name resolution should be attempted.
- static const flags numeric_service = implementation_defined;
-
- /// If the query protocol family is specified as IPv6, return IPv4-mapped
- /// IPv6 addresses on finding no IPv6 addresses.
- static const flags v4_mapped = implementation_defined;
-
- /// If used with v4_mapped, return all matching IPv6 and IPv4 addresses.
- static const flags all_matching = implementation_defined;
-
- /// Only return IPv4 addresses if a non-loopback IPv4 address is configured
- /// for the system. Only return IPv6 addresses if a non-loopback IPv6 address
- /// is configured for the system.
- static const flags address_configured = implementation_defined;
-#else
- enum flags
- {
- canonical_name = BOOST_ASIO_OS_DEF(AI_CANONNAME),
- passive = BOOST_ASIO_OS_DEF(AI_PASSIVE),
- numeric_host = BOOST_ASIO_OS_DEF(AI_NUMERICHOST),
- numeric_service = BOOST_ASIO_OS_DEF(AI_NUMERICSERV),
- v4_mapped = BOOST_ASIO_OS_DEF(AI_V4MAPPED),
- all_matching = BOOST_ASIO_OS_DEF(AI_ALL),
- address_configured = BOOST_ASIO_OS_DEF(AI_ADDRCONFIG)
- };
-
- // 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
-
protected:
/// Protected destructor to prevent deletion through this type.
~resolver_query_base()
diff --git a/boost/asio/ip/resolver_service.hpp b/boost/asio/ip/resolver_service.hpp
index b4aa4d25bb..83ad490348 100644
--- a/boost/asio/ip/resolver_service.hpp
+++ b/boost/asio/ip/resolver_service.hpp
@@ -16,11 +16,15 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <boost/asio/async_result.hpp>
#include <boost/system/error_code.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/basic_resolver_iterator.hpp>
#include <boost/asio/ip/basic_resolver_query.hpp>
+#include <boost/asio/ip/basic_resolver_results.hpp>
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
# include <boost/asio/detail/winrt_resolver_service.hpp>
@@ -38,7 +42,7 @@ namespace ip {
template <typename InternetProtocol>
class resolver_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<
resolver_service<InternetProtocol> >
@@ -47,7 +51,7 @@ class resolver_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
/// The protocol type.
@@ -62,6 +66,9 @@ public:
/// The iterator type.
typedef basic_resolver_iterator<InternetProtocol> iterator_type;
+ /// The results type.
+ typedef basic_resolver_results<InternetProtocol> results_type;
+
private:
// The type of the platform-specific implementation.
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
@@ -80,11 +87,11 @@ public:
typedef typename service_impl_type::implementation_type implementation_type;
#endif
- /// Construct a new resolver service for the specified io_service.
- explicit resolver_service(boost::asio::io_service& io_service)
+ /// Construct a new resolver service for the specified io_context.
+ explicit resolver_service(boost::asio::io_context& io_context)
: boost::asio::detail::service_base<
- resolver_service<InternetProtocol> >(io_service),
- service_impl_(io_service)
+ resolver_service<InternetProtocol> >(io_context),
+ service_impl_(io_context)
{
}
@@ -94,6 +101,23 @@ public:
service_impl_.construct(impl);
}
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a new resolver implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_construct(impl, other_impl);
+ }
+
+ /// Move-assign from another resolver implementation.
+ void move_assign(implementation_type& impl,
+ resolver_service& other_service,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
/// Destroy a resolver implementation.
void destroy(implementation_type& impl)
{
@@ -107,7 +131,7 @@ public:
}
/// Resolve a query to a list of entries.
- iterator_type resolve(implementation_type& impl, const query_type& query,
+ results_type resolve(implementation_type& impl, const query_type& query,
boost::system::error_code& ec)
{
return service_impl_.resolve(impl, query, ec);
@@ -116,21 +140,20 @@ public:
/// Asynchronously resolve a query to a list of entries.
template <typename ResolveHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ResolveHandler,
- void (boost::system::error_code, iterator_type))
+ void (boost::system::error_code, results_type))
async_resolve(implementation_type& impl, const query_type& query,
BOOST_ASIO_MOVE_ARG(ResolveHandler) handler)
{
- boost::asio::detail::async_result_init<
- ResolveHandler, void (boost::system::error_code, iterator_type)> init(
- BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler));
+ boost::asio::async_completion<ResolveHandler,
+ void (boost::system::error_code, results_type)> init(handler);
- service_impl_.async_resolve(impl, query, init.handler);
+ service_impl_.async_resolve(impl, query, init.completion_handler);
return init.result.get();
}
/// Resolve an endpoint to a list of entries.
- iterator_type resolve(implementation_type& impl,
+ results_type resolve(implementation_type& impl,
const endpoint_type& endpoint, boost::system::error_code& ec)
{
return service_impl_.resolve(impl, endpoint, ec);
@@ -139,30 +162,29 @@ public:
/// Asynchronously resolve an endpoint to a list of entries.
template <typename ResolveHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ResolveHandler,
- void (boost::system::error_code, iterator_type))
+ void (boost::system::error_code, results_type))
async_resolve(implementation_type& impl, const endpoint_type& endpoint,
BOOST_ASIO_MOVE_ARG(ResolveHandler) handler)
{
- boost::asio::detail::async_result_init<
- ResolveHandler, void (boost::system::error_code, iterator_type)> init(
- BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler));
+ boost::asio::async_completion<ResolveHandler,
+ void (boost::system::error_code, results_type)> init(handler);
- service_impl_.async_resolve(impl, endpoint, init.handler);
+ service_impl_.async_resolve(impl, endpoint, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// Perform any fork-related housekeeping.
- void fork_service(boost::asio::io_service::fork_event event)
+ void notify_fork(boost::asio::io_context::fork_event event)
{
- service_impl_.fork_service(event);
+ service_impl_.notify_fork(event);
}
// The platform-specific implementation.
@@ -175,4 +197,6 @@ private:
#include <boost/asio/detail/pop_options.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_IP_RESOLVER_SERVICE_HPP
diff --git a/boost/asio/ip/tcp.hpp b/boost/asio/ip/tcp.hpp
index 079ec46a25..d6bb59644b 100644
--- a/boost/asio/ip/tcp.hpp
+++ b/boost/asio/ip/tcp.hpp
@@ -100,7 +100,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::tcp::no_delay option(true);
* socket.set_option(option);
@@ -109,7 +109,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::tcp::no_delay option;
* socket.get_option(option);
diff --git a/boost/asio/ip/unicast.hpp b/boost/asio/ip/unicast.hpp
index 4a9df8bfd2..809bcacc85 100644
--- a/boost/asio/ip/unicast.hpp
+++ b/boost/asio/ip/unicast.hpp
@@ -33,7 +33,7 @@ namespace unicast {
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::ip::unicast::hops option(4);
* socket.set_option(option);
@@ -42,7 +42,7 @@ namespace unicast {
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::ip::unicast::hops option;
* socket.get_option(option);
diff --git a/boost/asio/ip/v6_only.hpp b/boost/asio/ip/v6_only.hpp
index b22c9a5db8..5dc6ff0874 100644
--- a/boost/asio/ip/v6_only.hpp
+++ b/boost/asio/ip/v6_only.hpp
@@ -32,7 +32,7 @@ namespace ip {
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::v6_only option(true);
* socket.set_option(option);
@@ -41,7 +41,7 @@ namespace ip {
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::ip::v6_only option;
* socket.get_option(option);
diff --git a/boost/asio/is_executor.hpp b/boost/asio/is_executor.hpp
new file mode 100644
index 0000000000..4983c5385c
--- /dev/null
+++ b/boost/asio/is_executor.hpp
@@ -0,0 +1,48 @@
+//
+// is_executor.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_IS_EXECUTOR_HPP
+#define BOOST_ASIO_IS_EXECUTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/is_executor.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// The is_executor trait detects whether a type T meets the Executor type
+/// requirements.
+/**
+ * Class template @c is_executor is a UnaryTypeTrait that is derived from @c
+ * true_type if the type @c T meets the syntactic requirements for Executor,
+ * otherwise @c false_type.
+ */
+template <typename T>
+struct is_executor
+#if defined(GENERATING_DOCUMENTATION)
+ : integral_constant<bool, automatically_determined>
+#else // defined(GENERATING_DOCUMENTATION)
+ : boost::asio::detail::is_executor<T>
+#endif // defined(GENERATING_DOCUMENTATION)
+{
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_IS_EXECUTOR_HPP
diff --git a/boost/asio/local/connect_pair.hpp b/boost/asio/local/connect_pair.hpp
index 333c758783..18417856c7 100644
--- a/boost/asio/local/connect_pair.hpp
+++ b/boost/asio/local/connect_pair.hpp
@@ -33,32 +33,32 @@ namespace asio {
namespace local {
/// Create a pair of connected sockets.
-template <typename Protocol, typename SocketService1, typename SocketService2>
+template <typename Protocol BOOST_ASIO_SVC_TPARAM BOOST_ASIO_SVC_TPARAM1>
void connect_pair(
- basic_socket<Protocol, SocketService1>& socket1,
- basic_socket<Protocol, SocketService2>& socket2);
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket1,
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG1>& socket2);
/// Create a pair of connected sockets.
-template <typename Protocol, typename SocketService1, typename SocketService2>
-boost::system::error_code connect_pair(
- basic_socket<Protocol, SocketService1>& socket1,
- basic_socket<Protocol, SocketService2>& socket2,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM BOOST_ASIO_SVC_TPARAM1>
+BOOST_ASIO_SYNC_OP_VOID connect_pair(
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket1,
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG1>& socket2,
boost::system::error_code& ec);
-template <typename Protocol, typename SocketService1, typename SocketService2>
+template <typename Protocol BOOST_ASIO_SVC_TPARAM BOOST_ASIO_SVC_TPARAM1>
inline void connect_pair(
- basic_socket<Protocol, SocketService1>& socket1,
- basic_socket<Protocol, SocketService2>& socket2)
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket1,
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG1>& socket2)
{
boost::system::error_code ec;
connect_pair(socket1, socket2, ec);
boost::asio::detail::throw_error(ec, "connect_pair");
}
-template <typename Protocol, typename SocketService1, typename SocketService2>
-inline boost::system::error_code connect_pair(
- basic_socket<Protocol, SocketService1>& socket1,
- basic_socket<Protocol, SocketService2>& socket2,
+template <typename Protocol BOOST_ASIO_SVC_TPARAM BOOST_ASIO_SVC_TPARAM1>
+inline BOOST_ASIO_SYNC_OP_VOID connect_pair(
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG>& socket1,
+ basic_socket<Protocol BOOST_ASIO_SVC_TARG1>& socket2,
boost::system::error_code& ec)
{
// Check that this function is only being used with a UNIX domain socket.
@@ -71,27 +71,29 @@ inline boost::system::error_code connect_pair(
if (boost::asio::detail::socket_ops::socketpair(protocol.family(),
protocol.type(), protocol.protocol(), sv, ec)
== boost::asio::detail::socket_error_retval)
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
- if (socket1.assign(protocol, sv[0], ec))
+ socket1.assign(protocol, sv[0], ec);
+ if (ec)
{
boost::system::error_code temp_ec;
boost::asio::detail::socket_ops::state_type state[2] = { 0, 0 };
boost::asio::detail::socket_ops::close(sv[0], state[0], true, temp_ec);
boost::asio::detail::socket_ops::close(sv[1], state[1], true, temp_ec);
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
- if (socket2.assign(protocol, sv[1], ec))
+ socket2.assign(protocol, sv[1], ec);
+ if (ec)
{
boost::system::error_code temp_ec;
socket1.close(temp_ec);
boost::asio::detail::socket_ops::state_type state = 0;
boost::asio::detail::socket_ops::close(sv[1], state, true, temp_ec);
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
} // namespace local
diff --git a/boost/asio/local/detail/impl/endpoint.ipp b/boost/asio/local/detail/impl/endpoint.ipp
index 4173a8242e..d668e8badc 100644
--- a/boost/asio/local/detail/impl/endpoint.ipp
+++ b/boost/asio/local/detail/impl/endpoint.ipp
@@ -109,7 +109,8 @@ void endpoint::init(const char* path_name, std::size_t path_length)
using namespace std; // For memcpy.
data_.local = boost::asio::detail::sockaddr_un_type();
data_.local.sun_family = AF_UNIX;
- memcpy(data_.local.sun_path, path_name, path_length);
+ 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
diff --git a/boost/asio/packaged_task.hpp b/boost/asio/packaged_task.hpp
new file mode 100644
index 0000000000..586de13b7b
--- /dev/null
+++ b/boost/asio/packaged_task.hpp
@@ -0,0 +1,128 @@
+//
+// packaged_task.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_PACKAGED_TASK_HPP
+#define BOOST_ASIO_PACKAGED_TASK_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_STD_FUTURE) \
+ || defined(GENERATING_DOCUMENTATION)
+
+#include <future>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/detail/variadic_templates.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+#if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES) \
+ || defined(GENERATING_DOCUMENTATION)
+
+/// Partial specialisation of @c async_result for @c std::packaged_task.
+template <typename Result, typename... Args, typename Signature>
+class async_result<std::packaged_task<Result(Args...)>, Signature>
+{
+public:
+ /// The packaged task is the concrete completion handler type.
+ typedef std::packaged_task<Result(Args...)> completion_handler_type;
+
+ /// The return type of the initiating function is the future obtained from
+ /// the packaged task.
+ typedef std::future<Result> return_type;
+
+ /// The constructor extracts the future from the packaged task.
+ explicit async_result(completion_handler_type& h)
+ : future_(h.get_future())
+ {
+ }
+
+ /// Returns the packaged task's future.
+ return_type get()
+ {
+ return std::move(future_);
+ }
+
+private:
+ return_type future_;
+};
+
+#else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+ // || defined(GENERATING_DOCUMENTATION)
+
+template <typename Result, typename Signature>
+struct async_result<std::packaged_task<Result()>, Signature>
+{
+ typedef std::packaged_task<Result()> completion_handler_type;
+ typedef std::future<Result> return_type;
+
+ explicit async_result(completion_handler_type& h)
+ : future_(h.get_future())
+ {
+ }
+
+ return_type get()
+ {
+ return std::move(future_);
+ }
+
+private:
+ return_type future_;
+};
+
+#define BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \
+ template <typename Result, \
+ BOOST_ASIO_VARIADIC_TPARAMS(n), typename Signature> \
+ class async_result< \
+ std::packaged_task<Result(BOOST_ASIO_VARIADIC_TARGS(n))>, Signature> \
+ { \
+ public: \
+ typedef std::packaged_task< \
+ Result(BOOST_ASIO_VARIADIC_TARGS(n))> \
+ completion_handler_type; \
+ \
+ typedef std::future<Result> return_type; \
+ \
+ explicit async_result(completion_handler_type& h) \
+ : future_(h.get_future()) \
+ { \
+ } \
+ \
+ return_type get() \
+ { \
+ return std::move(future_); \
+ } \
+ \
+ private: \
+ return_type future_; \
+ }; \
+ /**/
+ BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF)
+#undef BOOST_ASIO_PRIVATE_ASYNC_RESULT_DEF
+
+#endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
+ // || defined(GENERATING_DOCUMENTATION)
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // defined(BOOST_ASIO_HAS_STD_FUTURE)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#endif // BOOST_ASIO_PACKAGED_TASK_HPP
diff --git a/boost/asio/placeholders.hpp b/boost/asio/placeholders.hpp
index 8714e3454a..0bc72769a1 100644
--- a/boost/asio/placeholders.hpp
+++ b/boost/asio/placeholders.hpp
@@ -41,10 +41,20 @@ unspecified bytes_transferred;
/// An argument placeholder, for use with boost::bind(), that corresponds to
/// the iterator argument of a handler for asynchronous functions such as
-/// boost::asio::basic_resolver::async_resolve.
+/// boost::asio::async_connect.
unspecified iterator;
/// An argument placeholder, for use with boost::bind(), that corresponds to
+/// the results argument of a handler for asynchronous functions such as
+/// boost::asio::basic_resolver::async_resolve.
+unspecified results;
+
+/// An argument placeholder, for use with boost::bind(), that corresponds to
+/// the results argument of a handler for asynchronous functions such as
+/// boost::asio::async_connect.
+unspecified endpoint;
+
+/// An argument placeholder, for use with boost::bind(), that corresponds to
/// the signal_number argument of a handler for asynchronous functions such as
/// boost::asio::signal_set::async_wait.
unspecified signal_number;
@@ -67,6 +77,16 @@ inline boost::arg<2> iterator()
return boost::arg<2>();
}
+inline boost::arg<2> results()
+{
+ return boost::arg<2>();
+}
+
+inline boost::arg<2> endpoint()
+{
+ return boost::arg<2>();
+}
+
inline boost::arg<2> signal_number()
{
return boost::arg<2>();
@@ -95,6 +115,10 @@ static boost::arg<2>& bytes_transferred
= boost::asio::placeholders::detail::placeholder<2>::get();
static boost::arg<2>& iterator
= boost::asio::placeholders::detail::placeholder<2>::get();
+static boost::arg<2>& results
+ = boost::asio::placeholders::detail::placeholder<2>::get();
+static boost::arg<2>& endpoint
+ = boost::asio::placeholders::detail::placeholder<2>::get();
static boost::arg<2>& signal_number
= boost::asio::placeholders::detail::placeholder<2>::get();
@@ -108,6 +132,10 @@ namespace
= boost::asio::placeholders::detail::placeholder<2>::get();
boost::arg<2>& iterator
= boost::asio::placeholders::detail::placeholder<2>::get();
+ boost::arg<2>& results
+ = boost::asio::placeholders::detail::placeholder<2>::get();
+ boost::arg<2>& endpoint
+ = boost::asio::placeholders::detail::placeholder<2>::get();
boost::arg<2>& signal_number
= boost::asio::placeholders::detail::placeholder<2>::get();
} // namespace
diff --git a/boost/asio/posix/basic_descriptor.hpp b/boost/asio/posix/basic_descriptor.hpp
index a857c237a3..2bb8a04efa 100644
--- a/boost/asio/posix/basic_descriptor.hpp
+++ b/boost/asio/posix/basic_descriptor.hpp
@@ -17,6 +17,8 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
|| defined(GENERATING_DOCUMENTATION)
@@ -46,10 +48,6 @@ class basic_descriptor
public descriptor_base
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// descriptor.
- typedef typename DescriptorService::native_handle_type native_type;
-
/// The native representation of a descriptor.
typedef typename DescriptorService::native_handle_type native_handle_type;
@@ -60,12 +58,12 @@ public:
/**
* This constructor creates a descriptor without opening it.
*
- * @param io_service The io_service object that the descriptor will use to
+ * @param io_context The io_context object that the descriptor will use to
* dispatch handlers for any asynchronous operations performed on the
* descriptor.
*/
- explicit basic_descriptor(boost::asio::io_service& io_service)
- : basic_io_object<DescriptorService>(io_service)
+ explicit basic_descriptor(boost::asio::io_context& io_context)
+ : basic_io_object<DescriptorService>(io_context)
{
}
@@ -74,7 +72,7 @@ public:
* This constructor creates a descriptor object to hold an existing native
* descriptor.
*
- * @param io_service The io_service object that the descriptor will use to
+ * @param io_context The io_context object that the descriptor will use to
* dispatch handlers for any asynchronous operations performed on the
* descriptor.
*
@@ -82,9 +80,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_descriptor(boost::asio::io_service& io_service,
+ basic_descriptor(boost::asio::io_context& io_context,
const native_handle_type& native_descriptor)
- : basic_io_object<DescriptorService>(io_service)
+ : basic_io_object<DescriptorService>(io_context)
{
boost::system::error_code ec;
this->get_service().assign(this->get_implementation(),
@@ -101,7 +99,7 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_descriptor(io_service&) constructor.
+ * constructed using the @c basic_descriptor(io_context&) constructor.
*/
basic_descriptor(basic_descriptor&& other)
: basic_io_object<DescriptorService>(
@@ -117,7 +115,7 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_descriptor(io_service&) constructor.
+ * constructed using the @c basic_descriptor(io_context&) constructor.
*/
basic_descriptor& operator=(basic_descriptor&& other)
{
@@ -179,17 +177,18 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code assign(const native_handle_type& native_descriptor,
+ BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor,
boost::system::error_code& ec)
{
- return this->get_service().assign(
+ this->get_service().assign(
this->get_implementation(), native_descriptor, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the descriptor is open.
bool is_open() const
{
- return this->get_service().is_open(this->implementation);
+ return this->get_service().is_open(this->get_implementation());
}
/// Close the descriptor.
@@ -217,21 +216,10 @@ public:
* @param ec Set to indicate what error occurred, if any. Note that, even if
* the function indicates an error, the underlying descriptor is closed.
*/
- boost::system::error_code close(boost::system::error_code& ec)
- {
- return this->get_service().close(this->get_implementation(), ec);
- }
-
- /// (Deprecated: Use native_handle().) Get the native descriptor
- /// representation.
- /**
- * This function may be used to obtain the underlying representation of the
- * descriptor. This is intended to allow access to native descriptor
- * functionality that is not otherwise provided.
- */
- native_type native()
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
- return this->get_service().native_handle(this->implementation);
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the native descriptor representation.
@@ -242,7 +230,7 @@ public:
*/
native_handle_type native_handle()
{
- return this->get_service().native_handle(this->implementation);
+ return this->get_service().native_handle(this->get_implementation());
}
/// Release ownership of the native descriptor implementation.
@@ -257,7 +245,7 @@ public:
*/
native_handle_type release()
{
- return this->get_service().release(this->implementation);
+ return this->get_service().release(this->get_implementation());
}
/// Cancel all asynchronous operations associated with the descriptor.
@@ -283,9 +271,10 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code cancel(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
{
- return this->get_service().cancel(this->get_implementation(), ec);
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform an IO control command on the descriptor.
@@ -303,7 +292,7 @@ public:
* @par Example
* Getting the number of bytes ready to read:
* @code
- * boost::asio::posix::stream_descriptor descriptor(io_service);
+ * boost::asio::posix::stream_descriptor descriptor(io_context);
* ...
* boost::asio::posix::stream_descriptor::bytes_readable command;
* descriptor.io_control(command);
@@ -333,7 +322,7 @@ public:
* @par Example
* Getting the number of bytes ready to read:
* @code
- * boost::asio::posix::stream_descriptor descriptor(io_service);
+ * boost::asio::posix::stream_descriptor descriptor(io_context);
* ...
* boost::asio::posix::stream_descriptor::bytes_readable command;
* boost::system::error_code ec;
@@ -346,11 +335,11 @@ public:
* @endcode
*/
template <typename IoControlCommand>
- boost::system::error_code io_control(IoControlCommand& command,
+ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
boost::system::error_code& ec)
{
- return this->get_service().io_control(
- this->get_implementation(), command, ec);
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the descriptor.
@@ -366,7 +355,7 @@ public:
*/
bool non_blocking() const
{
- return this->get_service().non_blocking(this->implementation);
+ return this->get_service().non_blocking(this->get_implementation());
}
/// Sets the non-blocking mode of the descriptor.
@@ -402,11 +391,11 @@ public:
* operations. Asynchronous operations will never fail with the error
* boost::asio::error::would_block.
*/
- boost::system::error_code non_blocking(
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(
bool mode, boost::system::error_code& ec)
{
- return this->get_service().non_blocking(
- this->get_implementation(), mode, ec);
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the native descriptor implementation.
@@ -425,7 +414,8 @@ public:
*/
bool native_non_blocking() const
{
- return this->get_service().native_non_blocking(this->implementation);
+ return this->get_service().native_non_blocking(
+ this->get_implementation());
}
/// Sets the non-blocking mode of the native descriptor implementation.
@@ -466,11 +456,111 @@ public:
* function fails with boost::asio::error::invalid_argument, as the
* combination does not make sense.
*/
- boost::system::error_code native_non_blocking(
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
bool mode, boost::system::error_code& ec)
{
- return this->get_service().native_non_blocking(
+ this->get_service().native_non_blocking(
this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the descriptor to become ready to read, ready to write, or to
+ /// have pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a descriptor to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired descriptor state.
+ *
+ * @par Example
+ * Waiting for a descriptor to become readable.
+ * @code
+ * boost::asio::posix::stream_descriptor descriptor(io_context);
+ * ...
+ * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read);
+ * @endcode
+ */
+ void wait(wait_type w)
+ {
+ boost::system::error_code ec;
+ this->get_service().wait(this->get_implementation(), w, ec);
+ boost::asio::detail::throw_error(ec, "wait");
+ }
+
+ /// Wait for the descriptor to become ready to read, ready to write, or to
+ /// have pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a descriptor to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired descriptor state.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Waiting for a descriptor to become readable.
+ * @code
+ * boost::asio::posix::stream_descriptor descriptor(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read, ec);
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
+ {
+ this->get_service().wait(this->get_implementation(), w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the descriptor to become ready to read, ready to
+ /// 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void wait_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Wait succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::posix::stream_descriptor descriptor(io_context);
+ * ...
+ * descriptor.async_wait(
+ * boost::asio::posix::stream_descriptor::wait_read,
+ * wait_handler);
+ * @endcode
+ */
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WaitHandler.
+ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
+
+ return this->get_service().async_wait(this->get_implementation(),
+ w, BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
}
protected:
@@ -489,4 +579,6 @@ protected:
#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_POSIX_BASIC_DESCRIPTOR_HPP
diff --git a/boost/asio/posix/basic_stream_descriptor.hpp b/boost/asio/posix/basic_stream_descriptor.hpp
index 4baacb519b..ca88e31159 100644
--- a/boost/asio/posix/basic_stream_descriptor.hpp
+++ b/boost/asio/posix/basic_stream_descriptor.hpp
@@ -17,6 +17,8 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
|| defined(GENERATING_DOCUMENTATION)
@@ -50,10 +52,6 @@ class basic_stream_descriptor
: public basic_descriptor<StreamDescriptorService>
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// descriptor.
- typedef typename StreamDescriptorService::native_handle_type native_type;
-
/// The native representation of a descriptor.
typedef typename StreamDescriptorService::native_handle_type
native_handle_type;
@@ -64,12 +62,12 @@ public:
* descriptor needs to be opened and then connected or accepted before data
* can be sent or received on it.
*
- * @param io_service The io_service object that the stream descriptor will
+ * @param io_context The io_context object that the stream descriptor will
* use to dispatch handlers for any asynchronous operations performed on the
* descriptor.
*/
- explicit basic_stream_descriptor(boost::asio::io_service& io_service)
- : basic_descriptor<StreamDescriptorService>(io_service)
+ explicit basic_stream_descriptor(boost::asio::io_context& io_context)
+ : basic_descriptor<StreamDescriptorService>(io_context)
{
}
@@ -78,7 +76,7 @@ public:
* This constructor creates a stream descriptor object to hold an existing
* native descriptor.
*
- * @param io_service The io_service object that the stream descriptor will
+ * @param io_context The io_context object that the stream descriptor will
* use to dispatch handlers for any asynchronous operations performed on the
* descriptor.
*
@@ -86,9 +84,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_stream_descriptor(boost::asio::io_service& io_service,
+ basic_stream_descriptor(boost::asio::io_context& io_context,
const native_handle_type& native_descriptor)
- : basic_descriptor<StreamDescriptorService>(io_service, native_descriptor)
+ : basic_descriptor<StreamDescriptorService>(io_context, native_descriptor)
{
}
@@ -101,7 +99,7 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_stream_descriptor(io_service&) constructor.
+ * constructed using the @c basic_stream_descriptor(io_context&) constructor.
*/
basic_stream_descriptor(basic_stream_descriptor&& other)
: basic_descriptor<StreamDescriptorService>(
@@ -118,7 +116,7 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_stream_descriptor(io_service&) constructor.
+ * constructed using the @c basic_stream_descriptor(io_context&) constructor.
*/
basic_stream_descriptor& operator=(basic_stream_descriptor&& other)
{
@@ -209,7 +207,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -321,7 +319,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -361,4 +359,6 @@ public:
#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
diff --git a/boost/asio/posix/descriptor.hpp b/boost/asio/posix/descriptor.hpp
new file mode 100644
index 0000000000..be67663eb6
--- /dev/null
+++ b/boost/asio/posix/descriptor.hpp
@@ -0,0 +1,646 @@
+//
+// posix/descriptor.hpp
+// ~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_POSIX_DESCRIPTOR_HPP
+#define BOOST_ASIO_POSIX_DESCRIPTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
+ || defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/reactive_descriptor_service.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/posix/descriptor_base.hpp>
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#define BOOST_ASIO_SVC_T boost::asio::detail::reactive_descriptor_service
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace posix {
+
+/// Provides POSIX descriptor functionality.
+/**
+ * The posix::descriptor class template provides the ability to wrap a
+ * POSIX descriptor.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+class descriptor
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>,
+ public descriptor_base
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
+
+ /// The native representation of a descriptor.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef BOOST_ASIO_SVC_T::native_handle_type native_handle_type;
+#endif
+
+ /// A descriptor is always the lowest layer.
+ typedef descriptor lowest_layer_type;
+
+ /// Construct a descriptor without opening it.
+ /**
+ * This constructor creates a descriptor without opening it.
+ *
+ * @param io_context The io_context object that the descriptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * descriptor.
+ */
+ explicit descriptor(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ }
+
+ /// Construct a descriptor on an existing native descriptor.
+ /**
+ * This constructor creates a descriptor object to hold an existing native
+ * descriptor.
+ *
+ * @param io_context The io_context object that the descriptor will use to
+ * dispatch handlers for any asynchronous operations performed on the
+ * descriptor.
+ *
+ * @param native_descriptor A native descriptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ descriptor(boost::asio::io_context& io_context,
+ const native_handle_type& native_descriptor)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ native_descriptor, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a descriptor from another.
+ /**
+ * This constructor moves a descriptor from one object to another.
+ *
+ * @param other The other 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 descriptor(io_context&) constructor.
+ */
+ descriptor(descriptor&& other)
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
+ {
+ }
+
+ /// Move-assign a descriptor from another.
+ /**
+ * This assignment operator moves a descriptor from one object to another.
+ *
+ * @param other The other 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 descriptor(io_context&) constructor.
+ */
+ descriptor& operator=(descriptor&& other)
+ {
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::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 descriptor 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 descriptor 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 descriptor to the descriptor.
+ /*
+ * This function opens the descriptor to hold an existing native descriptor.
+ *
+ * @param native_descriptor A native descriptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const native_handle_type& native_descriptor)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ native_descriptor, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Assign an existing native descriptor to the descriptor.
+ /*
+ * This function opens the descriptor to hold an existing native descriptor.
+ *
+ * @param native_descriptor A native descriptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor,
+ boost::system::error_code& ec)
+ {
+ this->get_service().assign(
+ this->get_implementation(), native_descriptor, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the descriptor is open.
+ bool is_open() const
+ {
+ return this->get_service().is_open(this->get_implementation());
+ }
+
+ /// Close the descriptor.
+ /**
+ * This function is used to close the descriptor. Any asynchronous read or
+ * write operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure. Note that, even if
+ * the function indicates an error, the underlying descriptor is closed.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->get_service().close(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "close");
+ }
+
+ /// Close the descriptor.
+ /**
+ * This function is used to close the descriptor. Any asynchronous read or
+ * write operations will be cancelled immediately, and will complete with the
+ * boost::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.
+ */
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
+ {
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get the native descriptor representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * descriptor. This is intended to allow access to native descriptor
+ * functionality that is not otherwise provided.
+ */
+ native_handle_type native_handle()
+ {
+ return this->get_service().native_handle(this->get_implementation());
+ }
+
+ /// Release ownership of the native descriptor implementation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * descriptor. After calling this function, @c is_open() returns false. The
+ * caller is responsible for closing the descriptor.
+ *
+ * All outstanding asynchronous read or write operations will finish
+ * immediately, and the handlers for cancelled operations will be passed the
+ * boost::asio::error::operation_aborted error.
+ */
+ native_handle_type release()
+ {
+ return this->get_service().release(this->get_implementation());
+ }
+
+ /// Cancel all asynchronous operations associated with the descriptor.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->get_service().cancel(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all asynchronous operations associated with the descriptor.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
+ {
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Perform an IO control command on the descriptor.
+ /**
+ * This function is used to execute an IO control command on the descriptor.
+ *
+ * @param command The IO control command to be performed on the descriptor.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::posix::descriptor_base::bytes_readable @n
+ * boost::asio::posix::descriptor_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::posix::stream_descriptor descriptor(io_context);
+ * ...
+ * boost::asio::posix::stream_descriptor::bytes_readable command;
+ * descriptor.io_control(command);
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ void io_control(IoControlCommand& command)
+ {
+ boost::system::error_code ec;
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ boost::asio::detail::throw_error(ec, "io_control");
+ }
+
+ /// Perform an IO control command on the descriptor.
+ /**
+ * This function is used to execute an IO control command on the descriptor.
+ *
+ * @param command The IO control command to be performed on the descriptor.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa IoControlCommand @n
+ * boost::asio::posix::descriptor_base::bytes_readable @n
+ * boost::asio::posix::descriptor_base::non_blocking_io
+ *
+ * @par Example
+ * Getting the number of bytes ready to read:
+ * @code
+ * boost::asio::posix::stream_descriptor descriptor(io_context);
+ * ...
+ * boost::asio::posix::stream_descriptor::bytes_readable command;
+ * boost::system::error_code ec;
+ * descriptor.io_control(command, ec);
+ * if (ec)
+ * {
+ * // An error occurred.
+ * }
+ * std::size_t bytes_readable = command.get();
+ * @endcode
+ */
+ template <typename IoControlCommand>
+ BOOST_ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,
+ boost::system::error_code& ec)
+ {
+ this->get_service().io_control(this->get_implementation(), command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the descriptor.
+ /**
+ * @returns @c true if the descriptor's synchronous operations will fail with
+ * boost::asio::error::would_block if they are unable to perform the requested
+ * operation immediately. If @c false, synchronous operations will block
+ * until complete.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ bool non_blocking() const
+ {
+ return this->get_service().non_blocking(this->get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the descriptor.
+ /**
+ * @param mode If @c true, the descriptor's synchronous operations will fail
+ * with boost::asio::error::would_block if they are unable to perform the
+ * requested operation immediately. If @c false, synchronous operations will
+ * block until complete.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ void non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the descriptor.
+ /**
+ * @param mode If @c true, the descriptor's synchronous operations will fail
+ * with boost::asio::error::would_block if they are unable to perform the
+ * requested operation immediately. If @c false, synchronous operations will
+ * block until complete.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note The non-blocking mode has no effect on the behaviour of asynchronous
+ * operations. Asynchronous operations will never fail with the error
+ * boost::asio::error::would_block.
+ */
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ this->get_service().non_blocking(this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Gets the non-blocking mode of the native descriptor implementation.
+ /**
+ * This function is used to retrieve the non-blocking mode of the underlying
+ * native descriptor. This mode has no effect on the behaviour of the
+ * descriptor object's synchronous operations.
+ *
+ * @returns @c true if the underlying descriptor is in non-blocking mode and
+ * direct system calls may fail with boost::asio::error::would_block (or the
+ * equivalent system error).
+ *
+ * @note The current non-blocking mode is cached by the descriptor object.
+ * Consequently, the return value may be incorrect if the non-blocking mode
+ * was set directly on the native descriptor.
+ */
+ bool native_non_blocking() const
+ {
+ return this->get_service().native_non_blocking(
+ this->get_implementation());
+ }
+
+ /// Sets the non-blocking mode of the native descriptor implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native descriptor. It has no effect on the behaviour of the descriptor
+ * object's synchronous operations.
+ *
+ * @param mode If @c true, the underlying descriptor is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @throws boost::system::system_error Thrown on failure. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ */
+ void native_non_blocking(bool mode)
+ {
+ boost::system::error_code ec;
+ this->get_service().native_non_blocking(
+ this->get_implementation(), mode, ec);
+ boost::asio::detail::throw_error(ec, "native_non_blocking");
+ }
+
+ /// Sets the non-blocking mode of the native descriptor implementation.
+ /**
+ * This function is used to modify the non-blocking mode of the underlying
+ * native descriptor. It has no effect on the behaviour of the descriptor
+ * object's synchronous operations.
+ *
+ * @param mode If @c true, the underlying descriptor is put into non-blocking
+ * mode and direct system calls may fail with boost::asio::error::would_block
+ * (or the equivalent system error).
+ *
+ * @param ec Set to indicate what error occurred, if any. If the @c mode is
+ * @c false, but the current value of @c non_blocking() is @c true, this
+ * function fails with boost::asio::error::invalid_argument, as the
+ * combination does not make sense.
+ */
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(
+ bool mode, boost::system::error_code& ec)
+ {
+ this->get_service().native_non_blocking(
+ this->get_implementation(), mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the descriptor to become ready to read, ready to write, or to
+ /// have pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a descriptor to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired descriptor state.
+ *
+ * @par Example
+ * Waiting for a descriptor to become readable.
+ * @code
+ * boost::asio::posix::stream_descriptor descriptor(io_context);
+ * ...
+ * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read);
+ * @endcode
+ */
+ void wait(wait_type w)
+ {
+ boost::system::error_code ec;
+ this->get_service().wait(this->get_implementation(), w, ec);
+ boost::asio::detail::throw_error(ec, "wait");
+ }
+
+ /// Wait for the descriptor to become ready to read, ready to write, or to
+ /// have pending error conditions.
+ /**
+ * This function is used to perform a blocking wait for a descriptor to enter
+ * a ready to read, write or error condition state.
+ *
+ * @param w Specifies the desired descriptor state.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @par Example
+ * Waiting for a descriptor to become readable.
+ * @code
+ * boost::asio::posix::stream_descriptor descriptor(io_context);
+ * ...
+ * boost::system::error_code ec;
+ * descriptor.wait(boost::asio::posix::stream_descriptor::wait_read, ec);
+ * @endcode
+ */
+ BOOST_ASIO_SYNC_OP_VOID wait(wait_type w, boost::system::error_code& ec)
+ {
+ this->get_service().wait(this->get_implementation(), w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the descriptor to become ready to read, ready to
+ /// 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @par Example
+ * @code
+ * void wait_handler(const boost::system::error_code& error)
+ * {
+ * if (!error)
+ * {
+ * // Wait succeeded.
+ * }
+ * }
+ *
+ * ...
+ *
+ * boost::asio::posix::stream_descriptor descriptor(io_context);
+ * ...
+ * descriptor.async_wait(
+ * boost::asio::posix::stream_descriptor::wait_read,
+ * wait_handler);
+ * @endcode
+ */
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(wait_type w, BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WaitHandler.
+ BOOST_ASIO_WAIT_HANDLER_CHECK(WaitHandler, handler) type_check;
+
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_wait(
+ this->get_implementation(), w, init.completion_handler);
+
+ return init.result.get();
+ }
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ /**
+ * This function destroys the descriptor, cancelling any outstanding
+ * asynchronous wait operations associated with the descriptor as if by
+ * calling @c cancel.
+ */
+ ~descriptor()
+ {
+ }
+};
+
+} // namespace posix
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#undef BOOST_ASIO_SVC_T
+
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#endif // BOOST_ASIO_POSIX_DESCRIPTOR_HPP
diff --git a/boost/asio/posix/descriptor_base.hpp b/boost/asio/posix/descriptor_base.hpp
index e23af43bc8..3e547fe87b 100644
--- a/boost/asio/posix/descriptor_base.hpp
+++ b/boost/asio/posix/descriptor_base.hpp
@@ -29,33 +29,26 @@ namespace boost {
namespace asio {
namespace posix {
-/// The descriptor_base class is used as a base for the basic_stream_descriptor
-/// class template so that we have a common place to define the associated
-/// IO control commands.
+/// The descriptor_base class is used as a base for the descriptor class as a
+/// place to define the associated IO control commands.
class descriptor_base
{
public:
- /// (Deprecated: Use non_blocking().) IO control command to set the blocking
- /// mode of the descriptor.
+ /// Wait types.
/**
- * Implements the FIONBIO IO control command.
- *
- * @par Example
- * @code
- * boost::asio::posix::stream_descriptor descriptor(io_service);
- * ...
- * boost::asio::descriptor_base::non_blocking_io command(true);
- * descriptor.io_control(command);
- * @endcode
- *
- * @par Concepts:
- * IoControlCommand.
+ * For use with descriptor::wait() and descriptor::async_wait().
*/
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined non_blocking_io;
-#else
- typedef boost::asio::detail::io_control::non_blocking_io non_blocking_io;
-#endif
+ enum wait_type
+ {
+ /// Wait for a descriptor to become ready to read.
+ wait_read,
+
+ /// Wait for a descriptor to become ready to write.
+ wait_write,
+
+ /// Wait for a descriptor to have error conditions pending.
+ wait_error
+ };
/// IO control command to get the amount of data that can be read without
/// blocking.
@@ -64,7 +57,7 @@ public:
*
* @par Example
* @code
- * boost::asio::posix::stream_descriptor descriptor(io_service);
+ * boost::asio::posix::stream_descriptor descriptor(io_context);
* ...
* boost::asio::descriptor_base::bytes_readable command(true);
* descriptor.io_control(command);
diff --git a/boost/asio/posix/stream_descriptor.hpp b/boost/asio/posix/stream_descriptor.hpp
index d6d1344702..86db187ded 100644
--- a/boost/asio/posix/stream_descriptor.hpp
+++ b/boost/asio/posix/stream_descriptor.hpp
@@ -16,18 +16,341 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+#include <boost/asio/posix/descriptor.hpp>
#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
|| defined(GENERATING_DOCUMENTATION)
-#include <boost/asio/posix/basic_stream_descriptor.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/posix/basic_stream_descriptor.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
namespace boost {
namespace asio {
namespace posix {
-/// Typedef for the typical usage of a stream-oriented descriptor.
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+// Typedef for the typical usage of a stream-oriented descriptor.
typedef basic_stream_descriptor<> stream_descriptor;
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+/// Provides stream-oriented descriptor functionality.
+/**
+ * The posix::stream_descriptor class template provides asynchronous and
+ * blocking stream-oriented descriptor functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+class stream_descriptor
+ : public descriptor
+{
+public:
+ /// Construct a stream_descriptor without opening it.
+ /**
+ * This constructor creates a stream descriptor without opening it. The
+ * descriptor needs to be opened and then connected or accepted before data
+ * can be sent or received on it.
+ *
+ * @param io_context The io_context object that the stream descriptor will
+ * use to dispatch handlers for any asynchronous operations performed on the
+ * descriptor.
+ */
+ explicit stream_descriptor(boost::asio::io_context& io_context)
+ : descriptor(io_context)
+ {
+ }
+
+ /// Construct a stream_descriptor on an existing native descriptor.
+ /**
+ * This constructor creates a stream descriptor object to hold an existing
+ * native descriptor.
+ *
+ * @param io_context The io_context object that the stream descriptor will
+ * use to dispatch handlers for any asynchronous operations performed on the
+ * descriptor.
+ *
+ * @param native_descriptor The new underlying descriptor implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ stream_descriptor(boost::asio::io_context& io_context,
+ const native_handle_type& native_descriptor)
+ : descriptor(io_context, native_descriptor)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a stream_descriptor from another.
+ /**
+ * This constructor moves a stream descriptor from one object to another.
+ *
+ * @param other The other 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 stream_descriptor(io_context&) constructor.
+ */
+ stream_descriptor(stream_descriptor&& other)
+ : descriptor(std::move(other))
+ {
+ }
+
+ /// Move-assign a stream_descriptor from another.
+ /**
+ * This assignment operator moves a stream descriptor from one object to
+ * another.
+ *
+ * @param other The other 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 stream_descriptor(io_context&) constructor.
+ */
+ stream_descriptor& operator=(stream_descriptor&& other)
+ {
+ descriptor::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Write some data to the descriptor.
+ /**
+ * This function is used to write data to the stream descriptor. 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 descriptor.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::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
+ * descriptor.write_some(boost::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)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().write_some(
+ this->get_implementation(), buffers, ec);
+ boost::asio::detail::throw_error(ec, "write_some");
+ return s;
+ }
+
+ /// Write some data to the descriptor.
+ /**
+ * This function is used to write data to the stream descriptor. 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 descriptor.
+ *
+ * @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,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().write_some(
+ this->get_implementation(), buffers, ec);
+ }
+
+ /// Start an asynchronous write.
+ /**
+ * This function is used to asynchronously write data to the stream
+ * descriptor. The function call 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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 handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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
+ * descriptor.async_write_some(boost::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, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_write_some(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ boost::asio::async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_write_some(
+ this->get_implementation(), buffers, init.completion_handler);
+
+ return init.result.get();
+ }
+
+ /// Read some data from the descriptor.
+ /**
+ * This function is used to read data from the stream descriptor. 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 boost::system::system_error Thrown on failure. An error code of
+ * boost::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
+ * descriptor.read_some(boost::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)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().read_some(
+ this->get_implementation(), buffers, ec);
+ boost::asio::detail::throw_error(ec, "read_some");
+ return s;
+ }
+
+ /// Read some data from the descriptor.
+ /**
+ * This function is used to read data from the stream descriptor. 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,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().read_some(
+ this->get_implementation(), buffers, ec);
+ }
+
+ /// Start an asynchronous read.
+ /**
+ * This function is used to asynchronously read data from the stream
+ * descriptor. The function call 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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 handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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
+ * descriptor.async_read_some(boost::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, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+ async_read_some(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ boost::asio::async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_read_some(
+ this->get_implementation(), buffers, init.completion_handler);
+
+ return init.result.get();
+ }
+};
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
} // namespace posix
} // namespace asio
diff --git a/boost/asio/posix/stream_descriptor_service.hpp b/boost/asio/posix/stream_descriptor_service.hpp
index e42580d3f3..0648781505 100644
--- a/boost/asio/posix/stream_descriptor_service.hpp
+++ b/boost/asio/posix/stream_descriptor_service.hpp
@@ -17,13 +17,15 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \
|| defined(GENERATING_DOCUMENTATION)
#include <cstddef>
#include <boost/asio/async_result.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/reactive_descriptor_service.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -35,7 +37,7 @@ namespace posix {
/// Default service implementation for a stream descriptor.
class stream_descriptor_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<stream_descriptor_service>
#endif
@@ -43,7 +45,7 @@ class stream_descriptor_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
private:
@@ -58,13 +60,6 @@ public:
typedef service_impl_type::implementation_type implementation_type;
#endif
- /// (Deprecated: Use native_handle_type.) The native descriptor type.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined native_type;
-#else
- typedef service_impl_type::native_handle_type native_type;
-#endif
-
/// The native descriptor type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
@@ -72,10 +67,10 @@ public:
typedef service_impl_type::native_handle_type native_handle_type;
#endif
- /// Construct a new stream descriptor service for the specified io_service.
- explicit stream_descriptor_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<stream_descriptor_service>(io_service),
- service_impl_(io_service)
+ /// Construct a new stream descriptor service for the specified io_context.
+ explicit stream_descriptor_service(boost::asio::io_context& io_context)
+ : boost::asio::detail::service_base<stream_descriptor_service>(io_context),
+ service_impl_(io_context)
{
}
@@ -109,11 +104,12 @@ public:
}
/// Assign an existing native descriptor to a stream descriptor.
- boost::system::error_code assign(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl,
const native_handle_type& native_descriptor,
boost::system::error_code& ec)
{
- return service_impl_.assign(impl, native_descriptor, ec);
+ service_impl_.assign(impl, native_descriptor, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the descriptor is open.
@@ -123,17 +119,11 @@ public:
}
/// Close a stream descriptor implementation.
- boost::system::error_code close(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.close(impl, ec);
- }
-
- /// (Deprecated: Use native_handle().) Get the native descriptor
- /// implementation.
- native_type native(implementation_type& impl)
- {
- return service_impl_.native_handle(impl);
+ service_impl_.close(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the native descriptor implementation.
@@ -149,18 +139,20 @@ public:
}
/// Cancel all asynchronous operations associated with the descriptor.
- boost::system::error_code cancel(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.cancel(impl, ec);
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform an IO control command on the descriptor.
template <typename IoControlCommand>
- boost::system::error_code io_control(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl,
IoControlCommand& command, boost::system::error_code& ec)
{
- return service_impl_.io_control(impl, command, ec);
+ service_impl_.io_control(impl, command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the descriptor.
@@ -170,10 +162,11 @@ public:
}
/// Sets the non-blocking mode of the descriptor.
- boost::system::error_code non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.non_blocking(impl, mode, ec);
+ service_impl_.non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the native descriptor implementation.
@@ -183,10 +176,36 @@ public:
}
/// Sets the non-blocking mode of the native descriptor implementation.
- boost::system::error_code native_non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.native_non_blocking(impl, mode, ec);
+ service_impl_.native_non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the descriptor to become ready to read, ready to write, or to
+ /// have pending error conditions.
+ BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl,
+ descriptor_base::wait_type w, boost::system::error_code& ec)
+ {
+ service_impl_.wait(impl, w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the descriptor to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(implementation_type& impl, descriptor_base::wait_type w,
+ BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ service_impl_.async_wait(impl, w, init.completion_handler);
+
+ return init.result.get();
}
/// Write the given data to the stream.
@@ -205,11 +224,10 @@ public:
const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- boost::asio::detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ boost::asio::async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_write_some(impl, buffers, init.handler);
+ service_impl_.async_write_some(impl, buffers, init.completion_handler);
return init.result.get();
}
@@ -230,20 +248,19 @@ public:
const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- boost::asio::detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ boost::asio::async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_read_some(impl, buffers, init.handler);
+ service_impl_.async_read_some(impl, buffers, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -259,4 +276,6 @@ private:
#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_POSIX_STREAM_DESCRIPTOR_SERVICE_HPP
diff --git a/boost/asio/post.hpp b/boost/asio/post.hpp
new file mode 100644
index 0000000000..65e858fd88
--- /dev/null
+++ b/boost/asio/post.hpp
@@ -0,0 +1,109 @@
+//
+// post.hpp
+// ~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_POST_HPP
+#define BOOST_ASIO_POST_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/is_executor.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// Submits a completion token or function object for execution.
+/**
+ * This function submits an object for execution using the object's associated
+ * executor. The function object is queued for execution, and is never called
+ * from the current thread prior to returning from <tt>post()</tt>.
+ *
+ * This function has the following effects:
+ *
+ * @li Constructs a function object handler of type @c Handler, initialized
+ * with <tt>handler(forward<CompletionToken>(token))</tt>.
+ *
+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,
+ * initializing the object as <tt>result(handler)</tt>.
+ *
+ * @li Obtains the handler's associated executor object @c ex by performing
+ * <tt>get_associated_executor(handler)</tt>.
+ *
+ * @li Obtains the handler's associated allocator object @c alloc by performing
+ * <tt>get_associated_allocator(handler)</tt>.
+ *
+ * @li Performs <tt>ex.post(std::move(handler), alloc)</tt>.
+ *
+ * @li Returns <tt>result.get()</tt>.
+ */
+template <typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
+ BOOST_ASIO_MOVE_ARG(CompletionToken) token);
+
+/// Submits a completion token or function object for execution.
+/**
+ * This function submits an object for execution using the specified executor.
+ * The function object is queued for execution, and is never called from the
+ * current thread prior to returning from <tt>post()</tt>.
+ *
+ * This function has the following effects:
+ *
+ * @li Constructs a function object handler of type @c Handler, initialized
+ * with <tt>handler(forward<CompletionToken>(token))</tt>.
+ *
+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,
+ * initializing the object as <tt>result(handler)</tt>.
+ *
+ * @li Obtains the handler's associated executor object @c ex1 by performing
+ * <tt>get_associated_executor(handler)</tt>.
+ *
+ * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.
+ *
+ * @li Obtains the handler's associated allocator object @c alloc by performing
+ * <tt>get_associated_allocator(handler)</tt>.
+ *
+ * @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 Performs <tt>Executor(ex).post(std::move(f), alloc)</tt>.
+ *
+ * @li Returns <tt>result.get()</tt>.
+ */
+template <typename Executor, typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
+ const Executor& ex, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_executor<Executor>::value>::type* = 0);
+
+/// Submits a completion token or function object for execution.
+/**
+ * @returns <tt>post(ctx.get_executor(), forward<CompletionToken>(token))</tt>.
+ */
+template <typename ExecutionContext, typename CompletionToken>
+BOOST_ASIO_INITFN_RESULT_TYPE(CompletionToken, void()) post(
+ ExecutionContext& ctx, BOOST_ASIO_MOVE_ARG(CompletionToken) token,
+ typename enable_if<is_convertible<
+ ExecutionContext&, execution_context&>::value>::type* = 0);
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/impl/post.hpp>
+
+#endif // BOOST_ASIO_POST_HPP
diff --git a/boost/asio/raw_socket_service.hpp b/boost/asio/raw_socket_service.hpp
index 06880d5abb..9a777013e2 100644
--- a/boost/asio/raw_socket_service.hpp
+++ b/boost/asio/raw_socket_service.hpp
@@ -16,11 +16,14 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <cstddef>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
# include <boost/asio/detail/null_socket_service.hpp>
@@ -39,7 +42,7 @@ namespace asio {
template <typename Protocol>
class raw_socket_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<raw_socket_service<Protocol> >
#endif
@@ -47,7 +50,7 @@ class raw_socket_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
/// The protocol type.
@@ -74,13 +77,6 @@ public:
typedef typename service_impl_type::implementation_type implementation_type;
#endif
- /// (Deprecated: Use native_handle_type.) The native socket type.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined native_type;
-#else
- typedef typename service_impl_type::native_handle_type native_type;
-#endif
-
/// The native socket type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
@@ -88,11 +84,11 @@ public:
typedef typename service_impl_type::native_handle_type native_handle_type;
#endif
- /// Construct a new raw socket service for the specified io_service.
- explicit raw_socket_service(boost::asio::io_service& io_service)
+ /// Construct a new raw socket service for the specified io_context.
+ explicit raw_socket_service(boost::asio::io_context& io_context)
: boost::asio::detail::service_base<
- raw_socket_service<Protocol> >(io_service),
- service_impl_(io_service)
+ raw_socket_service<Protocol> >(io_context),
+ service_impl_(io_context)
{
}
@@ -143,22 +139,23 @@ public:
}
// Open a new raw socket implementation.
- boost::system::error_code open(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl,
const protocol_type& protocol, boost::system::error_code& ec)
{
if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_RAW))
service_impl_.open(impl, protocol, ec);
else
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Assign an existing native socket to a raw socket.
- boost::system::error_code assign(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl,
const protocol_type& protocol, const native_handle_type& native_socket,
boost::system::error_code& ec)
{
- return service_impl_.assign(impl, protocol, native_socket, ec);
+ service_impl_.assign(impl, protocol, native_socket, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is open.
@@ -168,16 +165,18 @@ public:
}
/// Close a raw socket implementation.
- boost::system::error_code close(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.close(impl, ec);
+ service_impl_.close(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
- /// (Deprecated: Use native_handle().) Get the native socket implementation.
- native_type native(implementation_type& impl)
+ /// Release ownership of the underlying socket.
+ native_handle_type release(implementation_type& impl,
+ boost::system::error_code& ec)
{
- return service_impl_.native_handle(impl);
+ return service_impl_.release(impl, ec);
}
/// Get the native socket implementation.
@@ -187,10 +186,11 @@ public:
}
/// Cancel all asynchronous operations associated with the socket.
- boost::system::error_code cancel(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.cancel(impl, ec);
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is at the out-of-band data mark.
@@ -208,17 +208,19 @@ public:
}
// Bind the raw socket to the specified local endpoint.
- boost::system::error_code bind(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID bind(implementation_type& impl,
const endpoint_type& endpoint, boost::system::error_code& ec)
{
- return service_impl_.bind(impl, endpoint, ec);
+ service_impl_.bind(impl, endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Connect the raw socket to the specified endpoint.
- boost::system::error_code connect(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID connect(implementation_type& impl,
const endpoint_type& peer_endpoint, boost::system::error_code& ec)
{
- return service_impl_.connect(impl, peer_endpoint, ec);
+ service_impl_.connect(impl, peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Start an asynchronous connect.
@@ -229,37 +231,39 @@ public:
const endpoint_type& peer_endpoint,
BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
{
- detail::async_result_init<
- ConnectHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
+ async_completion<ConnectHandler,
+ void (boost::system::error_code)> init(handler);
- service_impl_.async_connect(impl, peer_endpoint, init.handler);
+ service_impl_.async_connect(impl, peer_endpoint, init.completion_handler);
return init.result.get();
}
/// Set a socket option.
template <typename SettableSocketOption>
- boost::system::error_code set_option(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl,
const SettableSocketOption& option, boost::system::error_code& ec)
{
- return service_impl_.set_option(impl, option, ec);
+ service_impl_.set_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get a socket option.
template <typename GettableSocketOption>
- boost::system::error_code get_option(const implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl,
GettableSocketOption& option, boost::system::error_code& ec) const
{
- return service_impl_.get_option(impl, option, ec);
+ service_impl_.get_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform an IO control command on the socket.
template <typename IoControlCommand>
- boost::system::error_code io_control(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl,
IoControlCommand& command, boost::system::error_code& ec)
{
- return service_impl_.io_control(impl, command, ec);
+ service_impl_.io_control(impl, command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the socket.
@@ -269,10 +273,11 @@ public:
}
/// Sets the non-blocking mode of the socket.
- boost::system::error_code non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.non_blocking(impl, mode, ec);
+ service_impl_.non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the native socket implementation.
@@ -282,10 +287,11 @@ public:
}
/// Sets the non-blocking mode of the native socket implementation.
- boost::system::error_code native_non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.native_non_blocking(impl, mode, ec);
+ service_impl_.native_non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the local endpoint.
@@ -303,10 +309,36 @@ public:
}
/// Disable sends or receives on the socket.
- boost::system::error_code shutdown(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID shutdown(implementation_type& impl,
socket_base::shutdown_type what, boost::system::error_code& ec)
{
- return service_impl_.shutdown(impl, what, ec);
+ service_impl_.shutdown(impl, what, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
+ {
+ service_impl_.wait(impl, w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the socket to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(implementation_type& impl, socket_base::wait_type w,
+ BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ service_impl_.async_wait(impl, w, init.completion_handler);
+
+ return init.result.get();
}
/// Send the given data to the peer.
@@ -326,11 +358,10 @@ public:
socket_base::message_flags flags,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_send(impl, buffers, flags, init.handler);
+ service_impl_.async_send(impl, buffers, flags, init.completion_handler);
return init.result.get();
}
@@ -353,12 +384,11 @@ public:
socket_base::message_flags flags,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
service_impl_.async_send_to(impl, buffers,
- destination, flags, init.handler);
+ destination, flags, init.completion_handler);
return init.result.get();
}
@@ -381,11 +411,10 @@ public:
socket_base::message_flags flags,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_receive(impl, buffers, flags, init.handler);
+ service_impl_.async_receive(impl, buffers, flags, init.completion_handler);
return init.result.get();
}
@@ -409,21 +438,20 @@ public:
socket_base::message_flags flags,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
service_impl_.async_receive_from(impl, buffers,
- sender_endpoint, flags, init.handler);
+ sender_endpoint, flags, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -435,4 +463,6 @@ private:
#include <boost/asio/detail/pop_options.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_RAW_SOCKET_SERVICE_HPP
diff --git a/boost/asio/read.hpp b/boost/asio/read.hpp
index 0db29b7831..d03ed5a73d 100644
--- a/boost/asio/read.hpp
+++ b/boost/asio/read.hpp
@@ -18,9 +18,13 @@
#include <boost/asio/detail/config.hpp>
#include <cstddef>
#include <boost/asio/async_result.hpp>
-#include <boost/asio/basic_streambuf_fwd.hpp>
+#include <boost/asio/buffer.hpp>
#include <boost/asio/error.hpp>
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+# include <boost/asio/basic_streambuf_fwd.hpp>
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
@@ -71,7 +75,10 @@ namespace asio {
* boost::asio::transfer_all()); @endcode
*/
template <typename SyncReadStream, typename MutableBufferSequence>
-std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers);
+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type* = 0);
/// Attempt to read a certain amount of data from a stream before returning.
/**
@@ -111,7 +118,10 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers);
*/
template <typename SyncReadStream, typename MutableBufferSequence>
std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
- boost::system::error_code& ec);
+ boost::system::error_code& ec,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type* = 0);
/// Attempt to read a certain amount of data from a stream before returning.
/**
@@ -162,7 +172,10 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
template <typename SyncReadStream, typename MutableBufferSequence,
typename CompletionCondition>
std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
- CompletionCondition completion_condition);
+ CompletionCondition completion_condition,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type* = 0);
/// Attempt to read a certain amount of data from a stream before returning.
/**
@@ -206,8 +219,171 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
template <typename SyncReadStream, typename MutableBufferSequence,
typename CompletionCondition>
std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
- CompletionCondition completion_condition, boost::system::error_code& ec);
+ CompletionCondition completion_condition, boost::system::error_code& ec,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type* = 0);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The specified dynamic buffer sequence is full (that is, it has reached
+ * maximum size).
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::read(
+ * s, buffers,
+ * boost::asio::transfer_all()); @endcode
+ */
+template <typename SyncReadStream, typename DynamicBuffer>
+std::size_t read(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The supplied buffer is full (that is, it has reached maximum size).
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::read(
+ * s, buffers,
+ * boost::asio::transfer_all(), ec); @endcode
+ */
+template <typename SyncReadStream, typename DynamicBuffer>
+std::size_t read(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The specified dynamic buffer sequence is full (that is, it has reached
+ * maximum size).
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code std::size_t completion_condition(
+ * // Result of latest read_some operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the read operation is complete. A non-zero
+ * return value indicates the maximum number of bytes to be read on the next
+ * call to the stream's read_some function.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+template <typename SyncReadStream, typename DynamicBuffer,
+ typename CompletionCondition>
+std::size_t read(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ CompletionCondition completion_condition,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The specified dynamic buffer sequence is full (that is, it has reached
+ * maximum size).
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code std::size_t completion_condition(
+ * // Result of latest read_some operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the read operation is complete. A non-zero
+ * return value indicates the maximum number of bytes to be read on the next
+ * call to the stream's read_some function.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncReadStream, typename DynamicBuffer,
+ typename CompletionCondition>
+std::size_t read(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// Attempt to read a certain amount of data from a stream before returning.
@@ -351,6 +527,7 @@ std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b,
CompletionCondition completion_condition, boost::system::error_code& ec);
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
/*@}*/
/**
@@ -404,7 +581,7 @@ std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
@@ -426,7 +603,10 @@ template <typename AsyncReadStream, typename MutableBufferSequence,
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type* = 0);
/// Start an asynchronous operation to read a certain amount of data from a
/// stream.
@@ -479,7 +659,7 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
@@ -497,8 +677,143 @@ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
CompletionCondition completion_condition,
- BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_mutable_buffer_sequence<MutableBufferSequence>::value
+ >::type* = 0);
+
+/// 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:
+ *
+ * @li The specified dynamic buffer sequence is full (that is, it has reached
+ * maximum size).
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. The
+ * program must ensure that the stream performs no other read operations (such
+ * as async_read, the stream's async_read_some function, or any other composed
+ * operations that perform reads) until this operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * 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.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::async_read(
+ * s, buffers,
+ * boost::asio::transfer_all(),
+ * handler); @endcode
+ */
+template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read(AsyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+
+/// 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:
+ *
+ * @li The specified dynamic buffer sequence is full (that is, it has reached
+ * maximum size).
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. The
+ * program must ensure that the stream performs no other read operations (such
+ * as async_read, the stream's async_read_some function, or any other composed
+ * operations that perform reads) until this operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @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.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code std::size_t completion_condition(
+ * // Result of latest async_read_some operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the read operation is complete. A non-zero
+ * 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:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * 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.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ */
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename CompletionCondition, typename ReadHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read(AsyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ CompletionCondition completion_condition,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// Start an asynchronous operation to read a certain amount of data from a
@@ -541,7 +856,7 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @note This overload is equivalent to calling:
* @code boost::asio::async_read(
@@ -609,7 +924,7 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename AsyncReadStream, typename Allocator,
typename CompletionCondition, typename ReadHandler>
@@ -620,6 +935,7 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
/*@}*/
diff --git a/boost/asio/read_at.hpp b/boost/asio/read_at.hpp
index 03f6c155c1..fc10c8115e 100644
--- a/boost/asio/read_at.hpp
+++ b/boost/asio/read_at.hpp
@@ -18,10 +18,13 @@
#include <boost/asio/detail/config.hpp>
#include <cstddef>
#include <boost/asio/async_result.hpp>
-#include <boost/asio/basic_streambuf_fwd.hpp>
#include <boost/asio/detail/cstdint.hpp>
#include <boost/asio/error.hpp>
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+# include <boost/asio/basic_streambuf_fwd.hpp>
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
@@ -230,6 +233,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
uint64_t offset, const MutableBufferSequence& buffers,
CompletionCondition completion_condition, boost::system::error_code& ec);
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// Attempt to read a certain amount of data at the specified offset before
@@ -385,6 +389,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
CompletionCondition completion_condition, boost::system::error_code& ec);
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
/*@}*/
/**
@@ -437,7 +442,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
@@ -515,7 +520,7 @@ async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To read into a single data buffer use the @ref buffer function as follows:
@@ -536,6 +541,7 @@ async_read_at(AsyncRandomAccessReadDevice& d,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// Start an asynchronous operation to read a certain amount of data at the
@@ -575,7 +581,7 @@ async_read_at(AsyncRandomAccessReadDevice& d,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @note This overload is equivalent to calling:
* @code boost::asio::async_read_at(
@@ -641,7 +647,7 @@ async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename AsyncRandomAccessReadDevice, typename Allocator,
typename CompletionCondition, typename ReadHandler>
@@ -653,6 +659,7 @@ async_read_at(AsyncRandomAccessReadDevice& d,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
/*@}*/
diff --git a/boost/asio/read_until.hpp b/boost/asio/read_until.hpp
index 3ed288fc2c..12f82c7808 100644
--- a/boost/asio/read_until.hpp
+++ b/boost/asio/read_until.hpp
@@ -16,17 +16,18 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-
-#if !defined(BOOST_ASIO_NO_IOSTREAM)
-
#include <cstddef>
#include <string>
#include <boost/asio/async_result.hpp>
-#include <boost/asio/basic_streambuf.hpp>
#include <boost/asio/detail/regex_fwd.hpp>
+#include <boost/asio/detail/string_view.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+# include <boost/asio/basic_streambuf_fwd.hpp>
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
@@ -67,11 +68,482 @@ struct is_match_condition
/**
* @defgroup read_until boost::asio::read_until
*
- * @brief Read data into a streambuf until it contains a delimiter, matches a
- * regular expression, or a function object indicates a match.
+ * @brief Read data into a dynamic buffer sequence, or into a streambuf, until
+ * it contains a delimiter, matches a regular expression, or a function object
+ * indicates a match.
*/
/*@{*/
+/// Read data into a dynamic buffer sequence until it contains a specified
+/// delimiter.
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until the dynamic buffer sequence's get area contains the specified
+ * delimiter. The call will block until one of the following conditions is
+ * true:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains the delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param delim The delimiter character.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the delimiter.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note After a successful 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 subsequent
+ * read_until operation to examine.
+ *
+ * @par Example
+ * To read data into a @c std::string until a newline is encountered:
+ * @code std::string data;
+ * std::string n = boost::asio::read_until(s,
+ * boost::asio::dynamic_buffer(data), '\n');
+ * std::string line = data.substr(0, n);
+ * data.erase(0, n); @endcode
+ * After the @c read_until operation completes successfully, the string @c data
+ * contains the delimiter:
+ * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the
+ * delimiter, so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the buffer @c b as
+ * follows:
+ * @code { 'd', 'e', ... } @endcode
+ * This data may be the start of a new line, to be extracted by a subsequent
+ * @c read_until operation.
+ */
+template <typename SyncReadStream, typename DynamicBuffer>
+std::size_t read_until(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers, char delim);
+
+/// Read data into a dynamic buffer sequence until it contains a specified
+/// delimiter.
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until the dynamic buffer sequence's get area contains the specified
+ * delimiter. The call will block until one of the following conditions is
+ * true:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains the delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param delim The delimiter character.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the delimiter. Returns 0 if an error occurred.
+ *
+ * @note After a successful 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 subsequent
+ * read_until operation to examine.
+ */
+template <typename SyncReadStream, typename DynamicBuffer>
+std::size_t read_until(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ char delim, boost::system::error_code& ec);
+
+/// Read data into a dynamic buffer sequence until it contains a specified
+/// delimiter.
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until the dynamic buffer sequence's get area contains the specified
+ * delimiter. The call will block until one of the following conditions is
+ * true:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains the delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param delim The delimiter string.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the delimiter.
+ *
+ * @note After a successful 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 subsequent
+ * read_until operation to examine.
+ *
+ * @par Example
+ * To read data into a @c std::string until a CR-LF sequence is encountered:
+ * @code std::string data;
+ * std::string n = boost::asio::read_until(s,
+ * boost::asio::dynamic_buffer(data), "\r\n");
+ * std::string line = data.substr(0, n);
+ * data.erase(0, n); @endcode
+ * After the @c read_until operation completes successfully, the string @c data
+ * contains the delimiter:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the
+ * delimiter, so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the buffer @c b as
+ * follows:
+ * @code { 'd', 'e', ... } @endcode
+ * This data may be the start of a new line, to be extracted by a subsequent
+ * @c read_until operation.
+ */
+template <typename SyncReadStream, typename DynamicBuffer>
+std::size_t read_until(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_STRING_VIEW_PARAM delim);
+
+/// Read data into a dynamic buffer sequence until it contains a specified
+/// delimiter.
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until the dynamic buffer sequence's get area contains the specified
+ * delimiter. The call will block until one of the following conditions is
+ * true:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains the delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param delim The delimiter string.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the delimiter. Returns 0 if an error occurred.
+ *
+ * @note After a successful 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 subsequent
+ * read_until operation to examine.
+ */
+template <typename SyncReadStream, typename DynamicBuffer>
+std::size_t read_until(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_STRING_VIEW_PARAM delim,
+ boost::system::error_code& ec);
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+#if defined(BOOST_ASIO_HAS_BOOST_REGEX) \
+ || defined(GENERATING_DOCUMENTATION)
+
+/// Read data into a dynamic buffer sequence until some part of the data it
+/// contains matches a regular expression.
+/**
+ * This function is used to 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 call will block until one of the
+ * following conditions is true:
+ *
+ * @li A substring of the dynamic buffer sequence's get area matches the
+ * regular expression.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains data that matches the regular expression, the function returns
+ * immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers A dynamic buffer sequence into which the data will be read.
+ *
+ * @param expr The regular expression.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the substring that matches the regular expression.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note After a successful 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
+ * buffer sequence for a subsequent read_until operation to examine.
+ *
+ * @par Example
+ * To read data into a @c std::string until a CR-LF sequence is encountered:
+ * @code std::string data;
+ * std::string n = boost::asio::read_until(s,
+ * boost::asio::dynamic_buffer(data), boost::regex("\r\n"));
+ * std::string line = data.substr(0, n);
+ * data.erase(0, n); @endcode
+ * After the @c read_until operation completes successfully, the string @c data
+ * contains the delimiter:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the
+ * delimiter, so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the buffer @c b as
+ * follows:
+ * @code { 'd', 'e', ... } @endcode
+ * This data may be the start of a new line, to be extracted by a subsequent
+ * @c read_until operation.
+ */
+template <typename SyncReadStream, typename DynamicBuffer>
+std::size_t read_until(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ const boost::regex& expr);
+
+/// Read data into a dynamic buffer sequence until some part of the data it
+/// contains matches a regular expression.
+/**
+ * This function is used to 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 call will block until one of the
+ * following conditions is true:
+ *
+ * @li A substring of the dynamic buffer sequence's get area matches the
+ * regular expression.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains data that matches the regular expression, the function returns
+ * immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers A dynamic buffer sequence into which the data will be read.
+ *
+ * @param expr The regular expression.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the substring that matches the regular expression. Returns 0
+ * if an error occurred.
+ *
+ * @note After a successful 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
+ * buffer sequence for a subsequent read_until operation to examine.
+ */
+template <typename SyncReadStream, typename DynamicBuffer>
+std::size_t read_until(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ const boost::regex& expr, boost::system::error_code& ec);
+
+#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
+ // || defined(GENERATING_DOCUMENTATION)
+
+/// Read data into a dynamic buffer sequence until a function object indicates a
+/// match.
+
+/**
+ * This function is used to 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 call will block 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.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the match condition function object already indicates
+ * a match, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers A dynamic buffer sequence into which the data will be read.
+ *
+ * @param match_condition The function object to be called to determine whether
+ * a match exists. The signature of the function object must be:
+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);
+ * @endcode
+ * where @c iterator represents the type:
+ * @code buffers_iterator<typename DynamicBuffer::const_buffers_type>
+ * @endcode
+ * The iterator parameters @c begin and @c end define the range of bytes to be
+ * scanned to determine whether there is a match. The @c first member of the
+ * return value is an iterator marking one-past-the-end of the bytes that have
+ * been consumed by the match function. This iterator is used to calculate the
+ * @c begin parameter for any subsequent invocation of the match condition. The
+ * @c second member of the return value is true if a match has been found, false
+ * otherwise.
+ *
+ * @returns The number of bytes in the dynamic_buffer's get area that
+ * have been fully consumed by the match function.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note After a successful read_until operation, the dynamic buffer sequence
+ * may contain additional data beyond that which matched the function object.
+ * An application will typically leave that data in the dynamic buffer sequence
+ * for a subsequent read_until operation to examine.
+
+ * @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
+ * function objects.
+ *
+ * @par Examples
+ * To read data into a dynamic buffer sequence until whitespace is encountered:
+ * @code typedef boost::asio::buffers_iterator<
+ * boost::asio::const_buffers_1> iterator;
+ *
+ * std::pair<iterator, bool>
+ * match_whitespace(iterator begin, iterator end)
+ * {
+ * iterator i = begin;
+ * while (i != end)
+ * if (std::isspace(*i++))
+ * return std::make_pair(i, true);
+ * return std::make_pair(i, false);
+ * }
+ * ...
+ * std::string data;
+ * boost::asio::read_until(s, data, match_whitespace);
+ * @endcode
+ *
+ * To read data into a @c std::string until a matching character is found:
+ * @code class match_char
+ * {
+ * public:
+ * explicit match_char(char c) : c_(c) {}
+ *
+ * template <typename Iterator>
+ * std::pair<Iterator, bool> operator()(
+ * Iterator begin, Iterator end) const
+ * {
+ * Iterator i = begin;
+ * while (i != end)
+ * if (c_ == *i++)
+ * return std::make_pair(i, true);
+ * return std::make_pair(i, false);
+ * }
+ *
+ * private:
+ * char c_;
+ * };
+ *
+ * namespace asio {
+ * template <> struct is_match_condition<match_char>
+ * : public boost::true_type {};
+ * } // namespace asio
+ * ...
+ * std::string data;
+ * boost::asio::read_until(s, data, match_char('a'));
+ * @endcode
+ */
+template <typename SyncReadStream,
+ typename DynamicBuffer, typename MatchCondition>
+std::size_t read_until(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ MatchCondition match_condition,
+ typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);
+
+/// Read data into a dynamic buffer sequence until a function object indicates a
+/// match.
+/**
+ * This function is used to 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 call will block 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.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the match condition function object already indicates
+ * a match, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers A dynamic buffer sequence into which the data will be read.
+ *
+ * @param match_condition The function object to be called to determine whether
+ * a match exists. The signature of the function object must be:
+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);
+ * @endcode
+ * where @c iterator represents the type:
+ * @code buffers_iterator<DynamicBuffer::const_buffers_type>
+ * @endcode
+ * The iterator parameters @c begin and @c end define the range of bytes to be
+ * scanned to determine whether there is a match. The @c first member of the
+ * return value is an iterator marking one-past-the-end of the bytes that have
+ * been consumed by the match function. This iterator is used to calculate the
+ * @c begin parameter for any subsequent invocation of the match condition. The
+ * @c second member of the return value is true if a match has been found, false
+ * otherwise.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area that
+ * have been fully consumed by the match function. Returns 0 if an error
+ * occurred.
+ *
+ * @note After a successful read_until operation, the dynamic buffer sequence
+ * may contain additional data beyond that which matched the function object.
+ * An application will typically leave that data in the dynamic buffer sequence
+ * for a subsequent read_until operation to examine.
+ *
+ * @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
+ * function objects.
+ */
+template <typename SyncReadStream,
+ typename DynamicBuffer, typename MatchCondition>
+std::size_t read_until(SyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ MatchCondition match_condition, boost::system::error_code& ec,
+ typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);
+
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
/// Read data into a streambuf until it contains a specified delimiter.
/**
* This function is used to read data into the specified streambuf until the
@@ -113,8 +585,8 @@ struct is_match_condition
* contains the delimiter:
* @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode
* The call to @c std::getline then extracts the data up to and including the
- * delimiter, so that the string @c line contains:
- * @code { 'a', 'b', ..., 'c', '\n' } @endcode
+ * newline (which is discarded), so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c' } @endcode
* The remaining data is left in the buffer @c b as follows:
* @code { 'd', 'e', ... } @endcode
* This data may be the start of a new line, to be extracted by a subsequent
@@ -200,8 +672,8 @@ std::size_t read_until(SyncReadStream& s,
* contains the delimiter:
* @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
* The call to @c std::getline then extracts the data up to and including the
- * delimiter, so that the string @c line contains:
- * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * newline (which is discarded), so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r' } @endcode
* The remaining data is left in the buffer @c b as follows:
* @code { 'd', 'e', ... } @endcode
* This data may be the start of a new line, to be extracted by a subsequent
@@ -209,7 +681,8 @@ std::size_t read_until(SyncReadStream& s,
*/
template <typename SyncReadStream, typename Allocator>
std::size_t read_until(SyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, const std::string& delim);
+ boost::asio::basic_streambuf<Allocator>& b,
+ BOOST_ASIO_STRING_VIEW_PARAM delim);
/// Read data into a streambuf until it contains a specified delimiter.
/**
@@ -243,8 +716,8 @@ std::size_t read_until(SyncReadStream& s,
*/
template <typename SyncReadStream, typename Allocator>
std::size_t read_until(SyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, const std::string& delim,
- boost::system::error_code& ec);
+ boost::asio::basic_streambuf<Allocator>& b,
+ BOOST_ASIO_STRING_VIEW_PARAM delim, boost::system::error_code& ec);
#if defined(BOOST_ASIO_HAS_BOOST_REGEX) \
|| defined(GENERATING_DOCUMENTATION)
@@ -292,8 +765,8 @@ std::size_t read_until(SyncReadStream& s,
* contains the data which matched the regular expression:
* @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
* The call to @c std::getline then extracts the data up to and including the
- * match, so that the string @c line contains:
- * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * newline (which is discarded), so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r' } @endcode
* The remaining data is left in the buffer @c b as follows:
* @code { 'd', 'e', ... } @endcode
* This data may be the start of a new line, to be extracted by a subsequent
@@ -387,7 +860,8 @@ std::size_t read_until(SyncReadStream& s,
*
* @note After a successful read_until operation, the streambuf may contain
* additional data beyond that which matched the function object. An application
- * will typically leave that data in the streambuf for a subsequent
+ * will typically leave that data in the streambuf for a subsequent read_until
+ * operation to examine.
*
* @note The default implementation of the @c is_match_condition type trait
* evaluates to true for function pointers and function objects with a
@@ -491,7 +965,8 @@ std::size_t read_until(SyncReadStream& s,
*
* @note After a successful read_until operation, the streambuf may contain
* additional data beyond that which matched the function object. An application
- * will typically leave that data in the streambuf for a subsequent
+ * will typically leave that data in the streambuf for a subsequent read_until
+ * operation to examine.
*
* @note The default implementation of the @c is_match_condition type trait
* evaluates to true for function pointers and function objects with a
@@ -504,16 +979,440 @@ std::size_t read_until(SyncReadStream& s,
MatchCondition match_condition, boost::system::error_code& ec,
typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
/*@}*/
/**
* @defgroup async_read_until boost::asio::async_read_until
*
- * @brief Start an asynchronous operation to read data into a streambuf until it
- * contains a delimiter, matches a regular expression, or a function object
- * indicates a match.
+ * @brief Start an asynchronous operation to read data into a dynamic buffer
+ * sequence, or into a streambuf, until it contains a delimiter, matches a
+ * regular expression, or a function object indicates a match.
*/
/*@{*/
+/// 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:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. If
+ * the dynamic buffer sequence's get area already contains the delimiter, this
+ * asynchronous operation completes immediately. The program must ensure that
+ * the stream performs no other read operations (such as async_read,
+ * async_read_until, the stream's async_read_some function, or any other
+ * composed operations that perform reads) until this operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @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.
+ *
+ * @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:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::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. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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
+ * subsequent async_read_until operation to examine.
+ *
+ * @par Example
+ * To asynchronously read data into a @c std::string until a newline is
+ * encountered:
+ * @code std::string data;
+ * ...
+ * void handler(const boost::system::error_code& e, std::size_t size)
+ * {
+ * if (!e)
+ * {
+ * std::string line = data.substr(0, n);
+ * data.erase(0, n);
+ * ...
+ * }
+ * }
+ * ...
+ * boost::asio::async_read_until(s, data, '\n', handler); @endcode
+ * After the @c async_read_until operation completes successfully, the buffer
+ * @c data contains the delimiter:
+ * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the
+ * delimiter, so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the buffer @c data
+ * as follows:
+ * @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.
+ */
+template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ char delim, BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
+
+/// 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:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. If
+ * the dynamic buffer sequence's get area already contains the delimiter, this
+ * asynchronous operation completes immediately. The program must ensure that
+ * the stream performs no other read operations (such as async_read,
+ * async_read_until, the stream's async_read_some function, or any other
+ * composed operations that perform reads) until this operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @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.
+ *
+ * @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:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::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. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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
+ * subsequent async_read_until operation to examine.
+ *
+ * @par Example
+ * To asynchronously read data into a @c std::string until a CR-LF sequence is
+ * encountered:
+ * @code std::string data;
+ * ...
+ * void handler(const boost::system::error_code& e, std::size_t size)
+ * {
+ * if (!e)
+ * {
+ * std::string line = data.substr(0, n);
+ * data.erase(0, n);
+ * ...
+ * }
+ * }
+ * ...
+ * boost::asio::async_read_until(s, data, "\r\n", handler); @endcode
+ * After the @c async_read_until operation completes successfully, the string
+ * @c data contains the delimiter:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the
+ * delimiter, so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the string @c data
+ * as follows:
+ * @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.
+ */
+template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_STRING_VIEW_PARAM delim,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
+
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+#if defined(BOOST_ASIO_HAS_BOOST_REGEX) \
+ || defined(GENERATING_DOCUMENTATION)
+
+/// Start an asynchronous operation to read data into a dynamic buffer sequence
+/// until some part of its data matches a regular expression.
+/**
+ * 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:
+ *
+ * @li A substring of the dynamic buffer sequence's get area matches the regular
+ * expression.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. If
+ * the dynamic buffer sequence's get area already contains data that matches
+ * the regular expression, this asynchronous operation completes immediately.
+ * The program must ensure that the stream performs no other read operations
+ * (such as async_read, async_read_until, the stream's async_read_some
+ * function, or any other composed operations that perform reads) until this
+ * operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @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.
+ *
+ * @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:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::error_code& error,
+ *
+ * // The number of bytes in the dynamic buffer
+ * // sequence's get area up to and including the
+ * // substring that matches the regular expression.
+ * // 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. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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
+ * buffer sequence for a subsequent async_read_until operation to examine.
+ *
+ * @par Example
+ * To asynchronously read data into a @c std::string until a CR-LF sequence is
+ * encountered:
+ * @code std::string data;
+ * ...
+ * void handler(const boost::system::error_code& e, std::size_t size)
+ * {
+ * if (!e)
+ * {
+ * std::string line = data.substr(0, n);
+ * data.erase(0, n);
+ * ...
+ * }
+ * }
+ * ...
+ * boost::asio::async_read_until(s, data,
+ * boost::regex("\r\n"), handler); @endcode
+ * After the @c async_read_until operation completes successfully, the string
+ * @c data contains the data which matched the regular expression:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the match,
+ * so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the string @c data
+ * as follows:
+ * @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.
+ */
+template <typename AsyncReadStream,
+ typename DynamicBuffer, typename ReadHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ const boost::regex& expr,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
+
+#endif // defined(BOOST_ASIO_HAS_BOOST_REGEX)
+ // || defined(GENERATING_DOCUMENTATION)
+
+/// Start an asynchronous operation to read data into a dynamic buffer sequence
+/// until a function object indicates a match.
+/**
+ * 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:
+ *
+ * @li The match condition function object returns a std::pair where the second
+ * element evaluates to true.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. If
+ * the match condition function object already indicates a match, this
+ * asynchronous operation completes immediately. The program must ensure that
+ * the stream performs no other read operations (such as async_read,
+ * async_read_until, the stream's async_read_some function, or any other
+ * composed operations that perform reads) until this operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @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.
+ *
+ * @param match_condition The function object to be called to determine whether
+ * a match exists. The signature of the function object must be:
+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);
+ * @endcode
+ * where @c iterator represents the type:
+ * @code buffers_iterator<typename DynamicBuffer::const_buffers_type>
+ * @endcode
+ * The iterator parameters @c begin and @c end define the range of bytes to be
+ * scanned to determine whether there is a match. The @c first member of the
+ * return value is an iterator marking one-past-the-end of the bytes that have
+ * been consumed by the match function. This iterator is used to calculate the
+ * @c begin parameter for any subsequent invocation of the match condition. The
+ * @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:
+ * @code void handler(
+ * // Result of operation.
+ * const boost::system::error_code& error,
+ *
+ * // The number of bytes in the dynamic buffer sequence's
+ * // get area that have been fully consumed by the match
+ * // function. O 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. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @note After a successful async_read_until operation, the dynamic buffer
+ * sequence may contain additional data beyond that which matched the function
+ * object. An application will typically leave that data in the dynamic buffer
+ * sequence for a subsequent async_read_until operation to examine.
+ *
+ * @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
+ * function objects.
+ *
+ * @par Examples
+ * To asynchronously read data into a @c std::string until whitespace is
+ * encountered:
+ * @code typedef boost::asio::buffers_iterator<
+ * boost::asio::const_buffers_1> iterator;
+ *
+ * std::pair<iterator, bool>
+ * match_whitespace(iterator begin, iterator end)
+ * {
+ * iterator i = begin;
+ * while (i != end)
+ * if (std::isspace(*i++))
+ * return std::make_pair(i, true);
+ * return std::make_pair(i, false);
+ * }
+ * ...
+ * void handler(const boost::system::error_code& e, std::size_t size);
+ * ...
+ * std::string data;
+ * boost::asio::async_read_until(s, data, match_whitespace, handler);
+ * @endcode
+ *
+ * To asynchronously read data into a @c std::string until a matching character
+ * is found:
+ * @code class match_char
+ * {
+ * public:
+ * explicit match_char(char c) : c_(c) {}
+ *
+ * template <typename Iterator>
+ * std::pair<Iterator, bool> operator()(
+ * Iterator begin, Iterator end) const
+ * {
+ * Iterator i = begin;
+ * while (i != end)
+ * if (c_ == *i++)
+ * return std::make_pair(i, true);
+ * return std::make_pair(i, false);
+ * }
+ *
+ * private:
+ * char c_;
+ * };
+ *
+ * namespace asio {
+ * template <> struct is_match_condition<match_char>
+ * : public boost::true_type {};
+ * } // namespace asio
+ * ...
+ * void handler(const boost::system::error_code& e, std::size_t size);
+ * ...
+ * std::string data;
+ * boost::asio::async_read_until(s, data, match_char('a'), handler);
+ * @endcode
+ */
+template <typename AsyncReadStream, typename DynamicBuffer,
+ typename MatchCondition, typename ReadHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
+ typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);
+
+#if !defined(BOOST_ASIO_NO_IOSTREAM)
+
/// Start an asynchronous operation to read data into a streambuf until it
/// contains a specified delimiter.
/**
@@ -558,7 +1457,7 @@ std::size_t read_until(SyncReadStream& s,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @note After a successful async_read_until operation, the streambuf may
* contain additional data beyond the delimiter. An application will typically
@@ -585,8 +1484,8 @@ std::size_t read_until(SyncReadStream& s,
* @c b contains the delimiter:
* @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode
* The call to @c std::getline then extracts the data up to and including the
- * delimiter, so that the string @c line contains:
- * @code { 'a', 'b', ..., 'c', '\n' } @endcode
+ * newline (which is discarded), so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c' } @endcode
* The remaining data is left in the buffer @c b as follows:
* @code { 'd', 'e', ... } @endcode
* This data may be the start of a new line, to be extracted by a subsequent
@@ -643,7 +1542,7 @@ async_read_until(AsyncReadStream& s,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @note After a successful async_read_until operation, the streambuf may
* contain additional data beyond the delimiter. An application will typically
@@ -670,8 +1569,8 @@ async_read_until(AsyncReadStream& s,
* @c b contains the delimiter:
* @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
* The call to @c std::getline then extracts the data up to and including the
- * delimiter, so that the string @c line contains:
- * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * newline (which is discarded), so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r' } @endcode
* The remaining data is left in the buffer @c b as follows:
* @code { 'd', 'e', ... } @endcode
* This data may be the start of a new line, to be extracted by a subsequent
@@ -681,7 +1580,8 @@ template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
void (boost::system::error_code, std::size_t))
async_read_until(AsyncReadStream& s,
- boost::asio::basic_streambuf<Allocator>& b, const std::string& delim,
+ boost::asio::basic_streambuf<Allocator>& b,
+ BOOST_ASIO_STRING_VIEW_PARAM delim,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler);
#if defined(BOOST_ASIO_HAS_BOOST_REGEX) \
@@ -734,7 +1634,7 @@ async_read_until(AsyncReadStream& s,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @note After a successful async_read_until operation, the streambuf may
* contain additional data beyond that which matched the regular expression. An
@@ -762,8 +1662,8 @@ async_read_until(AsyncReadStream& s,
* @c b contains the data which matched the regular expression:
* @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
* The call to @c std::getline then extracts the data up to and including the
- * match, so that the string @c line contains:
- * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * newline (which is discarded), so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r' } @endcode
* The remaining data is left in the buffer @c b as follows:
* @code { 'd', 'e', ... } @endcode
* This data may be the start of a new line, to be extracted by a subsequent
@@ -836,7 +1736,7 @@ async_read_until(AsyncReadStream& s,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @note After a successful async_read_until operation, the streambuf may
* contain additional data beyond that which matched the function object. An
@@ -911,6 +1811,9 @@ async_read_until(AsyncReadStream& s,
MatchCondition match_condition, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);
+#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
/*@}*/
} // namespace asio
@@ -920,6 +1823,4 @@ async_read_until(AsyncReadStream& s,
#include <boost/asio/impl/read_until.hpp>
-#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
-
#endif // BOOST_ASIO_READ_UNTIL_HPP
diff --git a/boost/asio/seq_packet_socket_service.hpp b/boost/asio/seq_packet_socket_service.hpp
index fcccafe5ec..4688f3026a 100644
--- a/boost/asio/seq_packet_socket_service.hpp
+++ b/boost/asio/seq_packet_socket_service.hpp
@@ -16,11 +16,14 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <cstddef>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
# include <boost/asio/detail/null_socket_service.hpp>
@@ -39,7 +42,7 @@ namespace asio {
template <typename Protocol>
class seq_packet_socket_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<
seq_packet_socket_service<Protocol> >
@@ -48,7 +51,7 @@ class seq_packet_socket_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
/// The protocol type.
@@ -75,13 +78,6 @@ public:
typedef typename service_impl_type::implementation_type implementation_type;
#endif
- /// (Deprecated: Use native_handle_type.) The native socket type.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined native_type;
-#else
- typedef typename service_impl_type::native_handle_type native_type;
-#endif
-
/// The native socket type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
@@ -90,11 +86,11 @@ public:
#endif
/// Construct a new sequenced packet socket service for the specified
- /// io_service.
- explicit seq_packet_socket_service(boost::asio::io_service& io_service)
+ /// io_context.
+ explicit seq_packet_socket_service(boost::asio::io_context& io_context)
: boost::asio::detail::service_base<
- seq_packet_socket_service<Protocol> >(io_service),
- service_impl_(io_service)
+ seq_packet_socket_service<Protocol> >(io_context),
+ service_impl_(io_context)
{
}
@@ -145,22 +141,23 @@ public:
}
/// Open a sequenced packet socket.
- boost::system::error_code open(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl,
const protocol_type& protocol, boost::system::error_code& ec)
{
if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_SEQPACKET))
service_impl_.open(impl, protocol, ec);
else
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Assign an existing native socket to a sequenced packet socket.
- boost::system::error_code assign(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl,
const protocol_type& protocol, const native_handle_type& native_socket,
boost::system::error_code& ec)
{
- return service_impl_.assign(impl, protocol, native_socket, ec);
+ service_impl_.assign(impl, protocol, native_socket, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is open.
@@ -170,16 +167,18 @@ public:
}
/// Close a sequenced packet socket implementation.
- boost::system::error_code close(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.close(impl, ec);
+ service_impl_.close(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
- /// (Deprecated: Use native_handle().) Get the native socket implementation.
- native_type native(implementation_type& impl)
+ /// Release ownership of the underlying socket.
+ native_handle_type release(implementation_type& impl,
+ boost::system::error_code& ec)
{
- return service_impl_.native_handle(impl);
+ return service_impl_.release(impl, ec);
}
/// Get the native socket implementation.
@@ -189,10 +188,11 @@ public:
}
/// Cancel all asynchronous operations associated with the socket.
- boost::system::error_code cancel(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.cancel(impl, ec);
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is at the out-of-band data mark.
@@ -210,17 +210,19 @@ public:
}
/// Bind the sequenced packet socket to the specified local endpoint.
- boost::system::error_code bind(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID bind(implementation_type& impl,
const endpoint_type& endpoint, boost::system::error_code& ec)
{
- return service_impl_.bind(impl, endpoint, ec);
+ service_impl_.bind(impl, endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Connect the sequenced packet socket to the specified endpoint.
- boost::system::error_code connect(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID connect(implementation_type& impl,
const endpoint_type& peer_endpoint, boost::system::error_code& ec)
{
- return service_impl_.connect(impl, peer_endpoint, ec);
+ service_impl_.connect(impl, peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Start an asynchronous connect.
@@ -231,37 +233,39 @@ public:
const endpoint_type& peer_endpoint,
BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
{
- detail::async_result_init<
- ConnectHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
+ async_completion<ConnectHandler,
+ void (boost::system::error_code)> init(handler);
- service_impl_.async_connect(impl, peer_endpoint, init.handler);
+ service_impl_.async_connect(impl, peer_endpoint, init.completion_handler);
return init.result.get();
}
/// Set a socket option.
template <typename SettableSocketOption>
- boost::system::error_code set_option(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl,
const SettableSocketOption& option, boost::system::error_code& ec)
{
- return service_impl_.set_option(impl, option, ec);
+ service_impl_.set_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get a socket option.
template <typename GettableSocketOption>
- boost::system::error_code get_option(const implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl,
GettableSocketOption& option, boost::system::error_code& ec) const
{
- return service_impl_.get_option(impl, option, ec);
+ service_impl_.get_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform an IO control command on the socket.
template <typename IoControlCommand>
- boost::system::error_code io_control(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl,
IoControlCommand& command, boost::system::error_code& ec)
{
- return service_impl_.io_control(impl, command, ec);
+ service_impl_.io_control(impl, command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the socket.
@@ -271,10 +275,11 @@ public:
}
/// Sets the non-blocking mode of the socket.
- boost::system::error_code non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.non_blocking(impl, mode, ec);
+ service_impl_.non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the native socket implementation.
@@ -284,10 +289,11 @@ public:
}
/// Sets the non-blocking mode of the native socket implementation.
- boost::system::error_code native_non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.native_non_blocking(impl, mode, ec);
+ service_impl_.native_non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the local endpoint.
@@ -305,10 +311,36 @@ public:
}
/// Disable sends or receives on the socket.
- boost::system::error_code shutdown(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID shutdown(implementation_type& impl,
socket_base::shutdown_type what, boost::system::error_code& ec)
{
- return service_impl_.shutdown(impl, what, ec);
+ service_impl_.shutdown(impl, what, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
+ {
+ service_impl_.wait(impl, w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the socket to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(implementation_type& impl, socket_base::wait_type w,
+ BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ service_impl_.async_wait(impl, w, init.completion_handler);
+
+ return init.result.get();
}
/// Send the given data to the peer.
@@ -329,11 +361,10 @@ public:
socket_base::message_flags flags,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_send(impl, buffers, flags, init.handler);
+ service_impl_.async_send(impl, buffers, flags, init.completion_handler);
return init.result.get();
}
@@ -357,21 +388,20 @@ public:
socket_base::message_flags& out_flags,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
service_impl_.async_receive_with_flags(impl,
- buffers, in_flags, out_flags, init.handler);
+ buffers, in_flags, out_flags, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -383,4 +413,6 @@ private:
#include <boost/asio/detail/pop_options.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_SEQ_PACKET_SOCKET_SERVICE_HPP
diff --git a/boost/asio/serial_port.hpp b/boost/asio/serial_port.hpp
index f3b6fb2450..72a52a52b7 100644
--- a/boost/asio/serial_port.hpp
+++ b/boost/asio/serial_port.hpp
@@ -21,17 +21,750 @@
#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \
|| defined(GENERATING_DOCUMENTATION)
-#include <boost/asio/basic_serial_port.hpp>
+#include <string>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/serial_port_base.hpp>
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/basic_serial_port.hpp>
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# if defined(BOOST_ASIO_HAS_IOCP)
+# include <boost/asio/detail/win_iocp_serial_port_service.hpp>
+# define BOOST_ASIO_SVC_T detail::win_iocp_serial_port_service
+# else
+# include <boost/asio/detail/reactive_serial_port_service.hpp>
+# define BOOST_ASIO_SVC_T detail::reactive_serial_port_service
+# endif
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
-/// Typedef for the typical usage of a serial port.
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+// Typedef for the typical usage of a serial port.
typedef basic_serial_port<> serial_port;
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+/// Provides serial port functionality.
+/**
+ * The serial_port class provides a wrapper over serial port functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+class serial_port
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>,
+ public serial_port_base
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
+
+ /// The native representation of a serial port.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef BOOST_ASIO_SVC_T::native_handle_type native_handle_type;
+#endif
+
+ /// A basic_serial_port is always the lowest layer.
+ typedef serial_port lowest_layer_type;
+
+ /// Construct a serial_port without opening it.
+ /**
+ * This constructor creates a serial port without opening it.
+ *
+ * @param io_context The io_context object that the serial port will use to
+ * dispatch handlers for any asynchronous operations performed on the port.
+ */
+ explicit serial_port(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ }
+
+ /// Construct and open a serial_port.
+ /**
+ * This constructor creates and opens a serial port for the specified device
+ * name.
+ *
+ * @param io_context The io_context object that the serial port will use to
+ * dispatch handlers for any asynchronous operations performed on the port.
+ *
+ * @param device The platform-specific device name for this serial
+ * port.
+ */
+ explicit serial_port(boost::asio::io_context& io_context,
+ const char* device)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().open(this->get_implementation(), device, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct and open a serial_port.
+ /**
+ * This constructor creates and opens a serial port for the specified device
+ * name.
+ *
+ * @param io_context The io_context object that the serial port will use to
+ * dispatch handlers for any asynchronous operations performed on the port.
+ *
+ * @param device The platform-specific device name for this serial
+ * port.
+ */
+ explicit serial_port(boost::asio::io_context& io_context,
+ const std::string& device)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().open(this->get_implementation(), device, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Construct a serial_port on an existing native serial port.
+ /**
+ * This constructor creates a serial port object to hold an existing native
+ * serial port.
+ *
+ * @param io_context The io_context object that the serial port will use to
+ * dispatch handlers for any asynchronous operations performed on the port.
+ *
+ * @param native_serial_port A native serial port.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ serial_port(boost::asio::io_context& io_context,
+ const native_handle_type& native_serial_port)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ native_serial_port, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a serial_port from another.
+ /**
+ * This constructor moves a serial port from one object to another.
+ *
+ * @param other The other 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 serial_port(io_context&) constructor.
+ */
+ serial_port(serial_port&& other)
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
+ {
+ }
+
+ /// Move-assign a serial_port from another.
+ /**
+ * This assignment operator moves a serial port from one object to another.
+ *
+ * @param other The other 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 serial_port(io_context&) constructor.
+ */
+ serial_port& operator=(serial_port&& other)
+ {
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destroys the serial port.
+ /**
+ * This function destroys the serial port, cancelling any outstanding
+ * asynchronous wait operations associated with the serial port as if by
+ * calling @c cancel.
+ */
+ ~serial_port()
+ {
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::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 serial_port 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 serial_port 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;
+ }
+
+ /// Open the serial port using the specified device name.
+ /**
+ * This function opens the serial port for the specified device name.
+ *
+ * @param device The platform-specific device name.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void open(const std::string& device)
+ {
+ boost::system::error_code ec;
+ this->get_service().open(this->get_implementation(), device, ec);
+ boost::asio::detail::throw_error(ec, "open");
+ }
+
+ /// Open the serial port using the specified device name.
+ /**
+ * This function opens the serial port using the given platform-specific
+ * device name.
+ *
+ * @param device The platform-specific device name.
+ *
+ * @param ec Set the indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID open(const std::string& device,
+ boost::system::error_code& ec)
+ {
+ this->get_service().open(this->get_implementation(), device, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Assign an existing native serial port to the serial port.
+ /*
+ * This function opens the serial port to hold an existing native serial port.
+ *
+ * @param native_serial_port A native serial port.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const native_handle_type& native_serial_port)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(),
+ native_serial_port, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Assign an existing native serial port to the serial port.
+ /*
+ * This function opens the serial port to hold an existing native serial port.
+ *
+ * @param native_serial_port A native serial port.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& native_serial_port,
+ boost::system::error_code& ec)
+ {
+ this->get_service().assign(this->get_implementation(),
+ native_serial_port, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the serial port is open.
+ bool is_open() const
+ {
+ return this->get_service().is_open(this->get_implementation());
+ }
+
+ /// Close the serial port.
+ /**
+ * This function is used to close the serial port. Any asynchronous read or
+ * write operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->get_service().close(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "close");
+ }
+
+ /// Close the serial port.
+ /**
+ * This function is used to close the serial port. Any asynchronous read or
+ * write operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
+ {
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get the native serial port representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * serial port. This is intended to allow access to native serial port
+ * functionality that is not otherwise provided.
+ */
+ native_handle_type native_handle()
+ {
+ return this->get_service().native_handle(this->get_implementation());
+ }
+
+ /// Cancel all asynchronous operations associated with the serial port.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->get_service().cancel(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all asynchronous operations associated with the serial port.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
+ {
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Send a break sequence to the serial port.
+ /**
+ * This function causes a break sequence of platform-specific duration to be
+ * sent out the serial port.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void send_break()
+ {
+ boost::system::error_code ec;
+ this->get_service().send_break(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "send_break");
+ }
+
+ /// Send a break sequence to the serial port.
+ /**
+ * This function causes a break sequence of platform-specific duration to be
+ * sent out the serial port.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID send_break(boost::system::error_code& ec)
+ {
+ this->get_service().send_break(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Set an option on the serial port.
+ /**
+ * This function is used to set an option on the serial port.
+ *
+ * @param option The option value to be set on the serial port.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa SettableSerialPortOption @n
+ * boost::asio::serial_port_base::baud_rate @n
+ * boost::asio::serial_port_base::flow_control @n
+ * boost::asio::serial_port_base::parity @n
+ * boost::asio::serial_port_base::stop_bits @n
+ * boost::asio::serial_port_base::character_size
+ */
+ template <typename SettableSerialPortOption>
+ void set_option(const SettableSerialPortOption& option)
+ {
+ boost::system::error_code ec;
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "set_option");
+ }
+
+ /// Set an option on the serial port.
+ /**
+ * This function is used to set an option on the serial port.
+ *
+ * @param option The option value to be set on the serial port.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa SettableSerialPortOption @n
+ * boost::asio::serial_port_base::baud_rate @n
+ * boost::asio::serial_port_base::flow_control @n
+ * boost::asio::serial_port_base::parity @n
+ * boost::asio::serial_port_base::stop_bits @n
+ * boost::asio::serial_port_base::character_size
+ */
+ template <typename SettableSerialPortOption>
+ BOOST_ASIO_SYNC_OP_VOID set_option(const SettableSerialPortOption& option,
+ boost::system::error_code& ec)
+ {
+ this->get_service().set_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get an option from the serial port.
+ /**
+ * This function is used to get the current value of an option on the serial
+ * port.
+ *
+ * @param option The option value to be obtained from the serial port.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @sa GettableSerialPortOption @n
+ * boost::asio::serial_port_base::baud_rate @n
+ * boost::asio::serial_port_base::flow_control @n
+ * boost::asio::serial_port_base::parity @n
+ * boost::asio::serial_port_base::stop_bits @n
+ * boost::asio::serial_port_base::character_size
+ */
+ template <typename GettableSerialPortOption>
+ void get_option(GettableSerialPortOption& option)
+ {
+ boost::system::error_code ec;
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ boost::asio::detail::throw_error(ec, "get_option");
+ }
+
+ /// Get an option from the serial port.
+ /**
+ * This function is used to get the current value of an option on the serial
+ * port.
+ *
+ * @param option The option value to be obtained from the serial port.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @sa GettableSerialPortOption @n
+ * boost::asio::serial_port_base::baud_rate @n
+ * boost::asio::serial_port_base::flow_control @n
+ * boost::asio::serial_port_base::parity @n
+ * boost::asio::serial_port_base::stop_bits @n
+ * boost::asio::serial_port_base::character_size
+ */
+ template <typename GettableSerialPortOption>
+ BOOST_ASIO_SYNC_OP_VOID get_option(GettableSerialPortOption& option,
+ boost::system::error_code& ec)
+ {
+ this->get_service().get_option(this->get_implementation(), option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Write some data to the serial port.
+ /**
+ * This function is used to write data to the serial port. 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 serial port.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::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
+ * serial_port.write_some(boost::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)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().write_some(
+ this->get_implementation(), buffers, ec);
+ boost::asio::detail::throw_error(ec, "write_some");
+ return s;
+ }
+
+ /// Write some data to the serial port.
+ /**
+ * This function is used to write data to the serial port. 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 serial port.
+ *
+ * @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,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().write_some(
+ this->get_implementation(), buffers, ec);
+ }
+
+ /// Start an asynchronous write.
+ /**
+ * This function is used to asynchronously write data to the serial port.
+ * The function call 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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 handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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
+ * serial_port.async_write_some(boost::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, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_write_some(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_write_some(
+ this->get_implementation(), buffers, init.completion_handler);
+
+ return init.result.get();
+ }
+
+ /// Read some data from the serial port.
+ /**
+ * This function is used to read data from the serial port. 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 boost::system::system_error Thrown on failure. An error code of
+ * boost::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
+ * serial_port.read_some(boost::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)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().read_some(
+ this->get_implementation(), buffers, ec);
+ boost::asio::detail::throw_error(ec, "read_some");
+ return s;
+ }
+
+ /// Read some data from the serial port.
+ /**
+ * This function is used to read data from the serial port. 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,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().read_some(
+ this->get_implementation(), buffers, ec);
+ }
+
+ /// Start an asynchronous read.
+ /**
+ * This function is used to asynchronously read data from the serial port.
+ * The function call 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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 handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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
+ * serial_port.async_read_some(boost::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, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+ async_read_some(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_read_some(
+ this->get_implementation(), buffers, init.completion_handler);
+
+ return init.result.get();
+ }
+};
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
} // namespace asio
} // namespace boost
+#include <boost/asio/detail/pop_options.hpp>
+
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# undef BOOST_ASIO_SVC_T
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
// || defined(GENERATING_DOCUMENTATION)
diff --git a/boost/asio/serial_port_base.hpp b/boost/asio/serial_port_base.hpp
index 884c7ba95d..b2a8367023 100644
--- a/boost/asio/serial_port_base.hpp
+++ b/boost/asio/serial_port_base.hpp
@@ -55,10 +55,10 @@ public:
public:
explicit baud_rate(unsigned int rate = 0);
unsigned int value() const;
- BOOST_ASIO_DECL boost::system::error_code store(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID store(
BOOST_ASIO_OPTION_STORAGE& storage,
boost::system::error_code& ec) const;
- BOOST_ASIO_DECL boost::system::error_code load(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID load(
const BOOST_ASIO_OPTION_STORAGE& storage,
boost::system::error_code& ec);
private:
@@ -75,10 +75,10 @@ public:
enum type { none, software, hardware };
BOOST_ASIO_DECL explicit flow_control(type t = none);
type value() const;
- BOOST_ASIO_DECL boost::system::error_code store(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID store(
BOOST_ASIO_OPTION_STORAGE& storage,
boost::system::error_code& ec) const;
- BOOST_ASIO_DECL boost::system::error_code load(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID load(
const BOOST_ASIO_OPTION_STORAGE& storage,
boost::system::error_code& ec);
private:
@@ -95,10 +95,10 @@ public:
enum type { none, odd, even };
BOOST_ASIO_DECL explicit parity(type t = none);
type value() const;
- BOOST_ASIO_DECL boost::system::error_code store(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID store(
BOOST_ASIO_OPTION_STORAGE& storage,
boost::system::error_code& ec) const;
- BOOST_ASIO_DECL boost::system::error_code load(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID load(
const BOOST_ASIO_OPTION_STORAGE& storage,
boost::system::error_code& ec);
private:
@@ -115,10 +115,10 @@ public:
enum type { one, onepointfive, two };
BOOST_ASIO_DECL explicit stop_bits(type t = one);
type value() const;
- BOOST_ASIO_DECL boost::system::error_code store(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID store(
BOOST_ASIO_OPTION_STORAGE& storage,
boost::system::error_code& ec) const;
- BOOST_ASIO_DECL boost::system::error_code load(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID load(
const BOOST_ASIO_OPTION_STORAGE& storage,
boost::system::error_code& ec);
private:
@@ -134,10 +134,10 @@ public:
public:
BOOST_ASIO_DECL explicit character_size(unsigned int t = 8);
unsigned int value() const;
- BOOST_ASIO_DECL boost::system::error_code store(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID store(
BOOST_ASIO_OPTION_STORAGE& storage,
boost::system::error_code& ec) const;
- BOOST_ASIO_DECL boost::system::error_code load(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID load(
const BOOST_ASIO_OPTION_STORAGE& storage,
boost::system::error_code& ec);
private:
diff --git a/boost/asio/serial_port_service.hpp b/boost/asio/serial_port_service.hpp
index 20cb288b1b..88a1f16e4a 100644
--- a/boost/asio/serial_port_service.hpp
+++ b/boost/asio/serial_port_service.hpp
@@ -17,6 +17,8 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_SERIAL_PORT) \
|| defined(GENERATING_DOCUMENTATION)
@@ -26,7 +28,7 @@
#include <boost/asio/detail/reactive_serial_port_service.hpp>
#include <boost/asio/detail/win_iocp_serial_port_service.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/serial_port_base.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -37,7 +39,7 @@ namespace asio {
/// Default service implementation for a serial port.
class serial_port_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<serial_port_service>
#endif
@@ -45,7 +47,7 @@ class serial_port_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
private:
@@ -64,13 +66,6 @@ public:
typedef service_impl_type::implementation_type implementation_type;
#endif
- /// (Deprecated: Use native_handle_type.) The native handle type.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined native_type;
-#else
- typedef service_impl_type::native_handle_type native_type;
-#endif
-
/// The native handle type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
@@ -78,10 +73,10 @@ public:
typedef service_impl_type::native_handle_type native_handle_type;
#endif
- /// Construct a new serial port service for the specified io_service.
- explicit serial_port_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<serial_port_service>(io_service),
- service_impl_(io_service)
+ /// Construct a new serial port service for the specified io_context.
+ explicit serial_port_service(boost::asio::io_context& io_context)
+ : boost::asio::detail::service_base<serial_port_service>(io_context),
+ service_impl_(io_context)
{
}
@@ -115,17 +110,19 @@ public:
}
/// Open a serial port.
- boost::system::error_code open(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl,
const std::string& device, boost::system::error_code& ec)
{
- return service_impl_.open(impl, device, ec);
+ service_impl_.open(impl, device, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Assign an existing native handle to a serial port.
- boost::system::error_code assign(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl,
const native_handle_type& handle, boost::system::error_code& ec)
{
- return service_impl_.assign(impl, handle, ec);
+ service_impl_.assign(impl, handle, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the handle is open.
@@ -135,16 +132,11 @@ public:
}
/// Close a serial port implementation.
- boost::system::error_code close(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.close(impl, ec);
- }
-
- /// (Deprecated: Use native_handle().) Get the native handle implementation.
- native_type native(implementation_type& impl)
- {
- return service_impl_.native_handle(impl);
+ service_impl_.close(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the native handle implementation.
@@ -154,33 +146,37 @@ public:
}
/// Cancel all asynchronous operations associated with the handle.
- boost::system::error_code cancel(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.cancel(impl, ec);
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Set a serial port option.
template <typename SettableSerialPortOption>
- boost::system::error_code set_option(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl,
const SettableSerialPortOption& option, boost::system::error_code& ec)
{
- return service_impl_.set_option(impl, option, ec);
+ service_impl_.set_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get a serial port option.
template <typename GettableSerialPortOption>
- boost::system::error_code get_option(const implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl,
GettableSerialPortOption& option, boost::system::error_code& ec) const
{
- return service_impl_.get_option(impl, option, ec);
+ service_impl_.get_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Send a break sequence to the serial port.
- boost::system::error_code send_break(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID send_break(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.send_break(impl, ec);
+ service_impl_.send_break(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Write the given data to the stream.
@@ -199,11 +195,10 @@ public:
const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_write_some(impl, buffers, init.handler);
+ service_impl_.async_write_some(impl, buffers, init.completion_handler);
return init.result.get();
}
@@ -224,20 +219,19 @@ public:
const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_read_some(impl, buffers, init.handler);
+ service_impl_.async_read_some(impl, buffers, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -252,4 +246,6 @@ private:
#endif // defined(BOOST_ASIO_HAS_SERIAL_PORT)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_SERIAL_PORT_SERVICE_HPP
diff --git a/boost/asio/signal_set.hpp b/boost/asio/signal_set.hpp
index 422e4fca49..6d724e3fd2 100644
--- a/boost/asio/signal_set.hpp
+++ b/boost/asio/signal_set.hpp
@@ -16,13 +16,432 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/basic_signal_set.hpp>
+
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/basic_signal_set.hpp>
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/detail/signal_set_service.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
namespace boost {
namespace asio {
-/// Typedef for the typical usage of a signal set.
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+// Typedef for the typical usage of a signal set.
typedef basic_signal_set<> signal_set;
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+/// Provides signal functionality.
+/**
+ * The signal_set class provides the ability to perform an asynchronous wait
+ * for one or more signals to occur.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Example
+ * Performing an asynchronous wait:
+ * @code
+ * void handler(
+ * const boost::system::error_code& error,
+ * int signal_number)
+ * {
+ * if (!error)
+ * {
+ * // A signal occurred.
+ * }
+ * }
+ *
+ * ...
+ *
+ * // Construct a signal set registered for process termination.
+ * boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
+ *
+ * // Start an asynchronous wait for one of the signals to occur.
+ * signals.async_wait(handler);
+ * @endcode
+ *
+ * @par Queueing of signal notifications
+ *
+ * If a signal is registered with a signal_set, and the signal occurs when
+ * there are no waiting handlers, then the signal notification is queued. The
+ * next async_wait operation on that signal_set will dequeue the notification.
+ * If multiple notifications are queued, subsequent async_wait operations
+ * dequeue them one at a time. Signal notifications are dequeued in order of
+ * ascending signal number.
+ *
+ * If a signal number is removed from a signal_set (using the @c remove or @c
+ * erase member functions) then any queued notifications for that signal are
+ * discarded.
+ *
+ * @par Multiple registration of signals
+ *
+ * The same signal number may be registered with different signal_set objects.
+ * When the signal occurs, one handler is called for each signal_set object.
+ *
+ * Note that multiple registration only works for signals that are registered
+ * using Asio. The application must not also register a signal handler using
+ * functions such as @c signal() or @c sigaction().
+ *
+ * @par Signal masking on POSIX platforms
+ *
+ * POSIX allows signals to be blocked using functions such as @c sigprocmask()
+ * and @c pthread_sigmask(). For signals to be delivered, programs must ensure
+ * that any signals registered using signal_set objects are unblocked in at
+ * least one thread.
+ */
+class signal_set
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<detail::signal_set_service>
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
+
+ /// Construct a signal set without adding any signals.
+ /**
+ * This constructor creates a signal set without registering for any signals.
+ *
+ * @param io_context The io_context object that the signal set will use to
+ * dispatch handlers for any asynchronous operations performed on the set.
+ */
+ explicit signal_set(boost::asio::io_context& io_context)
+ : basic_io_object<detail::signal_set_service>(io_context)
+ {
+ }
+
+ /// Construct a signal set and add one signal.
+ /**
+ * This constructor creates a signal set and registers for one signal.
+ *
+ * @param io_context The io_context object that the signal set will use to
+ * dispatch handlers for any asynchronous operations performed on the set.
+ *
+ * @param signal_number_1 The signal number to be added.
+ *
+ * @note This constructor is equivalent to performing:
+ * @code boost::asio::signal_set signals(io_context);
+ * signals.add(signal_number_1); @endcode
+ */
+ signal_set(boost::asio::io_context& io_context, int signal_number_1)
+ : basic_io_object<detail::signal_set_service>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().add(this->get_implementation(), signal_number_1, ec);
+ boost::asio::detail::throw_error(ec, "add");
+ }
+
+ /// Construct a signal set and add two signals.
+ /**
+ * This constructor creates a signal set and registers for two signals.
+ *
+ * @param io_context The io_context object that the signal set will use to
+ * dispatch handlers for any asynchronous operations performed on the set.
+ *
+ * @param signal_number_1 The first signal number to be added.
+ *
+ * @param signal_number_2 The second signal number to be added.
+ *
+ * @note This constructor is equivalent to performing:
+ * @code boost::asio::signal_set signals(io_context);
+ * signals.add(signal_number_1);
+ * signals.add(signal_number_2); @endcode
+ */
+ signal_set(boost::asio::io_context& io_context, int signal_number_1,
+ int signal_number_2)
+ : basic_io_object<detail::signal_set_service>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().add(this->get_implementation(), signal_number_1, ec);
+ boost::asio::detail::throw_error(ec, "add");
+ this->get_service().add(this->get_implementation(), signal_number_2, ec);
+ boost::asio::detail::throw_error(ec, "add");
+ }
+
+ /// Construct a signal set and add three signals.
+ /**
+ * This constructor creates a signal set and registers for three signals.
+ *
+ * @param io_context The io_context object that the signal set will use to
+ * dispatch handlers for any asynchronous operations performed on the set.
+ *
+ * @param signal_number_1 The first signal number to be added.
+ *
+ * @param signal_number_2 The second signal number to be added.
+ *
+ * @param signal_number_3 The third signal number to be added.
+ *
+ * @note This constructor is equivalent to performing:
+ * @code boost::asio::signal_set signals(io_context);
+ * signals.add(signal_number_1);
+ * signals.add(signal_number_2);
+ * signals.add(signal_number_3); @endcode
+ */
+ signal_set(boost::asio::io_context& io_context, int signal_number_1,
+ int signal_number_2, int signal_number_3)
+ : basic_io_object<detail::signal_set_service>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().add(this->get_implementation(), signal_number_1, ec);
+ boost::asio::detail::throw_error(ec, "add");
+ this->get_service().add(this->get_implementation(), signal_number_2, ec);
+ boost::asio::detail::throw_error(ec, "add");
+ this->get_service().add(this->get_implementation(), signal_number_3, ec);
+ boost::asio::detail::throw_error(ec, "add");
+ }
+
+ /// Destroys the signal set.
+ /**
+ * This function destroys the signal set, cancelling any outstanding
+ * asynchronous wait operations associated with the signal set as if by
+ * calling @c cancel.
+ */
+ ~signal_set()
+ {
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<detail::signal_set_service>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<detail::signal_set_service>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<detail::signal_set_service>::get_executor();
+ }
+
+ /// Add a signal to a signal_set.
+ /**
+ * This function adds the specified signal to the set. It has no effect if the
+ * signal is already in the set.
+ *
+ * @param signal_number The signal to be added to the set.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void add(int signal_number)
+ {
+ boost::system::error_code ec;
+ this->get_service().add(this->get_implementation(), signal_number, ec);
+ boost::asio::detail::throw_error(ec, "add");
+ }
+
+ /// Add a signal to a signal_set.
+ /**
+ * This function adds the specified signal to the set. It has no effect if the
+ * signal is already in the set.
+ *
+ * @param signal_number The signal to be added to the set.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID add(int signal_number,
+ boost::system::error_code& ec)
+ {
+ this->get_service().add(this->get_implementation(), signal_number, ec);
+ BOOST_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
+ * if the signal is not in the set.
+ *
+ * @param signal_number The signal to be removed from the set.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note Removes any notifications that have been queued for the specified
+ * signal number.
+ */
+ void remove(int signal_number)
+ {
+ boost::system::error_code ec;
+ this->get_service().remove(this->get_implementation(), signal_number, ec);
+ boost::asio::detail::throw_error(ec, "remove");
+ }
+
+ /// Remove a signal from a signal_set.
+ /**
+ * This function removes the specified signal from the set. It has no effect
+ * if the signal is not in the set.
+ *
+ * @param signal_number The signal to be removed from the set.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note Removes any notifications that have been queued for the specified
+ * signal number.
+ */
+ BOOST_ASIO_SYNC_OP_VOID remove(int signal_number,
+ boost::system::error_code& ec)
+ {
+ this->get_service().remove(this->get_implementation(), signal_number, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Remove all signals from a signal_set.
+ /**
+ * This function removes all signals from the set. It has no effect if the set
+ * is already empty.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note Removes all queued notifications.
+ */
+ void clear()
+ {
+ boost::system::error_code ec;
+ this->get_service().clear(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "clear");
+ }
+
+ /// Remove all signals from a signal_set.
+ /**
+ * This function removes all signals from the set. It has no effect if the set
+ * is already empty.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note Removes all queued notifications.
+ */
+ BOOST_ASIO_SYNC_OP_VOID clear(boost::system::error_code& ec)
+ {
+ this->get_service().clear(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Cancel all operations associated with the signal set.
+ /**
+ * This function forces the completion of any pending asynchronous wait
+ * operations against the signal set. The handler for each cancelled
+ * operation will be invoked with the boost::asio::error::operation_aborted
+ * error code.
+ *
+ * Cancellation does not alter the set of registered signals.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note If a registered signal occurred before cancel() is called, then the
+ * handlers for asynchronous wait operations will:
+ *
+ * @li have already been invoked; or
+ *
+ * @li have been queued for invocation in the near future.
+ *
+ * These handlers can no longer be cancelled, and therefore are passed an
+ * error code that indicates the successful completion of the wait operation.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->get_service().cancel(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all operations associated with the signal set.
+ /**
+ * This function forces the completion of any pending asynchronous wait
+ * operations against the signal set. The handler for each cancelled
+ * operation will be invoked with the boost::asio::error::operation_aborted
+ * error code.
+ *
+ * Cancellation does not alter the set of registered signals.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @note If a registered signal occurred before cancel() is called, then the
+ * handlers for asynchronous wait operations will:
+ *
+ * @li have already been invoked; or
+ *
+ * @li have been queued for invocation in the near future.
+ *
+ * These handlers can no longer be cancelled, and therefore are passed an
+ * error code that indicates the successful completion of the wait operation.
+ */
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
+ {
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// 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.
+ *
+ * For each call to async_wait(), the supplied handler will be called exactly
+ * once. The 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 boost::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:
+ * @code void handler(
+ * const boost::system::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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ */
+ template <typename SignalHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(SignalHandler,
+ void (boost::system::error_code, int))
+ async_wait(BOOST_ASIO_MOVE_ARG(SignalHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a SignalHandler.
+ BOOST_ASIO_SIGNAL_HANDLER_CHECK(SignalHandler, handler) type_check;
+
+ async_completion<SignalHandler,
+ void (boost::system::error_code, int)> init(handler);
+
+ this->get_service().async_wait(this->get_implementation(),
+ init.completion_handler);
+
+ return init.result.get();
+ }
+};
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
} // namespace asio
} // namespace boost
diff --git a/boost/asio/signal_set_service.hpp b/boost/asio/signal_set_service.hpp
index 632eaf0aca..705b32cc42 100644
--- a/boost/asio/signal_set_service.hpp
+++ b/boost/asio/signal_set_service.hpp
@@ -16,10 +16,13 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/signal_set_service.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -29,7 +32,7 @@ namespace asio {
/// Default service implementation for a signal set.
class signal_set_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<signal_set_service>
#endif
@@ -37,7 +40,7 @@ class signal_set_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
public:
@@ -48,10 +51,10 @@ public:
typedef detail::signal_set_service::implementation_type implementation_type;
#endif
- /// Construct a new signal set service for the specified io_service.
- explicit signal_set_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<signal_set_service>(io_service),
- service_impl_(io_service)
+ /// Construct a new signal set service for the specified io_context.
+ explicit signal_set_service(boost::asio::io_context& io_context)
+ : boost::asio::detail::service_base<signal_set_service>(io_context),
+ service_impl_(io_context)
{
}
@@ -68,31 +71,35 @@ public:
}
/// Add a signal to a signal_set.
- boost::system::error_code add(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID add(implementation_type& impl,
int signal_number, boost::system::error_code& ec)
{
- return service_impl_.add(impl, signal_number, ec);
+ service_impl_.add(impl, signal_number, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Remove a signal to a signal_set.
- boost::system::error_code remove(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID remove(implementation_type& impl,
int signal_number, boost::system::error_code& ec)
{
- return service_impl_.remove(impl, signal_number, ec);
+ service_impl_.remove(impl, signal_number, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Remove all signals from a signal_set.
- boost::system::error_code clear(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID clear(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.clear(impl, ec);
+ service_impl_.clear(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Cancel all operations associated with the signal set.
- boost::system::error_code cancel(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.cancel(impl, ec);
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
// Start an asynchronous operation to wait for a signal to be delivered.
@@ -102,26 +109,25 @@ public:
async_wait(implementation_type& impl,
BOOST_ASIO_MOVE_ARG(SignalHandler) handler)
{
- detail::async_result_init<
- SignalHandler, void (boost::system::error_code, int)> init(
- BOOST_ASIO_MOVE_CAST(SignalHandler)(handler));
+ async_completion<SignalHandler,
+ void (boost::system::error_code, int)> init(handler);
- service_impl_.async_wait(impl, init.handler);
+ service_impl_.async_wait(impl, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// Perform any fork-related housekeeping.
- void fork_service(boost::asio::io_service::fork_event event)
+ void notify_fork(boost::asio::io_context::fork_event event)
{
- service_impl_.fork_service(event);
+ service_impl_.notify_fork(event);
}
// The platform-specific implementation.
@@ -133,4 +139,6 @@ private:
#include <boost/asio/detail/pop_options.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_SIGNAL_SET_SERVICE_HPP
diff --git a/boost/asio/socket_acceptor_service.hpp b/boost/asio/socket_acceptor_service.hpp
index e00c76c901..34adc178df 100644
--- a/boost/asio/socket_acceptor_service.hpp
+++ b/boost/asio/socket_acceptor_service.hpp
@@ -16,10 +16,13 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <boost/asio/basic_socket.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
# include <boost/asio/detail/null_socket_service.hpp>
@@ -38,7 +41,7 @@ namespace asio {
template <typename Protocol>
class socket_acceptor_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<socket_acceptor_service<Protocol> >
#endif
@@ -46,7 +49,7 @@ class socket_acceptor_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
/// The protocol type.
@@ -73,13 +76,6 @@ public:
typedef typename service_impl_type::implementation_type implementation_type;
#endif
- /// (Deprecated: Use native_handle_type.) The native acceptor type.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined native_type;
-#else
- typedef typename service_impl_type::native_handle_type native_type;
-#endif
-
/// The native acceptor type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
@@ -87,11 +83,11 @@ public:
typedef typename service_impl_type::native_handle_type native_handle_type;
#endif
- /// Construct a new socket acceptor service for the specified io_service.
- explicit socket_acceptor_service(boost::asio::io_service& io_service)
+ /// Construct a new socket acceptor service for the specified io_context.
+ explicit socket_acceptor_service(boost::asio::io_context& io_context)
: boost::asio::detail::service_base<
- socket_acceptor_service<Protocol> >(io_service),
- service_impl_(io_service)
+ socket_acceptor_service<Protocol> >(io_context),
+ service_impl_(io_context)
{
}
@@ -142,18 +138,20 @@ public:
}
/// Open a new socket acceptor implementation.
- boost::system::error_code open(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl,
const protocol_type& protocol, boost::system::error_code& ec)
{
- return service_impl_.open(impl, protocol, ec);
+ service_impl_.open(impl, protocol, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Assign an existing native acceptor to a socket acceptor.
- boost::system::error_code assign(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl,
const protocol_type& protocol, const native_handle_type& native_acceptor,
boost::system::error_code& ec)
{
- return service_impl_.assign(impl, protocol, native_acceptor, ec);
+ service_impl_.assign(impl, protocol, native_acceptor, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the acceptor is open.
@@ -163,38 +161,43 @@ public:
}
/// Cancel all asynchronous operations associated with the acceptor.
- boost::system::error_code cancel(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.cancel(impl, ec);
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Bind the socket acceptor to the specified local endpoint.
- boost::system::error_code bind(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID bind(implementation_type& impl,
const endpoint_type& endpoint, boost::system::error_code& ec)
{
- return service_impl_.bind(impl, endpoint, ec);
+ service_impl_.bind(impl, endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Place the socket acceptor into the state where it will listen for new
/// connections.
- boost::system::error_code listen(implementation_type& impl, int backlog,
+ BOOST_ASIO_SYNC_OP_VOID listen(implementation_type& impl, int backlog,
boost::system::error_code& ec)
{
- return service_impl_.listen(impl, backlog, ec);
+ service_impl_.listen(impl, backlog, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Close a socket acceptor implementation.
- boost::system::error_code close(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.close(impl, ec);
+ service_impl_.close(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
- /// (Deprecated: Use native_handle().) Get the native acceptor implementation.
- native_type native(implementation_type& impl)
+ /// Release ownership of the underlying acceptor.
+ native_handle_type release(implementation_type& impl,
+ boost::system::error_code& ec)
{
- return service_impl_.native_handle(impl);
+ return service_impl_.release(impl, ec);
}
/// Get the native acceptor implementation.
@@ -205,26 +208,29 @@ public:
/// Set a socket option.
template <typename SettableSocketOption>
- boost::system::error_code set_option(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl,
const SettableSocketOption& option, boost::system::error_code& ec)
{
- return service_impl_.set_option(impl, option, ec);
+ service_impl_.set_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get a socket option.
template <typename GettableSocketOption>
- boost::system::error_code get_option(const implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl,
GettableSocketOption& option, boost::system::error_code& ec) const
{
- return service_impl_.get_option(impl, option, ec);
+ service_impl_.get_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform an IO control command on the socket.
template <typename IoControlCommand>
- boost::system::error_code io_control(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl,
IoControlCommand& command, boost::system::error_code& ec)
{
- return service_impl_.io_control(impl, command, ec);
+ service_impl_.io_control(impl, command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the acceptor.
@@ -234,10 +240,11 @@ public:
}
/// Sets the non-blocking mode of the acceptor.
- boost::system::error_code non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.non_blocking(impl, mode, ec);
+ service_impl_.non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the native acceptor implementation.
@@ -247,10 +254,11 @@ public:
}
/// Sets the non-blocking mode of the native acceptor implementation.
- boost::system::error_code native_non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.native_non_blocking(impl, mode, ec);
+ service_impl_.native_non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the local endpoint.
@@ -260,15 +268,51 @@ public:
return service_impl_.local_endpoint(impl, ec);
}
+ /// Wait for the acceptor to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
+ {
+ service_impl_.wait(impl, w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the acceptor to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(implementation_type& impl, socket_base::wait_type w,
+ BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ service_impl_.async_wait(impl, w, init.completion_handler);
+
+ return init.result.get();
+ }
+
/// Accept a new connection.
template <typename Protocol1, typename SocketService>
- boost::system::error_code accept(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID accept(implementation_type& impl,
basic_socket<Protocol1, SocketService>& peer,
endpoint_type* peer_endpoint, boost::system::error_code& ec,
typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
{
- return service_impl_.accept(impl, peer, peer_endpoint, ec);
+ service_impl_.accept(impl, peer, peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Accept a new connection.
+ typename Protocol::socket accept(implementation_type& impl,
+ io_context* peer_io_context, endpoint_type* peer_endpoint,
+ boost::system::error_code& ec)
+ {
+ return service_impl_.accept(impl, peer_io_context, peer_endpoint, ec);
}
+#endif // defined(BOOST_ASIO_HAS_MOVE)
/// Start an asynchronous accept.
template <typename Protocol1, typename SocketService, typename AcceptHandler>
@@ -280,20 +324,40 @@ public:
BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
typename enable_if<is_convertible<Protocol, Protocol1>::value>::type* = 0)
{
- detail::async_result_init<
- AcceptHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
+ async_completion<AcceptHandler,
+ void (boost::system::error_code)> init(handler);
+
+ service_impl_.async_accept(impl,
+ peer, peer_endpoint, init.completion_handler);
+
+ return init.result.get();
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+ /// Start an asynchronous accept.
+ template <typename MoveAcceptHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(MoveAcceptHandler,
+ void (boost::system::error_code, typename Protocol::socket))
+ async_accept(implementation_type& impl,
+ boost::asio::io_context* peer_io_context, endpoint_type* peer_endpoint,
+ BOOST_ASIO_MOVE_ARG(MoveAcceptHandler) handler)
+ {
+ async_completion<MoveAcceptHandler,
+ void (boost::system::error_code,
+ typename Protocol::socket)> init(handler);
- service_impl_.async_accept(impl, peer, peer_endpoint, init.handler);
+ service_impl_.async_accept(impl,
+ peer_io_context, peer_endpoint, init.completion_handler);
return init.result.get();
}
+#endif // defined(BOOST_ASIO_HAS_MOVE)
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -305,4 +369,6 @@ private:
#include <boost/asio/detail/pop_options.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_SOCKET_ACCEPTOR_SERVICE_HPP
diff --git a/boost/asio/socket_base.hpp b/boost/asio/socket_base.hpp
index 7adbf5abfd..9c7518e68e 100644
--- a/boost/asio/socket_base.hpp
+++ b/boost/asio/socket_base.hpp
@@ -76,6 +76,22 @@ public:
message_end_of_record = BOOST_ASIO_OS_DEF(MSG_EOR));
#endif
+ /// Wait types.
+ /**
+ * For use with basic_socket::wait() and basic_socket::async_wait().
+ */
+ enum wait_type
+ {
+ /// Wait for a socket to become ready to read.
+ wait_read,
+
+ /// Wait for a socket to become ready to write.
+ wait_write,
+
+ /// Wait for a socket to have error conditions pending.
+ wait_error
+ };
+
/// Socket option to permit sending of broadcast messages.
/**
* Implements the SOL_SOCKET/SO_BROADCAST socket option.
@@ -83,7 +99,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::socket_base::broadcast option(true);
* socket.set_option(option);
@@ -92,7 +108,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::socket_base::broadcast option;
* socket.get_option(option);
@@ -117,7 +133,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::debug option(true);
* socket.set_option(option);
@@ -126,7 +142,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::debug option;
* socket.get_option(option);
@@ -150,7 +166,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::socket_base::do_not_route option(true);
* socket.set_option(option);
@@ -159,7 +175,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::udp::socket socket(io_service);
+ * boost::asio::ip::udp::socket socket(io_context);
* ...
* boost::asio::socket_base::do_not_route option;
* socket.get_option(option);
@@ -184,7 +200,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::keep_alive option(true);
* socket.set_option(option);
@@ -193,7 +209,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::keep_alive option;
* socket.get_option(option);
@@ -217,7 +233,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::send_buffer_size option(8192);
* socket.set_option(option);
@@ -226,7 +242,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::send_buffer_size option;
* socket.get_option(option);
@@ -251,7 +267,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::send_low_watermark option(1024);
* socket.set_option(option);
@@ -260,7 +276,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::send_low_watermark option;
* socket.get_option(option);
@@ -285,7 +301,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::receive_buffer_size option(8192);
* socket.set_option(option);
@@ -294,7 +310,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::receive_buffer_size option;
* socket.get_option(option);
@@ -319,7 +335,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::receive_low_watermark option(1024);
* socket.set_option(option);
@@ -328,7 +344,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::receive_low_watermark option;
* socket.get_option(option);
@@ -354,7 +370,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::asio::socket_base::reuse_address option(true);
* acceptor.set_option(option);
@@ -363,7 +379,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::asio::socket_base::reuse_address option;
* acceptor.get_option(option);
@@ -389,7 +405,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::linger option(true, 30);
* socket.set_option(option);
@@ -398,7 +414,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::linger option;
* socket.get_option(option);
@@ -417,6 +433,40 @@ public:
linger;
#endif
+ /// Socket option for putting received out-of-band data inline.
+ /**
+ * Implements the SOL_SOCKET/SO_OOBINLINE socket option.
+ *
+ * @par Examples
+ * Setting the option:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::socket_base::out_of_band_inline option(true);
+ * socket.set_option(option);
+ * @endcode
+ *
+ * @par
+ * Getting the current option value:
+ * @code
+ * boost::asio::ip::tcp::socket socket(io_context);
+ * ...
+ * boost::asio::socket_base::out_of_band_inline option;
+ * socket.get_option(option);
+ * bool value = option.value();
+ * @endcode
+ *
+ * @par Concepts:
+ * Socket_Option, Boolean_Socket_Option.
+ */
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined out_of_band_inline;
+#else
+ typedef boost::asio::detail::socket_option::boolean<
+ BOOST_ASIO_OS_DEF(SOL_SOCKET), BOOST_ASIO_OS_DEF(SO_OOBINLINE)>
+ out_of_band_inline;
+#endif
+
/// Socket option to report aborted connections on accept.
/**
* Implements a custom socket option that determines whether or not an accept
@@ -426,7 +476,7 @@ public:
* @par Examples
* Setting the option:
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::asio::socket_base::enable_connection_aborted option(true);
* acceptor.set_option(option);
@@ -435,7 +485,7 @@ public:
* @par
* Getting the current option value:
* @code
- * boost::asio::ip::tcp::acceptor acceptor(io_service);
+ * boost::asio::ip::tcp::acceptor acceptor(io_context);
* ...
* boost::asio::socket_base::enable_connection_aborted option;
* acceptor.get_option(option);
@@ -454,28 +504,6 @@ public:
enable_connection_aborted;
#endif
- /// (Deprecated: Use non_blocking().) IO control command to
- /// set the blocking mode of the socket.
- /**
- * Implements the FIONBIO IO control command.
- *
- * @par Example
- * @code
- * boost::asio::ip::tcp::socket socket(io_service);
- * ...
- * boost::asio::socket_base::non_blocking_io command(true);
- * socket.io_control(command);
- * @endcode
- *
- * @par Concepts:
- * IO_Control_Command, Boolean_IO_Control_Command.
- */
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined non_blocking_io;
-#else
- typedef boost::asio::detail::io_control::non_blocking_io non_blocking_io;
-#endif
-
/// IO control command to get the amount of data that can be read without
/// blocking.
/**
@@ -483,7 +511,7 @@ public:
*
* @par Example
* @code
- * boost::asio::ip::tcp::socket socket(io_service);
+ * boost::asio::ip::tcp::socket socket(io_context);
* ...
* boost::asio::socket_base::bytes_readable command(true);
* socket.io_control(command);
@@ -501,11 +529,22 @@ public:
/// The maximum length of the queue of pending incoming connections.
#if defined(GENERATING_DOCUMENTATION)
+ static const int max_listen_connections = implementation_defined;
+#else
+ BOOST_ASIO_STATIC_CONSTANT(int, max_listen_connections
+ = BOOST_ASIO_OS_DEF(SOMAXCONN));
+#endif
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use max_listen_connections.) The maximum length of the queue
+ /// of pending incoming connections.
+#if defined(GENERATING_DOCUMENTATION)
static const int max_connections = implementation_defined;
#else
BOOST_ASIO_STATIC_CONSTANT(int, max_connections
= BOOST_ASIO_OS_DEF(SOMAXCONN));
#endif
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
protected:
/// Protected destructor to prevent deletion through this type.
diff --git a/boost/asio/spawn.hpp b/boost/asio/spawn.hpp
index 966bd3efcc..093b4ec350 100644
--- a/boost/asio/spawn.hpp
+++ b/boost/asio/spawn.hpp
@@ -17,9 +17,13 @@
#include <boost/asio/detail/config.hpp>
#include <boost/coroutine/all.hpp>
-#include <boost/asio/detail/weak_ptr.hpp>
+#include <boost/asio/bind_executor.hpp>
+#include <boost/asio/detail/memory.hpp>
+#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/wrapped_handler.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/executor.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/is_executor.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -95,6 +99,19 @@ public:
{
}
+ /// Construct a yield context from another yield context type.
+ /**
+ * Requires that OtherHandler be convertible to Handler.
+ */
+ template <typename OtherHandler>
+ basic_yield_context(const basic_yield_context<OtherHandler>& other)
+ : coro_(other.coro_),
+ ca_(other.ca_),
+ handler_(other.handler_),
+ ec_(other.ec_)
+ {
+ }
+
/// Return a yield context that sets the specified error_code.
/**
* By default, when a yield context is used with an asynchronous operation, a
@@ -126,7 +143,7 @@ private:
#endif // defined(GENERATING_DOCUMENTATION)
detail::weak_ptr<callee_type> coro_;
caller_type& ca_;
- Handler& handler_;
+ Handler handler_;
boost::system::error_code* ec_;
};
@@ -135,9 +152,7 @@ private:
typedef basic_yield_context<unspecified> yield_context;
#else // defined(GENERATING_DOCUMENTATION)
typedef basic_yield_context<
- detail::wrapped_handler<
- io_service::strand, void(*)(),
- detail::is_continuation_if_running> > yield_context;
+ executor_binder<void(*)(), executor> > yield_context;
#endif // defined(GENERATING_DOCUMENTATION)
/**
@@ -181,6 +196,21 @@ typedef basic_yield_context<
/**
* 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
+ *
+ * @param attributes Boost.Coroutine attributes used to customise the coroutine.
+ */
+template <typename Function>
+void spawn(BOOST_ASIO_MOVE_ARG(Function) function,
+ const boost::coroutines::attributes& attributes
+ = boost::coroutines::attributes());
+
+/// Start a new stackful coroutine, calling the specified handler when it
+/// completes.
+/**
+ * This function is used to launch a new coroutine.
+ *
* @param handler A handler to be called when the coroutine exits. More
* importantly, the handler provides an execution context (via the the handler
* invocation hook) for the coroutine. The handler must have the signature:
@@ -195,7 +225,9 @@ template <typename Handler, typename Function>
void spawn(BOOST_ASIO_MOVE_ARG(Handler) handler,
BOOST_ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes
- = boost::coroutines::attributes());
+ = boost::coroutines::attributes(),
+ typename enable_if<!is_executor<typename decay<Handler>::type>::value &&
+ !is_convertible<Handler&, execution_context&>::value>::type* = 0);
/// Start a new stackful coroutine, inheriting the execution context of another.
/**
@@ -218,31 +250,49 @@ void spawn(basic_yield_context<Handler> ctx,
const boost::coroutines::attributes& attributes
= boost::coroutines::attributes());
-/// Start a new stackful coroutine that executes in the context of a strand.
+/// Start a new stackful coroutine that executes on a given executor.
/**
* This function is used to launch a new coroutine.
*
- * @param strand Identifies a strand. By starting multiple coroutines on the
- * same strand, the implementation ensures that none of those coroutines can
- * execute simultaneously.
+ * @param ex Identifies the executor that will run the coroutine. The new
+ * coroutine is implicitly given its own strand within this executor.
*
* @param function The coroutine function. The function must have the signature:
* @code void function(yield_context yield); @endcode
*
* @param attributes Boost.Coroutine attributes used to customise the coroutine.
*/
-template <typename Function>
-void spawn(boost::asio::io_service::strand strand,
+template <typename Function, typename Executor>
+void spawn(const Executor& ex,
+ BOOST_ASIO_MOVE_ARG(Function) function,
+ const boost::coroutines::attributes& attributes
+ = boost::coroutines::attributes(),
+ typename enable_if<is_executor<Executor>::value>::type* = 0);
+
+/// Start a new stackful coroutine that executes on a given strand.
+/**
+ * This function is used to launch a new coroutine.
+ *
+ * @param ex Identifies the strand that will run the coroutine.
+ *
+ * @param function The coroutine function. The function must have the signature:
+ * @code void function(yield_context yield); @endcode
+ *
+ * @param attributes Boost.Coroutine attributes used to customise the coroutine.
+ */
+template <typename Function, typename Executor>
+void spawn(const strand<Executor>& ex,
BOOST_ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes
= boost::coroutines::attributes());
-/// Start a new stackful coroutine that executes on a given io_service.
+/// Start a new stackful coroutine that executes in the context of a strand.
/**
* This function is used to launch a new coroutine.
*
- * @param io_service Identifies the io_service that will run the coroutine. The
- * new coroutine is implicitly given its own strand within this io_service.
+ * @param s Identifies a strand. By starting multiple coroutines on the same
+ * strand, the implementation ensures that none of those coroutines can execute
+ * simultaneously.
*
* @param function The coroutine function. The function must have the signature:
* @code void function(yield_context yield); @endcode
@@ -250,11 +300,32 @@ void spawn(boost::asio::io_service::strand strand,
* @param attributes Boost.Coroutine attributes used to customise the coroutine.
*/
template <typename Function>
-void spawn(boost::asio::io_service& io_service,
+void spawn(const boost::asio::io_context::strand& s,
BOOST_ASIO_MOVE_ARG(Function) function,
const boost::coroutines::attributes& attributes
= boost::coroutines::attributes());
+/// Start a new stackful coroutine that executes on a given execution context.
+/**
+ * This function is used to launch a new coroutine.
+ *
+ * @param ctx Identifies the execution context that will run the coroutine. The
+ * new coroutine is implicitly given its own strand within this execution
+ * context.
+ *
+ * @param function The coroutine function. The function must have the signature:
+ * @code void function(yield_context yield); @endcode
+ *
+ * @param attributes Boost.Coroutine attributes used to customise the coroutine.
+ */
+template <typename Function, typename ExecutionContext>
+void spawn(ExecutionContext& ctx,
+ BOOST_ASIO_MOVE_ARG(Function) function,
+ const boost::coroutines::attributes& attributes
+ = boost::coroutines::attributes(),
+ typename enable_if<is_convertible<
+ ExecutionContext&, execution_context&>::value>::type* = 0);
+
/*@}*/
} // namespace asio
diff --git a/boost/asio/ssl.hpp b/boost/asio/ssl.hpp
index f82bdc043d..6fc10a92f3 100644
--- a/boost/asio/ssl.hpp
+++ b/boost/asio/ssl.hpp
@@ -15,15 +15,12 @@
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-#include <boost/asio/ssl/basic_context.hpp>
#include <boost/asio/ssl/context.hpp>
#include <boost/asio/ssl/context_base.hpp>
-#include <boost/asio/ssl/context_service.hpp>
#include <boost/asio/ssl/error.hpp>
#include <boost/asio/ssl/rfc2818_verification.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/asio/ssl/stream_base.hpp>
-#include <boost/asio/ssl/stream_service.hpp>
#include <boost/asio/ssl/verify_context.hpp>
#include <boost/asio/ssl/verify_mode.hpp>
diff --git a/boost/asio/ssl/context.hpp b/boost/asio/ssl/context.hpp
index 8bab40ab3e..6869c0f011 100644
--- a/boost/asio/ssl/context.hpp
+++ b/boost/asio/ssl/context.hpp
@@ -17,20 +17,15 @@
#include <boost/asio/detail/config.hpp>
-#if defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/ssl/basic_context.hpp>
-# include <boost/asio/ssl/context_service.hpp>
-#else // defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <string>
-# include <boost/asio/buffer.hpp>
-# include <boost/asio/io_service.hpp>
-# include <boost/asio/ssl/context_base.hpp>
-# include <boost/asio/ssl/detail/openssl_types.hpp>
-# include <boost/asio/ssl/detail/openssl_init.hpp>
-# include <boost/asio/ssl/detail/password_callback.hpp>
-# include <boost/asio/ssl/detail/verify_callback.hpp>
-# include <boost/asio/ssl/verify_mode.hpp>
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <string>
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/ssl/context_base.hpp>
+#include <boost/asio/ssl/detail/openssl_types.hpp>
+#include <boost/asio/ssl/detail/openssl_init.hpp>
+#include <boost/asio/ssl/detail/password_callback.hpp>
+#include <boost/asio/ssl/detail/verify_callback.hpp>
+#include <boost/asio/ssl/verify_mode.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -38,13 +33,6 @@ namespace boost {
namespace asio {
namespace ssl {
-#if defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
-/// Typedef for the typical usage of context.
-typedef basic_context<context_service> context;
-
-#else // defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
class context
: public context_base,
private noncopyable
@@ -53,15 +41,9 @@ public:
/// The native handle type of the SSL context.
typedef SSL_CTX* native_handle_type;
- /// (Deprecated: Use native_handle_type.) The native type of the SSL context.
- typedef SSL_CTX* impl_type;
-
/// Constructor.
BOOST_ASIO_DECL explicit context(method m);
- /// Deprecated constructor taking a reference to an io_service object.
- BOOST_ASIO_DECL context(boost::asio::io_service&, method m);
-
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Move-construct a context from another.
/**
@@ -101,15 +83,6 @@ public:
*/
BOOST_ASIO_DECL native_handle_type native_handle();
- /// (Deprecated: Use native_handle().) Get the underlying implementation in
- /// the native type.
- /**
- * This function may be used to obtain the underlying implementation of the
- * context. This is intended to allow access to context functionality that is
- * not otherwise provided.
- */
- BOOST_ASIO_DECL impl_type impl();
-
/// Clear options on the context.
/**
* This function may be used to configure the SSL options used by the context.
@@ -136,7 +109,7 @@ public:
*
* @note Calls @c SSL_CTX_clear_options.
*/
- BOOST_ASIO_DECL boost::system::error_code clear_options(options o,
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID clear_options(options o,
boost::system::error_code& ec);
/// Set options on the context.
@@ -165,7 +138,7 @@ public:
*
* @note Calls @c SSL_CTX_set_options.
*/
- BOOST_ASIO_DECL boost::system::error_code set_options(options o,
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID set_options(options o,
boost::system::error_code& ec);
/// Set the peer verification mode.
@@ -194,7 +167,7 @@ public:
*
* @note Calls @c SSL_CTX_set_verify.
*/
- BOOST_ASIO_DECL boost::system::error_code set_verify_mode(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID set_verify_mode(
verify_mode v, boost::system::error_code& ec);
/// Set the peer verification depth.
@@ -223,7 +196,7 @@ public:
*
* @note Calls @c SSL_CTX_set_verify_depth.
*/
- BOOST_ASIO_DECL boost::system::error_code set_verify_depth(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID set_verify_depth(
int depth, boost::system::error_code& ec);
/// Set the callback used to verify peer certificates.
@@ -266,7 +239,7 @@ public:
* @note Calls @c SSL_CTX_set_verify.
*/
template <typename VerifyCallback>
- boost::system::error_code set_verify_callback(VerifyCallback callback,
+ BOOST_ASIO_SYNC_OP_VOID set_verify_callback(VerifyCallback callback,
boost::system::error_code& ec);
/// Load a certification authority file for performing verification.
@@ -295,7 +268,7 @@ public:
*
* @note Calls @c SSL_CTX_load_verify_locations.
*/
- BOOST_ASIO_DECL boost::system::error_code load_verify_file(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID load_verify_file(
const std::string& filename, boost::system::error_code& ec);
/// Add certification authority for performing verification.
@@ -324,7 +297,7 @@ public:
*
* @note Calls @c SSL_CTX_get_cert_store and @c X509_STORE_add_cert.
*/
- BOOST_ASIO_DECL boost::system::error_code add_certificate_authority(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID add_certificate_authority(
const const_buffer& ca, boost::system::error_code& ec);
/// Configures the context to use the default directories for finding
@@ -351,7 +324,7 @@ public:
*
* @note Calls @c SSL_CTX_set_default_verify_paths.
*/
- BOOST_ASIO_DECL boost::system::error_code set_default_verify_paths(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID set_default_verify_paths(
boost::system::error_code& ec);
/// Add a directory containing certificate authority files to be used for
@@ -384,7 +357,7 @@ public:
*
* @note Calls @c SSL_CTX_load_verify_locations.
*/
- BOOST_ASIO_DECL boost::system::error_code add_verify_path(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID add_verify_path(
const std::string& path, boost::system::error_code& ec);
/// Use a certificate from a memory buffer.
@@ -414,7 +387,7 @@ public:
*
* @note Calls @c SSL_CTX_use_certificate or SSL_CTX_use_certificate_ASN1.
*/
- BOOST_ASIO_DECL boost::system::error_code use_certificate(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID use_certificate(
const const_buffer& certificate, file_format format,
boost::system::error_code& ec);
@@ -445,7 +418,7 @@ public:
*
* @note Calls @c SSL_CTX_use_certificate_file.
*/
- BOOST_ASIO_DECL boost::system::error_code use_certificate_file(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID use_certificate_file(
const std::string& filename, file_format format,
boost::system::error_code& ec);
@@ -475,7 +448,7 @@ public:
*
* @note Calls @c SSL_CTX_use_certificate and SSL_CTX_add_extra_chain_cert.
*/
- BOOST_ASIO_DECL boost::system::error_code use_certificate_chain(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID use_certificate_chain(
const const_buffer& chain, boost::system::error_code& ec);
/// Use a certificate chain from a file.
@@ -504,7 +477,7 @@ public:
*
* @note Calls @c SSL_CTX_use_certificate_chain_file.
*/
- BOOST_ASIO_DECL boost::system::error_code use_certificate_chain_file(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID use_certificate_chain_file(
const std::string& filename, boost::system::error_code& ec);
/// Use a private key from a memory buffer.
@@ -534,7 +507,7 @@ public:
*
* @note Calls @c SSL_CTX_use_PrivateKey or SSL_CTX_use_PrivateKey_ASN1.
*/
- BOOST_ASIO_DECL boost::system::error_code use_private_key(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID use_private_key(
const const_buffer& private_key, file_format format,
boost::system::error_code& ec);
@@ -565,7 +538,7 @@ public:
*
* @note Calls @c SSL_CTX_use_PrivateKey_file.
*/
- BOOST_ASIO_DECL boost::system::error_code use_private_key_file(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID use_private_key_file(
const std::string& filename, file_format format,
boost::system::error_code& ec);
@@ -598,7 +571,7 @@ public:
*
* @note Calls @c SSL_CTX_use_RSAPrivateKey or SSL_CTX_use_RSAPrivateKey_ASN1.
*/
- BOOST_ASIO_DECL boost::system::error_code use_rsa_private_key(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID use_rsa_private_key(
const const_buffer& private_key, file_format format,
boost::system::error_code& ec);
@@ -631,7 +604,7 @@ public:
*
* @note Calls @c SSL_CTX_use_RSAPrivateKey_file.
*/
- BOOST_ASIO_DECL boost::system::error_code use_rsa_private_key_file(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID use_rsa_private_key_file(
const std::string& filename, file_format format,
boost::system::error_code& ec);
@@ -663,7 +636,7 @@ public:
*
* @note Calls @c SSL_CTX_set_tmp_dh.
*/
- BOOST_ASIO_DECL boost::system::error_code use_tmp_dh(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID use_tmp_dh(
const const_buffer& dh, boost::system::error_code& ec);
/// Use the specified file to obtain the temporary Diffie-Hellman parameters.
@@ -692,7 +665,7 @@ public:
*
* @note Calls @c SSL_CTX_set_tmp_dh.
*/
- BOOST_ASIO_DECL boost::system::error_code use_tmp_dh_file(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID use_tmp_dh_file(
const std::string& filename, boost::system::error_code& ec);
/// Set the password callback.
@@ -733,7 +706,7 @@ public:
* @note Calls @c SSL_CTX_set_default_passwd_cb.
*/
template <typename PasswordCallback>
- boost::system::error_code set_password_callback(PasswordCallback callback,
+ BOOST_ASIO_SYNC_OP_VOID set_password_callback(PasswordCallback callback,
boost::system::error_code& ec);
private:
@@ -744,7 +717,7 @@ private:
struct dh_cleanup;
// Helper function used to set a peer certificate verification callback.
- BOOST_ASIO_DECL boost::system::error_code do_set_verify_callback(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID do_set_verify_callback(
detail::verify_callback_base* callback, boost::system::error_code& ec);
// Callback used when the SSL implementation wants to verify a certificate.
@@ -752,7 +725,7 @@ private:
int preverified, X509_STORE_CTX* ctx);
// Helper function used to set a password callback.
- BOOST_ASIO_DECL boost::system::error_code do_set_password_callback(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID do_set_password_callback(
detail::password_callback_base* callback, boost::system::error_code& ec);
// Callback used when the SSL implementation wants a password.
@@ -760,7 +733,7 @@ private:
char* buf, int size, int purpose, void* data);
// Helper function to set the temporary Diffie-Hellman parameters from a BIO.
- BOOST_ASIO_DECL boost::system::error_code do_use_tmp_dh(
+ BOOST_ASIO_DECL BOOST_ASIO_SYNC_OP_VOID do_use_tmp_dh(
BIO* bio, boost::system::error_code& ec);
// Helper function to make a BIO from a memory buffer.
@@ -773,8 +746,6 @@ private:
boost::asio::ssl::detail::openssl_init<> init_;
};
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace ssl
} // namespace asio
} // namespace boost
diff --git a/boost/asio/ssl/detail/buffered_handshake_op.hpp b/boost/asio/ssl/detail/buffered_handshake_op.hpp
index b40fe5d69d..926e896ae9 100644
--- a/boost/asio/ssl/detail/buffered_handshake_op.hpp
+++ b/boost/asio/ssl/detail/buffered_handshake_op.hpp
@@ -17,9 +17,7 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/ssl/detail/engine.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/ssl/detail/engine.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -28,8 +26,6 @@ namespace asio {
namespace ssl {
namespace detail {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
template <typename ConstBufferSequence>
class buffered_handshake_op
{
@@ -46,8 +42,27 @@ public:
boost::system::error_code& ec,
std::size_t& bytes_transferred) const
{
- typename ConstBufferSequence::const_iterator iter = buffers_.begin();
- typename ConstBufferSequence::const_iterator end = buffers_.end();
+ return this->process(eng, ec, bytes_transferred,
+ boost::asio::buffer_sequence_begin(buffers_),
+ boost::asio::buffer_sequence_end(buffers_));
+ }
+
+ template <typename Handler>
+ void call_handler(Handler& handler,
+ const boost::system::error_code& ec,
+ const std::size_t& bytes_transferred) const
+ {
+ handler(ec, bytes_transferred);
+ }
+
+private:
+ template <typename Iterator>
+ engine::want process(engine& eng,
+ boost::system::error_code& ec,
+ std::size_t& bytes_transferred,
+ Iterator begin, Iterator end) const
+ {
+ Iterator iter = begin;
std::size_t accumulated_size = 0;
for (;;)
@@ -63,9 +78,9 @@ public:
const_buffer buffer(*iter);
// Skip over any buffers which have already been consumed by the engine.
- if (bytes_transferred >= accumulated_size + buffer_size(buffer))
+ if (bytes_transferred >= accumulated_size + buffer.size())
{
- accumulated_size += buffer_size(buffer);
+ accumulated_size += buffer.size();
++iter;
continue;
}
@@ -78,30 +93,19 @@ public:
// Pass the buffer to the engine, and update the bytes transferred to
// reflect the total number of bytes consumed so far.
- bytes_transferred += buffer_size(buffer);
+ bytes_transferred += buffer.size();
buffer = eng.put_input(buffer);
- bytes_transferred -= buffer_size(buffer);
+ bytes_transferred -= buffer.size();
break;
}
}
}
- template <typename Handler>
- void call_handler(Handler& handler,
- const boost::system::error_code& ec,
- const std::size_t& bytes_transferred) const
- {
- handler(ec, bytes_transferred);
- }
-
-private:
stream_base::handshake_type type_;
ConstBufferSequence buffers_;
std::size_t total_buffer_size_;
};
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace detail
} // namespace ssl
} // namespace asio
diff --git a/boost/asio/ssl/detail/engine.hpp b/boost/asio/ssl/detail/engine.hpp
index f31a4a7287..bcd516dc49 100644
--- a/boost/asio/ssl/detail/engine.hpp
+++ b/boost/asio/ssl/detail/engine.hpp
@@ -17,14 +17,12 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/buffer.hpp>
-# include <boost/asio/detail/static_mutex.hpp>
-# include <boost/asio/ssl/detail/openssl_types.hpp>
-# include <boost/asio/ssl/detail/verify_callback.hpp>
-# include <boost/asio/ssl/stream_base.hpp>
-# include <boost/asio/ssl/verify_mode.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/detail/static_mutex.hpp>
+#include <boost/asio/ssl/detail/openssl_types.hpp>
+#include <boost/asio/ssl/detail/verify_callback.hpp>
+#include <boost/asio/ssl/stream_base.hpp>
+#include <boost/asio/ssl/verify_mode.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -33,8 +31,6 @@ namespace asio {
namespace ssl {
namespace detail {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
class engine
{
public:
@@ -98,7 +94,7 @@ public:
boost::system::error_code& ec, std::size_t& bytes_transferred);
// Get output data to be written to the transport.
- BOOST_ASIO_DECL boost::asio::mutable_buffers_1 get_output(
+ BOOST_ASIO_DECL boost::asio::mutable_buffer get_output(
const boost::asio::mutable_buffer& data);
// Put input data that was read from the transport.
@@ -120,9 +116,11 @@ private:
BOOST_ASIO_DECL static int verify_callback_function(
int preverified, X509_STORE_CTX* ctx);
+#if (OPENSSL_VERSION_NUMBER < 0x10000000L)
// The SSL_accept function may not be thread safe. This mutex is used to
// protect all calls to the SSL_accept function.
BOOST_ASIO_DECL static boost::asio::detail::static_mutex& accept_mutex();
+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)
// Perform one operation. Returns >= 0 on success or error, want_read if the
// operation needs more input, or want_write if it needs to write some output
@@ -150,8 +148,6 @@ private:
BIO* ext_bio_;
};
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace detail
} // namespace ssl
} // namespace asio
diff --git a/boost/asio/ssl/detail/handshake_op.hpp b/boost/asio/ssl/detail/handshake_op.hpp
index dc61b702f0..de947520f3 100644
--- a/boost/asio/ssl/detail/handshake_op.hpp
+++ b/boost/asio/ssl/detail/handshake_op.hpp
@@ -17,9 +17,7 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/ssl/detail/engine.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/ssl/detail/engine.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -28,8 +26,6 @@ namespace asio {
namespace ssl {
namespace detail {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
class handshake_op
{
public:
@@ -58,8 +54,6 @@ private:
stream_base::handshake_type type_;
};
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace detail
} // namespace ssl
} // namespace asio
diff --git a/boost/asio/ssl/detail/impl/engine.ipp b/boost/asio/ssl/detail/impl/engine.ipp
index f7d869c56d..3133f91301 100644
--- a/boost/asio/ssl/detail/impl/engine.ipp
+++ b/boost/asio/ssl/detail/impl/engine.ipp
@@ -17,13 +17,11 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/detail/throw_error.hpp>
-# include <boost/asio/error.hpp>
-# include <boost/asio/ssl/detail/engine.hpp>
-# include <boost/asio/ssl/error.hpp>
-# include <boost/asio/ssl/verify_context.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/ssl/detail/engine.hpp>
+#include <boost/asio/ssl/error.hpp>
+#include <boost/asio/ssl/verify_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -32,8 +30,6 @@ namespace asio {
namespace ssl {
namespace detail {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
engine::engine(SSL_CTX* context)
: ssl_(::SSL_new(context))
{
@@ -45,7 +41,9 @@ engine::engine(SSL_CTX* context)
boost::asio::detail::throw_error(ec, "engine");
}
+#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);
@@ -146,37 +144,35 @@ engine::want engine::shutdown(boost::system::error_code& ec)
engine::want engine::write(const boost::asio::const_buffer& data,
boost::system::error_code& ec, std::size_t& bytes_transferred)
{
- if (boost::asio::buffer_size(data) == 0)
+ if (data.size() == 0)
{
ec = boost::system::error_code();
return engine::want_nothing;
}
return perform(&engine::do_write,
- const_cast<void*>(boost::asio::buffer_cast<const void*>(data)),
- boost::asio::buffer_size(data), ec, &bytes_transferred);
+ const_cast<void*>(data.data()),
+ data.size(), ec, &bytes_transferred);
}
engine::want engine::read(const boost::asio::mutable_buffer& data,
boost::system::error_code& ec, std::size_t& bytes_transferred)
{
- if (boost::asio::buffer_size(data) == 0)
+ if (data.size() == 0)
{
ec = boost::system::error_code();
return engine::want_nothing;
}
- return perform(&engine::do_read,
- boost::asio::buffer_cast<void*>(data),
- boost::asio::buffer_size(data), ec, &bytes_transferred);
+ return perform(&engine::do_read, data.data(),
+ data.size(), ec, &bytes_transferred);
}
-boost::asio::mutable_buffers_1 engine::get_output(
+boost::asio::mutable_buffer engine::get_output(
const boost::asio::mutable_buffer& data)
{
int length = ::BIO_read(ext_bio_,
- boost::asio::buffer_cast<void*>(data),
- static_cast<int>(boost::asio::buffer_size(data)));
+ data.data(), static_cast<int>(data.size()));
return boost::asio::buffer(data,
length > 0 ? static_cast<std::size_t>(length) : 0);
@@ -186,8 +182,7 @@ boost::asio::const_buffer engine::put_input(
const boost::asio::const_buffer& data)
{
int length = ::BIO_write(ext_bio_,
- boost::asio::buffer_cast<const void*>(data),
- static_cast<int>(boost::asio::buffer_size(data)));
+ data.data(), static_cast<int>(data.size()));
return boost::asio::buffer(data +
(length > 0 ? static_cast<std::size_t>(length) : 0));
@@ -210,7 +205,7 @@ const boost::system::error_code& engine::map_error_code(
// SSL v2 doesn't provide a protocol-level shutdown, so an eof on the
// underlying transport is passed through.
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
- if (ssl_->version == SSL2_VERSION)
+ if (SSL_version(ssl_) == SSL2_VERSION)
return ec;
#endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)
@@ -223,11 +218,13 @@ const boost::system::error_code& engine::map_error_code(
return ec;
}
+#if (OPENSSL_VERSION_NUMBER < 0x10000000L)
boost::asio::detail::static_mutex& engine::accept_mutex()
{
static boost::asio::detail::static_mutex mutex = BOOST_ASIO_STATIC_MUTEX_INIT;
return mutex;
}
+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)
engine::want engine::perform(int (engine::* op)(void*, std::size_t),
void* data, std::size_t length, boost::system::error_code& ec,
@@ -286,7 +283,9 @@ engine::want engine::perform(int (engine::* op)(void*, std::size_t),
int engine::do_accept(void*, std::size_t)
{
+#if (OPENSSL_VERSION_NUMBER < 0x10000000L)
boost::asio::detail::static_mutex::scoped_lock lock(accept_mutex());
+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)
return ::SSL_accept(ssl_);
}
@@ -315,8 +314,6 @@ int engine::do_write(void* data, std::size_t length)
length < INT_MAX ? static_cast<int>(length) : INT_MAX);
}
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace detail
} // namespace ssl
} // namespace asio
diff --git a/boost/asio/ssl/detail/impl/openssl_init.ipp b/boost/asio/ssl/detail/impl/openssl_init.ipp
index 725f5a75ee..dd3dd328b5 100644
--- a/boost/asio/ssl/detail/impl/openssl_init.ipp
+++ b/boost/asio/ssl/detail/impl/openssl_init.ipp
@@ -79,9 +79,8 @@ public:
#elif (OPENSSL_VERSION_NUMBER < 0x10100000L)
::ERR_remove_thread_state(NULL);
#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)
-#if !defined(SSL_OP_NO_COMPRESSION) \
- && (OPENSSL_VERSION_NUMBER >= 0x10002000L) \
- && (OPENSSL_VERSION_NUMBER < 0x10100000L)
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) \
+ && (OPENSSL_VERSION_NUMBER < 0x10100000L)
::SSL_COMP_free_compression_methods();
#endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)
// && (OPENSSL_VERSION_NUMBER < 0x10100000L)
diff --git a/boost/asio/ssl/detail/io.hpp b/boost/asio/ssl/detail/io.hpp
index 3dbe4520ef..ec1464cce8 100644
--- a/boost/asio/ssl/detail/io.hpp
+++ b/boost/asio/ssl/detail/io.hpp
@@ -17,11 +17,9 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/ssl/detail/engine.hpp>
-# include <boost/asio/ssl/detail/stream_core.hpp>
-# include <boost/asio/write.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/ssl/detail/engine.hpp>
+#include <boost/asio/ssl/detail/stream_core.hpp>
+#include <boost/asio/write.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -30,8 +28,6 @@ namespace asio {
namespace ssl {
namespace detail {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
template <typename Stream, typename Operation>
std::size_t io(Stream& next_layer, stream_core& core,
const Operation& op, boost::system::error_code& ec)
@@ -43,7 +39,7 @@ std::size_t io(Stream& next_layer, stream_core& core,
// If the input buffer is empty then we need to read some more data from
// the underlying transport.
- if (boost::asio::buffer_size(core.input_) == 0)
+ if (core.input_.size() == 0)
core.input_ = boost::asio::buffer(core.input_buffer_,
next_layer.read_some(core.input_buffer_, ec));
@@ -143,7 +139,7 @@ public:
// If the input buffer already has data in it we can pass it to the
// engine and then retry the operation immediately.
- if (boost::asio::buffer_size(core_.input_) != 0)
+ if (core_.input_.size() != 0)
{
core_.input_ = core_.engine_.put_input(core_.input_);
continue;
@@ -153,7 +149,7 @@ public:
// cannot allow more than one read operation at a time on the
// underlying transport. The pending_read_ timer's expiry is set to
// pos_infin if a read is in progress, and neg_infin otherwise.
- if (core_.pending_read_.expires_at() == core_.neg_infin())
+ if (core_.expiry(core_.pending_read_) == core_.neg_infin())
{
// Prevent other read operations from being started.
core_.pending_read_.expires_at(core_.pos_infin());
@@ -180,7 +176,7 @@ public:
// cannot allow more than one write operation at a time on the
// underlying transport. The pending_write_ timer's expiry is set to
// pos_infin if a write is in progress, and neg_infin otherwise.
- if (core_.pending_write_.expires_at() == core_.neg_infin())
+ if (core_.expiry(core_.pending_write_) == core_.neg_infin())
{
// Prevent other write operations from being started.
core_.pending_write_.expires_at(core_.pos_infin());
@@ -206,7 +202,7 @@ public:
// have to keep in mind that this function might be being called from
// the async operation's initiating function. In this case we're not
// allowed to call the handler directly. Instead, issue a zero-sized
- // read so the handler runs "as-if" posted using io_service::post().
+ // read so the handler runs "as-if" posted using io_context::post().
if (start)
{
next_layer_.async_read_some(
@@ -288,7 +284,7 @@ public:
Handler handler_;
};
-template <typename Stream, typename Operation, typename Handler>
+template <typename Stream, typename Operation, typename Handler>
inline void* asio_handler_allocate(std::size_t size,
io_op<Stream, Operation, Handler>* this_handler)
{
@@ -339,10 +335,37 @@ inline void async_io(Stream& next_layer, stream_core& core,
boost::system::error_code(), 0, 1);
}
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace detail
} // namespace ssl
+
+template <typename Stream, typename Operation,
+ typename Handler, typename Allocator>
+struct associated_allocator<
+ ssl::detail::io_op<Stream, Operation, Handler>, Allocator>
+{
+ typedef typename associated_allocator<Handler, Allocator>::type type;
+
+ static type get(const ssl::detail::io_op<Stream, Operation, Handler>& h,
+ const Allocator& a = Allocator()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_allocator<Handler, Allocator>::get(h.handler_, a);
+ }
+};
+
+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()) BOOST_ASIO_NOEXCEPT
+ {
+ return associated_executor<Handler, Executor>::get(h.handler_, ex);
+ }
+};
+
} // namespace asio
} // namespace boost
diff --git a/boost/asio/ssl/detail/openssl_init.hpp b/boost/asio/ssl/detail/openssl_init.hpp
index fd0432e589..d23febd4a6 100644
--- a/boost/asio/ssl/detail/openssl_init.hpp
+++ b/boost/asio/ssl/detail/openssl_init.hpp
@@ -17,8 +17,8 @@
#include <boost/asio/detail/config.hpp>
#include <cstring>
+#include <boost/asio/detail/memory.hpp>
#include <boost/asio/detail/noncopyable.hpp>
-#include <boost/asio/detail/shared_ptr.hpp>
#include <boost/asio/ssl/detail/openssl_types.hpp>
#include <boost/asio/detail/push_options.hpp>
diff --git a/boost/asio/ssl/detail/password_callback.hpp b/boost/asio/ssl/detail/password_callback.hpp
index 5df01946ba..707670c8d4 100644
--- a/boost/asio/ssl/detail/password_callback.hpp
+++ b/boost/asio/ssl/detail/password_callback.hpp
@@ -17,11 +17,9 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <cstddef>
-# include <string>
-# include <boost/asio/ssl/context_base.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <cstddef>
+#include <string>
+#include <boost/asio/ssl/context_base.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -30,8 +28,6 @@ namespace asio {
namespace ssl {
namespace detail {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
class password_callback_base
{
public:
@@ -62,8 +58,6 @@ private:
PasswordCallback callback_;
};
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace detail
} // namespace ssl
} // namespace asio
diff --git a/boost/asio/ssl/detail/read_op.hpp b/boost/asio/ssl/detail/read_op.hpp
index f0b5d6ddf9..d465f0ce15 100644
--- a/boost/asio/ssl/detail/read_op.hpp
+++ b/boost/asio/ssl/detail/read_op.hpp
@@ -17,10 +17,8 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/detail/buffer_sequence_adapter.hpp>
-# include <boost/asio/ssl/detail/engine.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/ssl/detail/engine.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -29,8 +27,6 @@ namespace asio {
namespace ssl {
namespace detail {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
template <typename MutableBufferSequence>
class read_op
{
@@ -63,8 +59,6 @@ private:
MutableBufferSequence buffers_;
};
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace detail
} // namespace ssl
} // namespace asio
diff --git a/boost/asio/ssl/detail/shutdown_op.hpp b/boost/asio/ssl/detail/shutdown_op.hpp
index 3a3f761c08..91acc9fb2a 100644
--- a/boost/asio/ssl/detail/shutdown_op.hpp
+++ b/boost/asio/ssl/detail/shutdown_op.hpp
@@ -17,9 +17,7 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/ssl/detail/engine.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/ssl/detail/engine.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -28,8 +26,6 @@ namespace asio {
namespace ssl {
namespace detail {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
class shutdown_op
{
public:
@@ -50,8 +46,6 @@ public:
}
};
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace detail
} // namespace ssl
} // namespace asio
diff --git a/boost/asio/ssl/detail/stream_core.hpp b/boost/asio/ssl/detail/stream_core.hpp
index 70d1feddbb..95993e5f4e 100644
--- a/boost/asio/ssl/detail/stream_core.hpp
+++ b/boost/asio/ssl/detail/stream_core.hpp
@@ -17,15 +17,13 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
-# include <boost/asio/deadline_timer.hpp>
-# else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
-# include <boost/asio/steady_timer.hpp>
-# endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
-# include <boost/asio/ssl/detail/engine.hpp>
-# include <boost/asio/buffer.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+# include <boost/asio/deadline_timer.hpp>
+#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+# include <boost/asio/steady_timer.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+#include <boost/asio/ssl/detail/engine.hpp>
+#include <boost/asio/buffer.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -34,18 +32,16 @@ namespace asio {
namespace ssl {
namespace detail {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
struct stream_core
{
// According to the OpenSSL documentation, this is the buffer size that is
// sufficient to hold the largest possible TLS record.
enum { max_tls_record_size = 17 * 1024 };
- stream_core(SSL_CTX* context, boost::asio::io_service& io_service)
+ stream_core(SSL_CTX* context, boost::asio::io_context& io_context)
: engine_(context),
- pending_read_(io_service),
- pending_write_(io_service),
+ pending_read_(io_context),
+ pending_write_(io_context),
output_buffer_space_(max_tls_record_size),
output_buffer_(boost::asio::buffer(output_buffer_space_)),
input_buffer_space_(max_tls_record_size),
@@ -80,6 +76,13 @@ struct stream_core
{
return boost::posix_time::pos_infin;
}
+
+ // Helper function to get a timer's expiry time.
+ static boost::asio::deadline_timer::time_type expiry(
+ const boost::asio::deadline_timer& timer)
+ {
+ return timer.expires_at();
+ }
#else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
// Timer used for storing queued read operations.
boost::asio::steady_timer pending_read_;
@@ -98,26 +101,31 @@ struct stream_core
{
return (boost::asio::steady_timer::time_point::max)();
}
+
+ // Helper function to get a timer's expiry time.
+ static boost::asio::steady_timer::time_point expiry(
+ const boost::asio::steady_timer& timer)
+ {
+ return timer.expiry();
+ }
#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
// Buffer space used to prepare output intended for the transport.
std::vector<unsigned char> output_buffer_space_;
// A buffer that may be used to prepare output intended for the transport.
- const boost::asio::mutable_buffers_1 output_buffer_;
+ const boost::asio::mutable_buffer output_buffer_;
// Buffer space used to read input intended for the engine.
std::vector<unsigned char> input_buffer_space_;
// A buffer that may be used to read input intended for the engine.
- const boost::asio::mutable_buffers_1 input_buffer_;
+ const boost::asio::mutable_buffer input_buffer_;
// The buffer pointing to the engine's unconsumed input.
boost::asio::const_buffer input_;
};
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace detail
} // namespace ssl
} // namespace asio
diff --git a/boost/asio/ssl/detail/verify_callback.hpp b/boost/asio/ssl/detail/verify_callback.hpp
index c4bea7c215..ea1a436b22 100644
--- a/boost/asio/ssl/detail/verify_callback.hpp
+++ b/boost/asio/ssl/detail/verify_callback.hpp
@@ -17,9 +17,7 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/ssl/verify_context.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/ssl/verify_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -28,8 +26,6 @@ namespace asio {
namespace ssl {
namespace detail {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
class verify_callback_base
{
public:
@@ -58,8 +54,6 @@ private:
VerifyCallback callback_;
};
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace detail
} // namespace ssl
} // namespace asio
diff --git a/boost/asio/ssl/detail/write_op.hpp b/boost/asio/ssl/detail/write_op.hpp
index c04eda86d2..b30f0c3787 100644
--- a/boost/asio/ssl/detail/write_op.hpp
+++ b/boost/asio/ssl/detail/write_op.hpp
@@ -17,10 +17,8 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/detail/buffer_sequence_adapter.hpp>
-# include <boost/asio/ssl/detail/engine.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/ssl/detail/engine.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -29,8 +27,6 @@ namespace asio {
namespace ssl {
namespace detail {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
template <typename ConstBufferSequence>
class write_op
{
@@ -63,8 +59,6 @@ private:
ConstBufferSequence buffers_;
};
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace detail
} // namespace ssl
} // namespace asio
diff --git a/boost/asio/ssl/impl/context.hpp b/boost/asio/ssl/impl/context.hpp
index 52547d0437..a207a73fa7 100644
--- a/boost/asio/ssl/impl/context.hpp
+++ b/boost/asio/ssl/impl/context.hpp
@@ -18,9 +18,7 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/detail/throw_error.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/detail/throw_error.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -28,8 +26,6 @@ namespace boost {
namespace asio {
namespace ssl {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
template <typename VerifyCallback>
void context::set_verify_callback(VerifyCallback callback)
{
@@ -39,11 +35,12 @@ void context::set_verify_callback(VerifyCallback callback)
}
template <typename VerifyCallback>
-boost::system::error_code context::set_verify_callback(
+BOOST_ASIO_SYNC_OP_VOID context::set_verify_callback(
VerifyCallback callback, boost::system::error_code& ec)
{
- return do_set_verify_callback(
+ do_set_verify_callback(
new detail::verify_callback<VerifyCallback>(callback), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
template <typename PasswordCallback>
@@ -55,15 +52,14 @@ void context::set_password_callback(PasswordCallback callback)
}
template <typename PasswordCallback>
-boost::system::error_code context::set_password_callback(
+BOOST_ASIO_SYNC_OP_VOID context::set_password_callback(
PasswordCallback callback, boost::system::error_code& ec)
{
- return do_set_password_callback(
+ do_set_password_callback(
new detail::password_callback<PasswordCallback>(callback), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace ssl
} // namespace asio
} // namespace boost
diff --git a/boost/asio/ssl/impl/context.ipp b/boost/asio/ssl/impl/context.ipp
index a1fb9a578b..f50ce454ea 100644
--- a/boost/asio/ssl/impl/context.ipp
+++ b/boost/asio/ssl/impl/context.ipp
@@ -18,13 +18,11 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <cstring>
-# include <boost/asio/detail/throw_error.hpp>
-# include <boost/asio/error.hpp>
-# include <boost/asio/ssl/context.hpp>
-# include <boost/asio/ssl/error.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <cstring>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/ssl/context.hpp>
+#include <boost/asio/ssl/error.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -32,8 +30,6 @@ namespace boost {
namespace asio {
namespace ssl {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
struct context::bio_cleanup
{
BIO* p;
@@ -326,14 +322,6 @@ context::context(context::method m)
set_options(no_compression);
}
-context::context(boost::asio::io_service&, context::method m)
- : handle_(0)
-{
- context tmp(m);
- handle_ = tmp.handle_;
- tmp.handle_ = 0;
-}
-
#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
context::context(context&& other)
{
@@ -390,11 +378,6 @@ context::native_handle_type context::native_handle()
return handle_;
}
-context::impl_type context::impl()
-{
- return handle_;
-}
-
void context::clear_options(context::options o)
{
boost::system::error_code ec;
@@ -402,7 +385,7 @@ void context::clear_options(context::options o)
boost::asio::detail::throw_error(ec, "clear_options");
}
-boost::system::error_code context::clear_options(
+BOOST_ASIO_SYNC_OP_VOID context::clear_options(
context::options o, boost::system::error_code& ec)
{
#if (OPENSSL_VERSION_NUMBER >= 0x009080DFL) \
@@ -426,7 +409,7 @@ boost::system::error_code context::clear_options(
ec = boost::asio::error::operation_not_supported;
#endif // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)
// && (OPENSSL_VERSION_NUMBER != 0x00909000L)
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::set_options(context::options o)
@@ -436,7 +419,7 @@ void context::set_options(context::options o)
boost::asio::detail::throw_error(ec, "set_options");
}
-boost::system::error_code context::set_options(
+BOOST_ASIO_SYNC_OP_VOID context::set_options(
context::options o, boost::system::error_code& ec)
{
#if !defined(SSL_OP_NO_COMPRESSION)
@@ -453,7 +436,7 @@ boost::system::error_code context::set_options(
::SSL_CTX_set_options(handle_, o);
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::set_verify_mode(verify_mode v)
@@ -463,13 +446,13 @@ void context::set_verify_mode(verify_mode v)
boost::asio::detail::throw_error(ec, "set_verify_mode");
}
-boost::system::error_code context::set_verify_mode(
+BOOST_ASIO_SYNC_OP_VOID context::set_verify_mode(
verify_mode v, boost::system::error_code& ec)
{
::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_));
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::set_verify_depth(int depth)
@@ -479,13 +462,13 @@ void context::set_verify_depth(int depth)
boost::asio::detail::throw_error(ec, "set_verify_depth");
}
-boost::system::error_code context::set_verify_depth(
+BOOST_ASIO_SYNC_OP_VOID context::set_verify_depth(
int depth, boost::system::error_code& ec)
{
::SSL_CTX_set_verify_depth(handle_, depth);
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::load_verify_file(const std::string& filename)
@@ -495,7 +478,7 @@ void context::load_verify_file(const std::string& filename)
boost::asio::detail::throw_error(ec, "load_verify_file");
}
-boost::system::error_code context::load_verify_file(
+BOOST_ASIO_SYNC_OP_VOID context::load_verify_file(
const std::string& filename, boost::system::error_code& ec)
{
::ERR_clear_error();
@@ -505,11 +488,11 @@ boost::system::error_code context::load_verify_file(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::add_certificate_authority(const const_buffer& ca)
@@ -519,7 +502,7 @@ void context::add_certificate_authority(const const_buffer& ca)
boost::asio::detail::throw_error(ec, "add_certificate_authority");
}
-boost::system::error_code context::add_certificate_authority(
+BOOST_ASIO_SYNC_OP_VOID context::add_certificate_authority(
const const_buffer& ca, boost::system::error_code& ec)
{
::ERR_clear_error();
@@ -535,7 +518,7 @@ boost::system::error_code context::add_certificate_authority(
if (::X509_STORE_add_cert(store, cert.p) == 1)
{
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
}
@@ -544,7 +527,7 @@ boost::system::error_code context::add_certificate_authority(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::set_default_verify_paths()
@@ -554,7 +537,7 @@ void context::set_default_verify_paths()
boost::asio::detail::throw_error(ec, "set_default_verify_paths");
}
-boost::system::error_code context::set_default_verify_paths(
+BOOST_ASIO_SYNC_OP_VOID context::set_default_verify_paths(
boost::system::error_code& ec)
{
::ERR_clear_error();
@@ -564,11 +547,11 @@ boost::system::error_code context::set_default_verify_paths(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::add_verify_path(const std::string& path)
@@ -578,7 +561,7 @@ void context::add_verify_path(const std::string& path)
boost::asio::detail::throw_error(ec, "add_verify_path");
}
-boost::system::error_code context::add_verify_path(
+BOOST_ASIO_SYNC_OP_VOID context::add_verify_path(
const std::string& path, boost::system::error_code& ec)
{
::ERR_clear_error();
@@ -588,11 +571,11 @@ boost::system::error_code context::add_verify_path(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::use_certificate(
@@ -603,7 +586,7 @@ void context::use_certificate(
boost::asio::detail::throw_error(ec, "use_certificate");
}
-boost::system::error_code context::use_certificate(
+BOOST_ASIO_SYNC_OP_VOID context::use_certificate(
const const_buffer& certificate, file_format format,
boost::system::error_code& ec)
{
@@ -612,11 +595,11 @@ boost::system::error_code context::use_certificate(
if (format == context_base::asn1)
{
if (::SSL_CTX_use_certificate_ASN1(handle_,
- static_cast<int>(buffer_size(certificate)),
- buffer_cast<const unsigned char*>(certificate)) == 1)
+ static_cast<int>(certificate.size()),
+ static_cast<const unsigned char*>(certificate.data())) == 1)
{
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
else if (format == context_base::pem)
@@ -630,7 +613,7 @@ boost::system::error_code context::use_certificate(
if (::SSL_CTX_use_certificate(handle_, cert.p) == 1)
{
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
}
@@ -638,13 +621,13 @@ boost::system::error_code context::use_certificate(
else
{
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::use_certificate_file(
@@ -655,7 +638,7 @@ void context::use_certificate_file(
boost::asio::detail::throw_error(ec, "use_certificate_file");
}
-boost::system::error_code context::use_certificate_file(
+BOOST_ASIO_SYNC_OP_VOID context::use_certificate_file(
const std::string& filename, file_format format,
boost::system::error_code& ec)
{
@@ -671,7 +654,7 @@ boost::system::error_code context::use_certificate_file(
default:
{
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
@@ -682,11 +665,11 @@ boost::system::error_code context::use_certificate_file(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::use_certificate_chain(const const_buffer& chain)
@@ -696,7 +679,7 @@ void context::use_certificate_chain(const const_buffer& chain)
boost::asio::detail::throw_error(ec, "use_certificate_chain");
}
-boost::system::error_code context::use_certificate_chain(
+BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain(
const const_buffer& chain, boost::system::error_code& ec)
{
::ERR_clear_error();
@@ -719,7 +702,7 @@ boost::system::error_code context::use_certificate_chain(
{
ec = boost::system::error_code(ERR_R_PEM_LIB,
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
int result = ::SSL_CTX_use_certificate(handle_, cert.p);
@@ -728,7 +711,7 @@ boost::system::error_code context::use_certificate_chain(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) && !defined(LIBRESSL_VERSION_NUMBER)
@@ -750,7 +733,7 @@ boost::system::error_code context::use_certificate_chain(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
@@ -760,14 +743,14 @@ boost::system::error_code context::use_certificate_chain(
{
::ERR_clear_error();
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::use_certificate_chain_file(const std::string& filename)
@@ -777,7 +760,7 @@ void context::use_certificate_chain_file(const std::string& filename)
boost::asio::detail::throw_error(ec, "use_certificate_chain_file");
}
-boost::system::error_code context::use_certificate_chain_file(
+BOOST_ASIO_SYNC_OP_VOID context::use_certificate_chain_file(
const std::string& filename, boost::system::error_code& ec)
{
::ERR_clear_error();
@@ -787,11 +770,11 @@ boost::system::error_code context::use_certificate_chain_file(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::use_private_key(
@@ -802,7 +785,7 @@ void context::use_private_key(
boost::asio::detail::throw_error(ec, "use_private_key");
}
-boost::system::error_code context::use_private_key(
+BOOST_ASIO_SYNC_OP_VOID context::use_private_key(
const const_buffer& private_key, context::file_format format,
boost::system::error_code& ec)
{
@@ -833,7 +816,7 @@ boost::system::error_code context::use_private_key(
default:
{
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
@@ -842,7 +825,7 @@ boost::system::error_code context::use_private_key(
if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)
{
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
}
@@ -850,7 +833,7 @@ boost::system::error_code context::use_private_key(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::use_private_key_file(
@@ -869,7 +852,7 @@ void context::use_rsa_private_key(
boost::asio::detail::throw_error(ec, "use_rsa_private_key");
}
-boost::system::error_code context::use_rsa_private_key(
+BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key(
const const_buffer& private_key, context::file_format format,
boost::system::error_code& ec)
{
@@ -900,7 +883,7 @@ boost::system::error_code context::use_rsa_private_key(
default:
{
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
@@ -909,7 +892,7 @@ boost::system::error_code context::use_rsa_private_key(
if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1)
{
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
}
@@ -917,10 +900,10 @@ boost::system::error_code context::use_rsa_private_key(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
-boost::system::error_code context::use_private_key_file(
+BOOST_ASIO_SYNC_OP_VOID context::use_private_key_file(
const std::string& filename, context::file_format format,
boost::system::error_code& ec)
{
@@ -936,7 +919,7 @@ boost::system::error_code context::use_private_key_file(
default:
{
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
@@ -947,11 +930,11 @@ boost::system::error_code context::use_private_key_file(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::use_rsa_private_key_file(
@@ -962,7 +945,7 @@ void context::use_rsa_private_key_file(
boost::asio::detail::throw_error(ec, "use_rsa_private_key_file");
}
-boost::system::error_code context::use_rsa_private_key_file(
+BOOST_ASIO_SYNC_OP_VOID context::use_rsa_private_key_file(
const std::string& filename, context::file_format format,
boost::system::error_code& ec)
{
@@ -978,7 +961,7 @@ boost::system::error_code context::use_rsa_private_key_file(
default:
{
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
@@ -990,11 +973,11 @@ boost::system::error_code context::use_rsa_private_key_file(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::use_tmp_dh(const const_buffer& dh)
@@ -1004,7 +987,7 @@ void context::use_tmp_dh(const const_buffer& dh)
boost::asio::detail::throw_error(ec, "use_tmp_dh");
}
-boost::system::error_code context::use_tmp_dh(
+BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh(
const const_buffer& dh, boost::system::error_code& ec)
{
::ERR_clear_error();
@@ -1018,7 +1001,7 @@ boost::system::error_code context::use_tmp_dh(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
void context::use_tmp_dh_file(const std::string& filename)
@@ -1028,7 +1011,7 @@ void context::use_tmp_dh_file(const std::string& filename)
boost::asio::detail::throw_error(ec, "use_tmp_dh_file");
}
-boost::system::error_code context::use_tmp_dh_file(
+BOOST_ASIO_SYNC_OP_VOID context::use_tmp_dh_file(
const std::string& filename, boost::system::error_code& ec)
{
::ERR_clear_error();
@@ -1042,10 +1025,10 @@ boost::system::error_code context::use_tmp_dh_file(
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
-boost::system::error_code context::do_use_tmp_dh(
+BOOST_ASIO_SYNC_OP_VOID context::do_use_tmp_dh(
BIO* bio, boost::system::error_code& ec)
{
::ERR_clear_error();
@@ -1056,17 +1039,17 @@ boost::system::error_code context::do_use_tmp_dh(
if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1)
{
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
}
ec = boost::system::error_code(
static_cast<int>(::ERR_get_error()),
boost::asio::error::get_ssl_category());
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
-boost::system::error_code context::do_set_verify_callback(
+BOOST_ASIO_SYNC_OP_VOID context::do_set_verify_callback(
detail::verify_callback_base* callback, boost::system::error_code& ec)
{
if (SSL_CTX_get_app_data(handle_))
@@ -1082,7 +1065,7 @@ boost::system::error_code context::do_set_verify_callback(
&context::verify_callback_function);
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
@@ -1111,7 +1094,7 @@ int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)
return 0;
}
-boost::system::error_code context::do_set_password_callback(
+BOOST_ASIO_SYNC_OP_VOID context::do_set_password_callback(
detail::password_callback_base* callback, boost::system::error_code& ec)
{
#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)
@@ -1129,7 +1112,7 @@ boost::system::error_code context::do_set_password_callback(
SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);
ec = boost::system::error_code();
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
int context::password_callback_function(
@@ -1162,12 +1145,10 @@ int context::password_callback_function(
BIO* context::make_buffer_bio(const const_buffer& b)
{
return ::BIO_new_mem_buf(
- const_cast<void*>(buffer_cast<const void*>(b)),
- static_cast<int>(buffer_size(b)));
+ const_cast<void*>(b.data()),
+ static_cast<int>(b.size()));
}
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace ssl
} // namespace asio
} // namespace boost
diff --git a/boost/asio/ssl/impl/rfc2818_verification.ipp b/boost/asio/ssl/impl/rfc2818_verification.ipp
index 7f22806735..d759ce567c 100644
--- a/boost/asio/ssl/impl/rfc2818_verification.ipp
+++ b/boost/asio/ssl/impl/rfc2818_verification.ipp
@@ -17,13 +17,11 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <cctype>
-# include <cstring>
-# include <boost/asio/ip/address.hpp>
-# include <boost/asio/ssl/rfc2818_verification.hpp>
-# include <boost/asio/ssl/detail/openssl_types.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <cctype>
+#include <cstring>
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/ssl/rfc2818_verification.hpp>
+#include <boost/asio/ssl/detail/openssl_types.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -31,8 +29,6 @@ namespace boost {
namespace asio {
namespace ssl {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
bool rfc2818_verification::operator()(
bool preverified, verify_context& ctx) const
{
@@ -50,7 +46,7 @@ bool rfc2818_verification::operator()(
// Try converting the host name to an address. If it is an address then we
// need to look for an IP address in the certificate rather than a host name.
boost::system::error_code ec;
- ip::address address = ip::address::from_string(host_, ec);
+ ip::address address = ip::make_address(host_, ec);
bool is_address = !ec;
X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
@@ -157,8 +153,6 @@ bool rfc2818_verification::match_pattern(const char* pattern,
return p == p_end && !*h;
}
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace ssl
} // namespace asio
} // namespace boost
diff --git a/boost/asio/ssl/old/basic_context.hpp b/boost/asio/ssl/old/basic_context.hpp
deleted file mode 100644
index d8703b21ae..0000000000
--- a/boost/asio/ssl/old/basic_context.hpp
+++ /dev/null
@@ -1,436 +0,0 @@
-//
-// ssl/old/basic_context.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_SSL_OLD_BASIC_CONTEXT_HPP
-#define BOOST_ASIO_SSL_OLD_BASIC_CONTEXT_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <string>
-#include <boost/noncopyable.hpp>
-#include <boost/asio/detail/throw_error.hpp>
-#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/ssl/context_base.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace ssl {
-namespace old {
-
-/// SSL context.
-template <typename Service>
-class basic_context
- : public context_base,
- private boost::noncopyable
-{
-public:
- /// The type of the service that will be used to provide context operations.
- typedef Service service_type;
-
- /// The native implementation type of the SSL context.
- typedef typename service_type::impl_type impl_type;
-
- /// Constructor.
- basic_context(boost::asio::io_service& io_service, method m)
- : service_(boost::asio::use_service<Service>(io_service)),
- impl_(service_.null())
- {
- service_.create(impl_, m);
- }
-
- /// Destructor.
- ~basic_context()
- {
- service_.destroy(impl_);
- }
-
- /// Get the underlying implementation in the native type.
- /**
- * This function may be used to obtain the underlying implementation of the
- * context. This is intended to allow access to context functionality that is
- * not otherwise provided.
- */
- impl_type impl()
- {
- return impl_;
- }
-
- /// Set options on the context.
- /**
- * This function may be used to configure the SSL options used by the context.
- *
- * @param o A bitmask of options. The available option values are defined in
- * the context_base class. The options are bitwise-ored with any existing
- * value for the options.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- void set_options(options o)
- {
- boost::system::error_code ec;
- service_.set_options(impl_, o, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Set options on the context.
- /**
- * This function may be used to configure the SSL options used by the context.
- *
- * @param o A bitmask of options. The available option values are defined in
- * the context_base class. The options are bitwise-ored with any existing
- * value for the options.
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- boost::system::error_code set_options(options o,
- boost::system::error_code& ec)
- {
- return service_.set_options(impl_, o, ec);
- }
-
- /// Set the peer verification mode.
- /**
- * This function may be used to configure the peer verification mode used by
- * the context.
- *
- * @param v A bitmask of peer verification modes. The available verify_mode
- * values are defined in the context_base class.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- void set_verify_mode(verify_mode v)
- {
- boost::system::error_code ec;
- service_.set_verify_mode(impl_, v, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Set the peer verification mode.
- /**
- * This function may be used to configure the peer verification mode used by
- * the context.
- *
- * @param v A bitmask of peer verification modes. The available verify_mode
- * values are defined in the context_base class.
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- boost::system::error_code set_verify_mode(verify_mode v,
- boost::system::error_code& ec)
- {
- return service_.set_verify_mode(impl_, v, ec);
- }
-
- /// Load a certification authority file for performing verification.
- /**
- * This function is used to load one or more trusted certification authorities
- * from a file.
- *
- * @param filename The name of a file containing certification authority
- * certificates in PEM format.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- void load_verify_file(const std::string& filename)
- {
- boost::system::error_code ec;
- service_.load_verify_file(impl_, filename, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Load a certification authority file for performing verification.
- /**
- * This function is used to load the certificates for one or more trusted
- * certification authorities from a file.
- *
- * @param filename The name of a file containing certification authority
- * certificates in PEM format.
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- boost::system::error_code load_verify_file(const std::string& filename,
- boost::system::error_code& ec)
- {
- return service_.load_verify_file(impl_, filename, ec);
- }
-
- /// Add a directory containing certificate authority files to be used for
- /// performing verification.
- /**
- * This function is used to specify the name of a directory containing
- * certification authority certificates. Each file in the directory must
- * contain a single certificate. The files must be named using the subject
- * name's hash and an extension of ".0".
- *
- * @param path The name of a directory containing the certificates.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- void add_verify_path(const std::string& path)
- {
- boost::system::error_code ec;
- service_.add_verify_path(impl_, path, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Add a directory containing certificate authority files to be used for
- /// performing verification.
- /**
- * This function is used to specify the name of a directory containing
- * certification authority certificates. Each file in the directory must
- * contain a single certificate. The files must be named using the subject
- * name's hash and an extension of ".0".
- *
- * @param path The name of a directory containing the certificates.
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- boost::system::error_code add_verify_path(const std::string& path,
- boost::system::error_code& ec)
- {
- return service_.add_verify_path(impl_, path, ec);
- }
-
- /// Use a certificate from a file.
- /**
- * This function is used to load a certificate into the context from a file.
- *
- * @param filename The name of the file containing the certificate.
- *
- * @param format The file format (ASN.1 or PEM).
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- void use_certificate_file(const std::string& filename, file_format format)
- {
- boost::system::error_code ec;
- service_.use_certificate_file(impl_, filename, format, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Use a certificate from a file.
- /**
- * This function is used to load a certificate into the context from a file.
- *
- * @param filename The name of the file containing the certificate.
- *
- * @param format The file format (ASN.1 or PEM).
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- boost::system::error_code use_certificate_file(const std::string& filename,
- file_format format, boost::system::error_code& ec)
- {
- return service_.use_certificate_file(impl_, filename, format, ec);
- }
-
- /// Use a certificate chain from a file.
- /**
- * This function is used to load a certificate chain into the context from a
- * file.
- *
- * @param filename The name of the file containing the certificate. The file
- * must use the PEM format.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- void use_certificate_chain_file(const std::string& filename)
- {
- boost::system::error_code ec;
- service_.use_certificate_chain_file(impl_, filename, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Use a certificate chain from a file.
- /**
- * This function is used to load a certificate chain into the context from a
- * file.
- *
- * @param filename The name of the file containing the certificate. The file
- * must use the PEM format.
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- boost::system::error_code use_certificate_chain_file(
- const std::string& filename, boost::system::error_code& ec)
- {
- return service_.use_certificate_chain_file(impl_, filename, ec);
- }
-
- /// Use a private key from a file.
- /**
- * This function is used to load a private key into the context from a file.
- *
- * @param filename The name of the file containing the private key.
- *
- * @param format The file format (ASN.1 or PEM).
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- void use_private_key_file(const std::string& filename, file_format format)
- {
- boost::system::error_code ec;
- service_.use_private_key_file(impl_, filename, format, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Use a private key from a file.
- /**
- * This function is used to load a private key into the context from a file.
- *
- * @param filename The name of the file containing the private key.
- *
- * @param format The file format (ASN.1 or PEM).
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- boost::system::error_code use_private_key_file(const std::string& filename,
- file_format format, boost::system::error_code& ec)
- {
- return service_.use_private_key_file(impl_, filename, format, ec);
- }
-
- /// Use an RSA private key from a file.
- /**
- * This function is used to load an RSA private key into the context from a
- * file.
- *
- * @param filename The name of the file containing the RSA private key.
- *
- * @param format The file format (ASN.1 or PEM).
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- void use_rsa_private_key_file(const std::string& filename, file_format format)
- {
- boost::system::error_code ec;
- service_.use_rsa_private_key_file(impl_, filename, format, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Use an RSA private key from a file.
- /**
- * This function is used to load an RSA private key into the context from a
- * file.
- *
- * @param filename The name of the file containing the RSA private key.
- *
- * @param format The file format (ASN.1 or PEM).
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- boost::system::error_code use_rsa_private_key_file(
- const std::string& filename, file_format format,
- boost::system::error_code& ec)
- {
- return service_.use_rsa_private_key_file(impl_, filename, format, ec);
- }
-
- /// Use the specified file to obtain the temporary Diffie-Hellman parameters.
- /**
- * This function is used to load Diffie-Hellman parameters into the context
- * from a file.
- *
- * @param filename The name of the file containing the Diffie-Hellman
- * parameters. The file must use the PEM format.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- void use_tmp_dh_file(const std::string& filename)
- {
- boost::system::error_code ec;
- service_.use_tmp_dh_file(impl_, filename, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Use the specified file to obtain the temporary Diffie-Hellman parameters.
- /**
- * This function is used to load Diffie-Hellman parameters into the context
- * from a file.
- *
- * @param filename The name of the file containing the Diffie-Hellman
- * parameters. The file must use the PEM format.
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- boost::system::error_code use_tmp_dh_file(const std::string& filename,
- boost::system::error_code& ec)
- {
- return service_.use_tmp_dh_file(impl_, filename, ec);
- }
-
- /// Set the password callback.
- /**
- * This function is used to specify a callback function to obtain password
- * information about an encrypted key in PEM format.
- *
- * @param callback The function object to be used for obtaining the password.
- * The function signature of the handler must be:
- * @code std::string password_callback(
- * std::size_t max_length, // The maximum size for a password.
- * password_purpose purpose // Whether password is for reading or writing.
- * ); @endcode
- * The return value of the callback is a string containing the password.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- template <typename PasswordCallback>
- void set_password_callback(PasswordCallback callback)
- {
- boost::system::error_code ec;
- service_.set_password_callback(impl_, callback, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Set the password callback.
- /**
- * This function is used to specify a callback function to obtain password
- * information about an encrypted key in PEM format.
- *
- * @param callback The function object to be used for obtaining the password.
- * The function signature of the handler must be:
- * @code std::string password_callback(
- * std::size_t max_length, // The maximum size for a password.
- * password_purpose purpose // Whether password is for reading or writing.
- * ); @endcode
- * The return value of the callback is a string containing the password.
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- template <typename PasswordCallback>
- boost::system::error_code set_password_callback(PasswordCallback callback,
- boost::system::error_code& ec)
- {
- return service_.set_password_callback(impl_, callback, ec);
- }
-
-private:
- /// The backend service implementation.
- service_type& service_;
-
- /// The underlying native implementation.
- impl_type impl_;
-};
-
-} // namespace old
-} // namespace ssl
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_SSL_OLD_BASIC_CONTEXT_HPP
diff --git a/boost/asio/ssl/old/context_service.hpp b/boost/asio/ssl/old/context_service.hpp
deleted file mode 100644
index 1d9fbc0751..0000000000
--- a/boost/asio/ssl/old/context_service.hpp
+++ /dev/null
@@ -1,176 +0,0 @@
-//
-// ssl/old/context_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_SSL_OLD_CONTEXT_SERVICE_HPP
-#define BOOST_ASIO_SSL_OLD_CONTEXT_SERVICE_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <string>
-#include <boost/noncopyable.hpp>
-#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/ssl/context_base.hpp>
-#include <boost/asio/ssl/old/detail/openssl_context_service.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace ssl {
-namespace old {
-
-/// Default service implementation for a context.
-class context_service
-#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
-#else
- : public boost::asio::detail::service_base<context_service>
-#endif
-{
-private:
- // The type of the platform-specific implementation.
- typedef old::detail::openssl_context_service service_impl_type;
-
-public:
-#if defined(GENERATING_DOCUMENTATION)
- /// The unique service identifier.
- static boost::asio::io_service::id id;
-#endif
-
- /// The type of the context.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined impl_type;
-#else
- typedef service_impl_type::impl_type impl_type;
-#endif
-
- /// Constructor.
- explicit context_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<context_service>(io_service),
- service_impl_(boost::asio::use_service<service_impl_type>(io_service))
- {
- }
-
- /// Return a null context implementation.
- impl_type null() const
- {
- return service_impl_.null();
- }
-
- /// Create a new context implementation.
- void create(impl_type& impl, context_base::method m)
- {
- service_impl_.create(impl, m);
- }
-
- /// Destroy a context implementation.
- void destroy(impl_type& impl)
- {
- service_impl_.destroy(impl);
- }
-
- /// Set options on the context.
- boost::system::error_code set_options(impl_type& impl,
- context_base::options o, boost::system::error_code& ec)
- {
- return service_impl_.set_options(impl, o, ec);
- }
-
- /// Set peer verification mode.
- boost::system::error_code set_verify_mode(impl_type& impl,
- context_base::verify_mode v, boost::system::error_code& ec)
- {
- return service_impl_.set_verify_mode(impl, v, ec);
- }
-
- /// Load a certification authority file for performing verification.
- boost::system::error_code load_verify_file(impl_type& impl,
- const std::string& filename, boost::system::error_code& ec)
- {
- return service_impl_.load_verify_file(impl, filename, ec);
- }
-
- /// Add a directory containing certification authority files to be used for
- /// performing verification.
- boost::system::error_code add_verify_path(impl_type& impl,
- const std::string& path, boost::system::error_code& ec)
- {
- return service_impl_.add_verify_path(impl, path, ec);
- }
-
- /// Use a certificate from a file.
- boost::system::error_code use_certificate_file(impl_type& impl,
- const std::string& filename, context_base::file_format format,
- boost::system::error_code& ec)
- {
- return service_impl_.use_certificate_file(impl, filename, format, ec);
- }
-
- /// Use a certificate chain from a file.
- boost::system::error_code use_certificate_chain_file(impl_type& impl,
- const std::string& filename, boost::system::error_code& ec)
- {
- return service_impl_.use_certificate_chain_file(impl, filename, ec);
- }
-
- /// Use a private key from a file.
- boost::system::error_code use_private_key_file(impl_type& impl,
- const std::string& filename, context_base::file_format format,
- boost::system::error_code& ec)
- {
- return service_impl_.use_private_key_file(impl, filename, format, ec);
- }
-
- /// Use an RSA private key from a file.
- boost::system::error_code use_rsa_private_key_file(impl_type& impl,
- const std::string& filename, context_base::file_format format,
- boost::system::error_code& ec)
- {
- return service_impl_.use_rsa_private_key_file(impl, filename, format, ec);
- }
-
- /// Use the specified file to obtain the temporary Diffie-Hellman parameters.
- boost::system::error_code use_tmp_dh_file(impl_type& impl,
- const std::string& filename, boost::system::error_code& ec)
- {
- return service_impl_.use_tmp_dh_file(impl, filename, ec);
- }
-
- /// Set the password callback.
- template <typename PasswordCallback>
- boost::system::error_code set_password_callback(impl_type& impl,
- PasswordCallback callback, boost::system::error_code& ec)
- {
- return service_impl_.set_password_callback(impl, callback, ec);
- }
-
-private:
- // Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- }
-
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
-};
-
-} // namespace old
-} // namespace ssl
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_SSL_OLD_CONTEXT_SERVICE_HPP
diff --git a/boost/asio/ssl/old/detail/openssl_context_service.hpp b/boost/asio/ssl/old/detail/openssl_context_service.hpp
deleted file mode 100644
index dd54c3297b..0000000000
--- a/boost/asio/ssl/old/detail/openssl_context_service.hpp
+++ /dev/null
@@ -1,396 +0,0 @@
-//
-// ssl/old/detail/openssl_context_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP
-#define BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <cstring>
-#include <string>
-#include <boost/function.hpp>
-#include <boost/asio/detail/throw_error.hpp>
-#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/ssl/context_base.hpp>
-#include <boost/asio/ssl/detail/openssl_init.hpp>
-#include <boost/asio/ssl/detail/openssl_types.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace ssl {
-namespace old {
-namespace detail {
-
-class openssl_context_service
- : public boost::asio::detail::service_base<openssl_context_service>
-{
-public:
- // The native type of the context.
- typedef ::SSL_CTX* impl_type;
-
- // The type for the password callback function object.
- typedef boost::function<std::string(std::size_t,
- context_base::password_purpose)> password_callback_type;
-
- // Constructor.
- openssl_context_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<openssl_context_service>(io_service)
- {
- }
-
- // Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- }
-
- // Return a null context implementation.
- static impl_type null()
- {
- return 0;
- }
-
- // Create a new context implementation.
- void create(impl_type& impl, context_base::method m)
- {
- switch (m)
- {
-#if defined(OPENSSL_NO_SSL2)
- case context_base::sslv2:
- case context_base::sslv2_client:
- case context_base::sslv2_server:
- boost::asio::detail::throw_error(boost::asio::error::invalid_argument);
- break;
-#else // defined(OPENSSL_NO_SSL2)
- case context_base::sslv2:
- impl = ::SSL_CTX_new(::SSLv2_method());
- break;
- case context_base::sslv2_client:
- impl = ::SSL_CTX_new(::SSLv2_client_method());
- break;
- case context_base::sslv2_server:
- impl = ::SSL_CTX_new(::SSLv2_server_method());
- break;
-#endif // defined(OPENSSL_NO_SSL2)
-#if defined(OPENSSL_NO_SSL3)
- case context_base::sslv3:
- case context_base::sslv3_client:
- case context_base::sslv3_server:
- boost::asio::detail::throw_error(boost::asio::error::invalid_argument);
- break;
-#else // defined(OPENSSL_NO_SSL3)
- case context_base::sslv3:
- impl = ::SSL_CTX_new(::SSLv3_method());
- break;
- case context_base::sslv3_client:
- impl = ::SSL_CTX_new(::SSLv3_client_method());
- break;
- case context_base::sslv3_server:
- impl = ::SSL_CTX_new(::SSLv3_server_method());
- break;
-#endif // defined(OPENSSL_NO_SSL3)
- case context_base::tlsv1:
- impl = ::SSL_CTX_new(::TLSv1_method());
- break;
- case context_base::tlsv1_client:
- impl = ::SSL_CTX_new(::TLSv1_client_method());
- break;
- case context_base::tlsv1_server:
- impl = ::SSL_CTX_new(::TLSv1_server_method());
- break;
- case context_base::sslv23:
- impl = ::SSL_CTX_new(::SSLv23_method());
- break;
- case context_base::sslv23_client:
- impl = ::SSL_CTX_new(::SSLv23_client_method());
- break;
- case context_base::sslv23_server:
- impl = ::SSL_CTX_new(::SSLv23_server_method());
- break;
- default:
- impl = ::SSL_CTX_new(0);
- break;
- }
- }
-
- // Destroy a context implementation.
- void destroy(impl_type& impl)
- {
- if (impl != null())
- {
- if (impl->default_passwd_callback_userdata)
- {
- password_callback_type* callback =
- static_cast<password_callback_type*>(
- impl->default_passwd_callback_userdata);
- delete callback;
- impl->default_passwd_callback_userdata = 0;
- }
-
- ::SSL_CTX_free(impl);
- impl = null();
- }
- }
-
- // Set options on the context.
- boost::system::error_code set_options(impl_type& impl,
- context_base::options o, boost::system::error_code& ec)
- {
- ::SSL_CTX_set_options(impl, o);
-
- ec = boost::system::error_code();
- return ec;
- }
-
- // Set peer verification mode.
- boost::system::error_code set_verify_mode(impl_type& impl,
- context_base::verify_mode v, boost::system::error_code& ec)
- {
- ::SSL_CTX_set_verify(impl, v, 0);
-
- ec = boost::system::error_code();
- return ec;
- }
-
- // Load a certification authority file for performing verification.
- boost::system::error_code load_verify_file(impl_type& impl,
- const std::string& filename, boost::system::error_code& ec)
- {
- if (::SSL_CTX_load_verify_locations(impl, filename.c_str(), 0) != 1)
- {
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
-
- ec = boost::system::error_code();
- return ec;
- }
-
- // Add a directory containing certification authority files to be used for
- // performing verification.
- boost::system::error_code add_verify_path(impl_type& impl,
- const std::string& path, boost::system::error_code& ec)
- {
- if (::SSL_CTX_load_verify_locations(impl, 0, path.c_str()) != 1)
- {
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
-
- ec = boost::system::error_code();
- return ec;
- }
-
- // Use a certificate from a file.
- boost::system::error_code use_certificate_file(impl_type& impl,
- const std::string& filename, context_base::file_format format,
- boost::system::error_code& ec)
- {
- int file_type;
- switch (format)
- {
- case context_base::asn1:
- file_type = SSL_FILETYPE_ASN1;
- break;
- case context_base::pem:
- file_type = SSL_FILETYPE_PEM;
- break;
- default:
- {
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
- }
-
- if (::SSL_CTX_use_certificate_file(impl, filename.c_str(), file_type) != 1)
- {
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
-
- ec = boost::system::error_code();
- return ec;
- }
-
- // Use a certificate chain from a file.
- boost::system::error_code use_certificate_chain_file(impl_type& impl,
- const std::string& filename, boost::system::error_code& ec)
- {
- if (::SSL_CTX_use_certificate_chain_file(impl, filename.c_str()) != 1)
- {
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
-
- ec = boost::system::error_code();
- return ec;
- }
-
- // Use a private key from a file.
- boost::system::error_code use_private_key_file(impl_type& impl,
- const std::string& filename, context_base::file_format format,
- boost::system::error_code& ec)
- {
- int file_type;
- switch (format)
- {
- case context_base::asn1:
- file_type = SSL_FILETYPE_ASN1;
- break;
- case context_base::pem:
- file_type = SSL_FILETYPE_PEM;
- break;
- default:
- {
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
- }
-
- if (::SSL_CTX_use_PrivateKey_file(impl, filename.c_str(), file_type) != 1)
- {
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
-
- ec = boost::system::error_code();
- return ec;
- }
-
- // Use an RSA private key from a file.
- boost::system::error_code use_rsa_private_key_file(impl_type& impl,
- const std::string& filename, context_base::file_format format,
- boost::system::error_code& ec)
- {
- int file_type;
- switch (format)
- {
- case context_base::asn1:
- file_type = SSL_FILETYPE_ASN1;
- break;
- case context_base::pem:
- file_type = SSL_FILETYPE_PEM;
- break;
- default:
- {
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
- }
-
- if (::SSL_CTX_use_RSAPrivateKey_file(
- impl, filename.c_str(), file_type) != 1)
- {
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
-
- ec = boost::system::error_code();
- return ec;
- }
-
- // Use the specified file to obtain the temporary Diffie-Hellman parameters.
- boost::system::error_code use_tmp_dh_file(impl_type& impl,
- const std::string& filename, boost::system::error_code& ec)
- {
- ::BIO* bio = ::BIO_new_file(filename.c_str(), "r");
- if (!bio)
- {
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
-
- ::DH* dh = ::PEM_read_bio_DHparams(bio, 0, 0, 0);
- if (!dh)
- {
- ::BIO_free(bio);
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
-
- ::BIO_free(bio);
- int result = ::SSL_CTX_set_tmp_dh(impl, dh);
- ::DH_free(dh);
- if (result != 1)
- {
- ec = boost::asio::error::invalid_argument;
- return ec;
- }
-
- ec = boost::system::error_code();
- return ec;
- }
-
- static int password_callback(char* buf, int size, int purpose, void* data)
- {
- using namespace std; // For strncat and strlen.
-
- if (data)
- {
- password_callback_type* callback =
- static_cast<password_callback_type*>(data);
- std::string passwd = (*callback)(static_cast<std::size_t>(size),
- purpose ? context_base::for_writing : context_base::for_reading);
- *buf = '\0';
- strncat(buf, passwd.c_str(), size);
- return strlen(buf);
- }
-
- return 0;
- }
-
- // Set the password callback.
- template <typename Password_Callback>
- boost::system::error_code set_password_callback(impl_type& impl,
- Password_Callback callback, boost::system::error_code& ec)
- {
- // Allocate callback function object if not already present.
- if (impl->default_passwd_callback_userdata)
- {
- password_callback_type* callback_function =
- static_cast<password_callback_type*>(
- impl->default_passwd_callback_userdata);
- *callback_function = callback;
- }
- else
- {
- password_callback_type* callback_function =
- new password_callback_type(callback);
- impl->default_passwd_callback_userdata = callback_function;
- }
-
- // Set the password callback.
- SSL_CTX_set_default_passwd_cb(impl,
- &openssl_context_service::password_callback);
-
- ec = boost::system::error_code();
- return ec;
- }
-
-private:
- // Ensure openssl is initialised.
- boost::asio::ssl::detail::openssl_init<> init_;
-};
-
-} // namespace detail
-} // namespace old
-} // namespace ssl
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_CONTEXT_SERVICE_HPP
diff --git a/boost/asio/ssl/old/detail/openssl_operation.hpp b/boost/asio/ssl/old/detail/openssl_operation.hpp
deleted file mode 100644
index 6835f5ff6a..0000000000
--- a/boost/asio/ssl/old/detail/openssl_operation.hpp
+++ /dev/null
@@ -1,526 +0,0 @@
-//
-// ssl/old/detail/openssl_operation.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-//
-// Distributed under the 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 BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_OPERATION_HPP
-#define BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_OPERATION_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <boost/function.hpp>
-#include <boost/bind.hpp>
-#include <boost/asio/buffer.hpp>
-#include <boost/asio/detail/assert.hpp>
-#include <boost/asio/detail/socket_ops.hpp>
-#include <boost/asio/placeholders.hpp>
-#include <boost/asio/ssl/detail/openssl_types.hpp>
-#include <boost/asio/ssl/error.hpp>
-#include <boost/asio/strand.hpp>
-#include <boost/system/system_error.hpp>
-#include <boost/asio/write.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace ssl {
-namespace old {
-namespace detail {
-
-typedef boost::function<int (::SSL*)> ssl_primitive_func;
-typedef boost::function<void (const boost::system::error_code&, int)>
- user_handler_func;
-
-// Network send_/recv buffer implementation
-//
-//
-class net_buffer
-{
- static const int NET_BUF_SIZE = 16*1024 + 256; // SSL record size + spare
-
- unsigned char buf_[NET_BUF_SIZE];
- unsigned char* data_start_;
- unsigned char* data_end_;
-
-public:
- net_buffer()
- {
- data_start_ = data_end_ = buf_;
- }
- unsigned char* get_unused_start() { return data_end_; }
- unsigned char* get_data_start() { return data_start_; }
- size_t get_unused_len() { return (NET_BUF_SIZE - (data_end_ - buf_)); }
- size_t get_data_len() { return (data_end_ - data_start_); }
- void data_added(size_t count)
- {
- data_end_ += count;
- data_end_ = data_end_ > (buf_ + NET_BUF_SIZE)?
- (buf_ + NET_BUF_SIZE):
- data_end_;
- }
- void data_removed(size_t count)
- {
- data_start_ += count;
- if (data_start_ >= data_end_) reset();
- }
- void reset() { data_start_ = buf_; data_end_ = buf_; }
- bool has_data() { return (data_start_ < data_end_); }
-}; // class net_buffer
-
-//
-// Operation class
-//
-//
-template <typename Stream>
-class openssl_operation
-{
-public:
-
- // Constructor for asynchronous operations
- openssl_operation(ssl_primitive_func primitive,
- Stream& socket,
- net_buffer& recv_buf,
- SSL* session,
- BIO* ssl_bio,
- user_handler_func handler,
- boost::asio::io_service::strand& strand
- )
- : primitive_(primitive)
- , user_handler_(handler)
- , strand_(&strand)
- , recv_buf_(recv_buf)
- , socket_(socket)
- , ssl_bio_(ssl_bio)
- , session_(session)
- {
- write_ = boost::bind(
- &openssl_operation::do_async_write,
- this, boost::arg<1>(), boost::arg<2>()
- );
- read_ = boost::bind(
- &openssl_operation::do_async_read,
- this
- );
- handler_= boost::bind(
- &openssl_operation::async_user_handler,
- this, boost::arg<1>(), boost::arg<2>()
- );
- }
-
- // Constructor for synchronous operations
- openssl_operation(ssl_primitive_func primitive,
- Stream& socket,
- net_buffer& recv_buf,
- SSL* session,
- BIO* ssl_bio)
- : primitive_(primitive)
- , strand_(0)
- , recv_buf_(recv_buf)
- , socket_(socket)
- , ssl_bio_(ssl_bio)
- , session_(session)
- {
- write_ = boost::bind(
- &openssl_operation::do_sync_write,
- this, boost::arg<1>(), boost::arg<2>()
- );
- read_ = boost::bind(
- &openssl_operation::do_sync_read,
- this
- );
- handler_ = boost::bind(
- &openssl_operation::sync_user_handler,
- this, boost::arg<1>(), boost::arg<2>()
- );
- }
-
- // Start operation
- // In case of asynchronous it returns 0, in sync mode returns success code
- // or throws an error...
- int start()
- {
- int rc = primitive_( session_ );
-
- bool is_operation_done = (rc > 0);
- // For connect/accept/shutdown, the operation
- // is done, when return code is 1
- // for write, it is done, when is retcode > 0
- // for read, it is done when retcode > 0
-
- int error_code = !is_operation_done ?
- ::SSL_get_error( session_, rc ) :
- 0;
- int sys_error_code = ERR_get_error();
-
- if (error_code == SSL_ERROR_SSL)
- return handler_(boost::system::error_code(
- sys_error_code, boost::asio::error::get_ssl_category()), rc);
-
- bool is_read_needed = (error_code == SSL_ERROR_WANT_READ);
- bool is_write_needed = (error_code == SSL_ERROR_WANT_WRITE ||
- ::BIO_ctrl_pending( ssl_bio_ ));
- bool is_shut_down_received =
- ((::SSL_get_shutdown( session_ ) & SSL_RECEIVED_SHUTDOWN) ==
- SSL_RECEIVED_SHUTDOWN);
- bool is_shut_down_sent =
- ((::SSL_get_shutdown( session_ ) & SSL_SENT_SHUTDOWN) ==
- SSL_SENT_SHUTDOWN);
-
- if (is_shut_down_sent && is_shut_down_received
- && is_operation_done && !is_write_needed)
- // SSL connection is shut down cleanly
- return handler_(boost::system::error_code(), 1);
-
- if (is_shut_down_received && !is_operation_done)
- // Shutdown has been requested, while we were reading or writing...
- // abort our action...
- return handler_(boost::asio::error::shut_down, 0);
-
- if (!is_operation_done && !is_read_needed && !is_write_needed
- && !is_shut_down_sent)
- {
- // The operation has failed... It is not completed and does
- // not want network communication nor does want to send shutdown out...
- if (error_code == SSL_ERROR_SYSCALL)
- {
- return handler_(boost::system::error_code(
- sys_error_code, boost::asio::error::system_category), rc);
- }
- else
- {
- return handler_(boost::system::error_code(
- sys_error_code, boost::asio::error::get_ssl_category()), rc);
- }
- }
-
- if (!is_operation_done && !is_write_needed)
- {
- // We may have left over data that we can pass to SSL immediately
- if (recv_buf_.get_data_len() > 0)
- {
- // Pass the buffered data to SSL
- int written = ::BIO_write
- (
- ssl_bio_,
- recv_buf_.get_data_start(),
- recv_buf_.get_data_len()
- );
-
- if (written > 0)
- {
- recv_buf_.data_removed(written);
- }
- else if (written < 0)
- {
- if (!BIO_should_retry(ssl_bio_))
- {
- // Some serios error with BIO....
- return handler_(boost::asio::error::no_recovery, 0);
- }
- }
-
- return start();
- }
- else if (is_read_needed || (is_shut_down_sent && !is_shut_down_received))
- {
- return read_();
- }
- }
-
- // Continue with operation, flush any SSL data out to network...
- return write_(is_operation_done, rc);
- }
-
-// Private implementation
-private:
- typedef boost::function<int (const boost::system::error_code&, int)>
- int_handler_func;
- typedef boost::function<int (bool, int)> write_func;
- typedef boost::function<int ()> read_func;
-
- ssl_primitive_func primitive_;
- user_handler_func user_handler_;
- boost::asio::io_service::strand* strand_;
- write_func write_;
- read_func read_;
- int_handler_func handler_;
-
- net_buffer send_buf_; // buffers for network IO
-
- // The recv buffer is owned by the stream, not the operation, since there can
- // be left over bytes after passing the data up to the application, and these
- // bytes need to be kept around for the next read operation issued by the
- // application.
- net_buffer& recv_buf_;
-
- Stream& socket_;
- BIO* ssl_bio_;
- SSL* session_;
-
- //
- int sync_user_handler(const boost::system::error_code& error, int rc)
- {
- if (!error)
- return rc;
-
- throw boost::system::system_error(error);
- }
-
- int async_user_handler(boost::system::error_code error, int rc)
- {
- if (rc < 0)
- {
- if (!error)
- error = boost::asio::error::no_recovery;
- rc = 0;
- }
-
- user_handler_(error, rc);
- return 0;
- }
-
- // Writes bytes asynchronously from SSL to NET
- int do_async_write(bool is_operation_done, int rc)
- {
- int len = ::BIO_ctrl_pending( ssl_bio_ );
- if ( len )
- {
- // There is something to write into net, do it...
- len = (int)send_buf_.get_unused_len() > len?
- len:
- send_buf_.get_unused_len();
-
- if (len == 0)
- {
- // In case our send buffer is full, we have just to wait until
- // previous send to complete...
- return 0;
- }
-
- // Read outgoing data from bio
- len = ::BIO_read( ssl_bio_, send_buf_.get_unused_start(), len);
-
- if (len > 0)
- {
- unsigned char *data_start = send_buf_.get_unused_start();
- send_buf_.data_added(len);
-
- BOOST_ASIO_ASSERT(strand_);
- boost::asio::async_write
- (
- socket_,
- boost::asio::buffer(data_start, len),
- strand_->wrap
- (
- boost::bind
- (
- &openssl_operation::async_write_handler,
- this,
- is_operation_done,
- rc,
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred
- )
- )
- );
-
- return 0;
- }
- else if (!BIO_should_retry(ssl_bio_))
- {
- // Seems like fatal error
- // reading from SSL BIO has failed...
- handler_(boost::asio::error::no_recovery, 0);
- return 0;
- }
- }
-
- if (is_operation_done)
- {
- // Finish the operation, with success
- handler_(boost::system::error_code(), rc);
- return 0;
- }
-
- // OPeration is not done and writing to net has been made...
- // start operation again
- start();
-
- return 0;
- }
-
- void async_write_handler(bool is_operation_done, int rc,
- const boost::system::error_code& error, size_t bytes_sent)
- {
- if (!error)
- {
- // Remove data from send buffer
- send_buf_.data_removed(bytes_sent);
-
- if (is_operation_done)
- handler_(boost::system::error_code(), rc);
- else
- // Since the operation was not completed, try it again...
- start();
- }
- else
- handler_(error, rc);
- }
-
- int do_async_read()
- {
- // Wait for new data
- BOOST_ASIO_ASSERT(strand_);
- socket_.async_read_some
- (
- boost::asio::buffer(recv_buf_.get_unused_start(),
- recv_buf_.get_unused_len()),
- strand_->wrap
- (
- boost::bind
- (
- &openssl_operation::async_read_handler,
- this,
- boost::asio::placeholders::error,
- boost::asio::placeholders::bytes_transferred
- )
- )
- );
- return 0;
- }
-
- void async_read_handler(const boost::system::error_code& error,
- size_t bytes_recvd)
- {
- if (!error)
- {
- recv_buf_.data_added(bytes_recvd);
-
- // Pass the received data to SSL
- int written = ::BIO_write
- (
- ssl_bio_,
- recv_buf_.get_data_start(),
- recv_buf_.get_data_len()
- );
-
- if (written > 0)
- {
- recv_buf_.data_removed(written);
- }
- else if (written < 0)
- {
- if (!BIO_should_retry(ssl_bio_))
- {
- // Some serios error with BIO....
- handler_(boost::asio::error::no_recovery, 0);
- return;
- }
- }
-
- // and try the SSL primitive again
- start();
- }
- else
- {
- // Error in network level...
- // SSL can't continue either...
- handler_(error, 0);
- }
- }
-
- // Syncronous functions...
- int do_sync_write(bool is_operation_done, int rc)
- {
- int len = ::BIO_ctrl_pending( ssl_bio_ );
- if ( len )
- {
- // There is something to write into net, do it...
- len = (int)send_buf_.get_unused_len() > len?
- len:
- send_buf_.get_unused_len();
-
- // Read outgoing data from bio
- len = ::BIO_read( ssl_bio_, send_buf_.get_unused_start(), len);
-
- if (len > 0)
- {
- size_t sent_len = boost::asio::write(
- socket_,
- boost::asio::buffer(send_buf_.get_unused_start(), len)
- );
-
- send_buf_.data_added(len);
- send_buf_.data_removed(sent_len);
- }
- else if (!BIO_should_retry(ssl_bio_))
- {
- // Seems like fatal error
- // reading from SSL BIO has failed...
- throw boost::system::system_error(boost::asio::error::no_recovery);
- }
- }
-
- if (is_operation_done)
- // Finish the operation, with success
- return rc;
-
- // Operation is not finished, start again.
- return start();
- }
-
- int do_sync_read()
- {
- size_t len = socket_.read_some
- (
- boost::asio::buffer(recv_buf_.get_unused_start(),
- recv_buf_.get_unused_len())
- );
-
- // Write data to ssl
- recv_buf_.data_added(len);
-
- // Pass the received data to SSL
- int written = ::BIO_write
- (
- ssl_bio_,
- recv_buf_.get_data_start(),
- recv_buf_.get_data_len()
- );
-
- if (written > 0)
- {
- recv_buf_.data_removed(written);
- }
- else if (written < 0)
- {
- if (!BIO_should_retry(ssl_bio_))
- {
- // Some serios error with BIO....
- throw boost::system::system_error(boost::asio::error::no_recovery);
- }
- }
-
- // Try the operation again
- return start();
- }
-}; // class openssl_operation
-
-} // namespace detail
-} // namespace old
-} // namespace ssl
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_OPERATION_HPP
diff --git a/boost/asio/ssl/old/detail/openssl_stream_service.hpp b/boost/asio/ssl/old/detail/openssl_stream_service.hpp
deleted file mode 100644
index afccf3652a..0000000000
--- a/boost/asio/ssl/old/detail/openssl_stream_service.hpp
+++ /dev/null
@@ -1,573 +0,0 @@
-//
-// ssl/old/detail/stream_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_STREAM_SERVICE_HPP
-#define BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_STREAM_SERVICE_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <cstddef>
-#include <climits>
-#include <memory>
-#include <boost/config.hpp>
-#include <boost/noncopyable.hpp>
-#include <boost/function.hpp>
-#include <boost/bind.hpp>
-#include <boost/asio/detail/buffer_sequence_adapter.hpp>
-#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/ssl/basic_context.hpp>
-#include <boost/asio/ssl/stream_base.hpp>
-#include <boost/asio/ssl/old/detail/openssl_operation.hpp>
-#include <boost/asio/ssl/detail/openssl_types.hpp>
-#include <boost/asio/strand.hpp>
-#include <boost/system/system_error.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace ssl {
-namespace old {
-namespace detail {
-
-class openssl_stream_service
- : public boost::asio::detail::service_base<openssl_stream_service>
-{
-private:
- enum { max_buffer_size = INT_MAX };
-
- //Base handler for asyncrhonous operations
- template <typename Stream>
- class base_handler
- {
- public:
- typedef boost::function<
- void (const boost::system::error_code&, size_t)> func_t;
-
- base_handler(boost::asio::io_service& io_service)
- : op_(NULL)
- , io_service_(io_service)
- , work_(io_service)
- {}
-
- void do_func(const boost::system::error_code& error, size_t size)
- {
- func_(error, size);
- }
-
- void set_operation(openssl_operation<Stream>* op) { op_ = op; }
- void set_func(func_t func) { func_ = func; }
-
- ~base_handler()
- {
- delete op_;
- }
-
- private:
- func_t func_;
- openssl_operation<Stream>* op_;
- boost::asio::io_service& io_service_;
- boost::asio::io_service::work work_;
- }; // class base_handler
-
- // Handler for asynchronous IO (write/read) operations
- template<typename Stream, typename Handler>
- class io_handler
- : public base_handler<Stream>
- {
- public:
- io_handler(Handler handler, boost::asio::io_service& io_service)
- : base_handler<Stream>(io_service)
- , handler_(handler)
- {
- this->set_func(boost::bind(
- &io_handler<Stream, Handler>::handler_impl,
- this, boost::arg<1>(), boost::arg<2>() ));
- }
-
- private:
- Handler handler_;
- void handler_impl(const boost::system::error_code& error, size_t size)
- {
- std::auto_ptr<io_handler<Stream, Handler> > this_ptr(this);
- handler_(error, size);
- }
- }; // class io_handler
-
- // Handler for asyncrhonous handshake (connect, accept) functions
- template <typename Stream, typename Handler>
- class handshake_handler
- : public base_handler<Stream>
- {
- public:
- handshake_handler(Handler handler, boost::asio::io_service& io_service)
- : base_handler<Stream>(io_service)
- , handler_(handler)
- {
- this->set_func(boost::bind(
- &handshake_handler<Stream, Handler>::handler_impl,
- this, boost::arg<1>(), boost::arg<2>() ));
- }
-
- private:
- Handler handler_;
- void handler_impl(const boost::system::error_code& error, size_t)
- {
- std::auto_ptr<handshake_handler<Stream, Handler> > this_ptr(this);
- handler_(error);
- }
-
- }; // class handshake_handler
-
- // Handler for asyncrhonous shutdown
- template <typename Stream, typename Handler>
- class shutdown_handler
- : public base_handler<Stream>
- {
- public:
- shutdown_handler(Handler handler, boost::asio::io_service& io_service)
- : base_handler<Stream>(io_service),
- handler_(handler)
- {
- this->set_func(boost::bind(
- &shutdown_handler<Stream, Handler>::handler_impl,
- this, boost::arg<1>(), boost::arg<2>() ));
- }
-
- private:
- Handler handler_;
- void handler_impl(const boost::system::error_code& error, size_t)
- {
- std::auto_ptr<shutdown_handler<Stream, Handler> > this_ptr(this);
- handler_(error);
- }
- }; // class shutdown_handler
-
-public:
- // The implementation type.
- typedef struct impl_struct
- {
- ::SSL* ssl;
- ::BIO* ext_bio;
- net_buffer recv_buf;
- } * impl_type;
-
- // Construct a new stream socket service for the specified io_service.
- explicit openssl_stream_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<openssl_stream_service>(io_service),
- strand_(io_service)
- {
- }
-
- // Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- }
-
- // Return a null stream implementation.
- impl_type null() const
- {
- return 0;
- }
-
- // Create a new stream implementation.
- template <typename Stream, typename Context_Service>
- void create(impl_type& impl, Stream& /*next_layer*/,
- basic_context<Context_Service>& context)
- {
- impl = new impl_struct;
- impl->ssl = ::SSL_new(context.impl());
- ::SSL_set_mode(impl->ssl, SSL_MODE_ENABLE_PARTIAL_WRITE);
- ::SSL_set_mode(impl->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
- ::BIO* int_bio = 0;
- impl->ext_bio = 0;
- ::BIO_new_bio_pair(&int_bio, 8192, &impl->ext_bio, 8192);
- ::SSL_set_bio(impl->ssl, int_bio, int_bio);
- }
-
- // Destroy a stream implementation.
- template <typename Stream>
- void destroy(impl_type& impl, Stream& /*next_layer*/)
- {
- if (impl != 0)
- {
- ::BIO_free(impl->ext_bio);
- ::SSL_free(impl->ssl);
- delete impl;
- impl = 0;
- }
- }
-
- // Perform SSL handshaking.
- template <typename Stream>
- boost::system::error_code handshake(impl_type& impl, Stream& next_layer,
- stream_base::handshake_type type, boost::system::error_code& ec)
- {
- try
- {
- openssl_operation<Stream> op(
- type == stream_base::client ?
- &ssl_wrap<mutex_type>::SSL_connect:
- &ssl_wrap<mutex_type>::SSL_accept,
- next_layer,
- impl->recv_buf,
- impl->ssl,
- impl->ext_bio);
- op.start();
- }
- catch (boost::system::system_error& e)
- {
- ec = e.code();
- return ec;
- }
-
- ec = boost::system::error_code();
- return ec;
- }
-
- // Start an asynchronous SSL handshake.
- template <typename Stream, typename Handler>
- void async_handshake(impl_type& impl, Stream& next_layer,
- stream_base::handshake_type type, Handler handler)
- {
- typedef handshake_handler<Stream, Handler> connect_handler;
-
- connect_handler* local_handler =
- new connect_handler(handler, get_io_service());
-
- openssl_operation<Stream>* op = new openssl_operation<Stream>
- (
- type == stream_base::client ?
- &ssl_wrap<mutex_type>::SSL_connect:
- &ssl_wrap<mutex_type>::SSL_accept,
- next_layer,
- impl->recv_buf,
- impl->ssl,
- impl->ext_bio,
- boost::bind
- (
- &base_handler<Stream>::do_func,
- local_handler,
- boost::arg<1>(),
- boost::arg<2>()
- ),
- strand_
- );
- local_handler->set_operation(op);
-
- strand_.post(boost::bind(&openssl_operation<Stream>::start, op));
- }
-
- // Shut down SSL on the stream.
- template <typename Stream>
- boost::system::error_code shutdown(impl_type& impl, Stream& next_layer,
- boost::system::error_code& ec)
- {
- try
- {
- openssl_operation<Stream> op(
- &ssl_wrap<mutex_type>::SSL_shutdown,
- next_layer,
- impl->recv_buf,
- impl->ssl,
- impl->ext_bio);
- op.start();
- }
- catch (boost::system::system_error& e)
- {
- ec = e.code();
- return ec;
- }
-
- ec = boost::system::error_code();
- return ec;
- }
-
- // Asynchronously shut down SSL on the stream.
- template <typename Stream, typename Handler>
- void async_shutdown(impl_type& impl, Stream& next_layer, Handler handler)
- {
- typedef shutdown_handler<Stream, Handler> disconnect_handler;
-
- disconnect_handler* local_handler =
- new disconnect_handler(handler, get_io_service());
-
- openssl_operation<Stream>* op = new openssl_operation<Stream>
- (
- &ssl_wrap<mutex_type>::SSL_shutdown,
- next_layer,
- impl->recv_buf,
- impl->ssl,
- impl->ext_bio,
- boost::bind
- (
- &base_handler<Stream>::do_func,
- local_handler,
- boost::arg<1>(),
- boost::arg<2>()
- ),
- strand_
- );
- local_handler->set_operation(op);
-
- strand_.post(boost::bind(&openssl_operation<Stream>::start, op));
- }
-
- // Write some data to the stream.
- template <typename Stream, typename Const_Buffers>
- std::size_t write_some(impl_type& impl, Stream& next_layer,
- const Const_Buffers& buffers, boost::system::error_code& ec)
- {
- size_t bytes_transferred = 0;
- try
- {
- boost::asio::const_buffer buffer =
- boost::asio::detail::buffer_sequence_adapter<
- boost::asio::const_buffer, Const_Buffers>::first(buffers);
-
- std::size_t buffer_size = boost::asio::buffer_size(buffer);
- if (buffer_size > max_buffer_size)
- buffer_size = max_buffer_size;
- else if (buffer_size == 0)
- {
- ec = boost::system::error_code();
- return 0;
- }
-
- boost::function<int (SSL*)> send_func =
- boost::bind(boost::type<int>(), &::SSL_write, boost::arg<1>(),
- boost::asio::buffer_cast<const void*>(buffer),
- static_cast<int>(buffer_size));
- openssl_operation<Stream> op(
- send_func,
- next_layer,
- impl->recv_buf,
- impl->ssl,
- impl->ext_bio
- );
- bytes_transferred = static_cast<size_t>(op.start());
- }
- catch (boost::system::system_error& e)
- {
- ec = e.code();
- return 0;
- }
-
- ec = boost::system::error_code();
- return bytes_transferred;
- }
-
- // Start an asynchronous write.
- template <typename Stream, typename Const_Buffers, typename Handler>
- void async_write_some(impl_type& impl, Stream& next_layer,
- const Const_Buffers& buffers, Handler handler)
- {
- typedef io_handler<Stream, Handler> send_handler;
-
- boost::asio::const_buffer buffer =
- boost::asio::detail::buffer_sequence_adapter<
- boost::asio::const_buffer, Const_Buffers>::first(buffers);
-
- std::size_t buffer_size = boost::asio::buffer_size(buffer);
- if (buffer_size > max_buffer_size)
- buffer_size = max_buffer_size;
- else if (buffer_size == 0)
- {
- get_io_service().post(boost::asio::detail::bind_handler(
- handler, boost::system::error_code(), 0));
- return;
- }
-
- send_handler* local_handler = new send_handler(handler, get_io_service());
-
- boost::function<int (SSL*)> send_func =
- boost::bind(boost::type<int>(), &::SSL_write, boost::arg<1>(),
- boost::asio::buffer_cast<const void*>(buffer),
- static_cast<int>(buffer_size));
-
- openssl_operation<Stream>* op = new openssl_operation<Stream>
- (
- send_func,
- next_layer,
- impl->recv_buf,
- impl->ssl,
- impl->ext_bio,
- boost::bind
- (
- &base_handler<Stream>::do_func,
- local_handler,
- boost::arg<1>(),
- boost::arg<2>()
- ),
- strand_
- );
- local_handler->set_operation(op);
-
- strand_.post(boost::bind(&openssl_operation<Stream>::start, op));
- }
-
- // Read some data from the stream.
- template <typename Stream, typename Mutable_Buffers>
- std::size_t read_some(impl_type& impl, Stream& next_layer,
- const Mutable_Buffers& buffers, boost::system::error_code& ec)
- {
- size_t bytes_transferred = 0;
- try
- {
- boost::asio::mutable_buffer buffer =
- boost::asio::detail::buffer_sequence_adapter<
- boost::asio::mutable_buffer, Mutable_Buffers>::first(buffers);
-
- std::size_t buffer_size = boost::asio::buffer_size(buffer);
- if (buffer_size > max_buffer_size)
- buffer_size = max_buffer_size;
- else if (buffer_size == 0)
- {
- ec = boost::system::error_code();
- return 0;
- }
-
- boost::function<int (SSL*)> recv_func =
- boost::bind(boost::type<int>(), &::SSL_read, boost::arg<1>(),
- boost::asio::buffer_cast<void*>(buffer),
- static_cast<int>(buffer_size));
- openssl_operation<Stream> op(recv_func,
- next_layer,
- impl->recv_buf,
- impl->ssl,
- impl->ext_bio
- );
-
- bytes_transferred = static_cast<size_t>(op.start());
- }
- catch (boost::system::system_error& e)
- {
- ec = e.code();
- return 0;
- }
-
- ec = boost::system::error_code();
- return bytes_transferred;
- }
-
- // Start an asynchronous read.
- template <typename Stream, typename Mutable_Buffers, typename Handler>
- void async_read_some(impl_type& impl, Stream& next_layer,
- const Mutable_Buffers& buffers, Handler handler)
- {
- typedef io_handler<Stream, Handler> recv_handler;
-
- boost::asio::mutable_buffer buffer =
- boost::asio::detail::buffer_sequence_adapter<
- boost::asio::mutable_buffer, Mutable_Buffers>::first(buffers);
-
- std::size_t buffer_size = boost::asio::buffer_size(buffer);
- if (buffer_size > max_buffer_size)
- buffer_size = max_buffer_size;
- else if (buffer_size == 0)
- {
- get_io_service().post(boost::asio::detail::bind_handler(
- handler, boost::system::error_code(), 0));
- return;
- }
-
- recv_handler* local_handler = new recv_handler(handler, get_io_service());
-
- boost::function<int (SSL*)> recv_func =
- boost::bind(boost::type<int>(), &::SSL_read, boost::arg<1>(),
- boost::asio::buffer_cast<void*>(buffer),
- static_cast<int>(buffer_size));
-
- openssl_operation<Stream>* op = new openssl_operation<Stream>
- (
- recv_func,
- next_layer,
- impl->recv_buf,
- impl->ssl,
- impl->ext_bio,
- boost::bind
- (
- &base_handler<Stream>::do_func,
- local_handler,
- boost::arg<1>(),
- boost::arg<2>()
- ),
- strand_
- );
- local_handler->set_operation(op);
-
- strand_.post(boost::bind(&openssl_operation<Stream>::start, op));
- }
-
- // Peek at the incoming data on the stream.
- template <typename Stream, typename Mutable_Buffers>
- std::size_t peek(impl_type& /*impl*/, Stream& /*next_layer*/,
- const Mutable_Buffers& /*buffers*/, boost::system::error_code& ec)
- {
- ec = boost::system::error_code();
- return 0;
- }
-
- // Determine the amount of data that may be read without blocking.
- template <typename Stream>
- std::size_t in_avail(impl_type& /*impl*/, Stream& /*next_layer*/,
- boost::system::error_code& ec)
- {
- ec = boost::system::error_code();
- return 0;
- }
-
-private:
- boost::asio::io_service::strand strand_;
-
- typedef boost::asio::detail::mutex mutex_type;
-
- template<typename Mutex>
- struct ssl_wrap
- {
- static Mutex ssl_mutex_;
-
- static int SSL_accept(SSL *ssl)
- {
- typename Mutex::scoped_lock lock(ssl_mutex_);
- return ::SSL_accept(ssl);
- }
-
- static int SSL_connect(SSL *ssl)
- {
- typename Mutex::scoped_lock lock(ssl_mutex_);
- return ::SSL_connect(ssl);
- }
-
- static int SSL_shutdown(SSL *ssl)
- {
- typename Mutex::scoped_lock lock(ssl_mutex_);
- return ::SSL_shutdown(ssl);
- }
- };
-};
-
-template<typename Mutex>
-Mutex openssl_stream_service::ssl_wrap<Mutex>::ssl_mutex_;
-
-} // namespace detail
-} // namespace old
-} // namespace ssl
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_SSL_OLD_DETAIL_OPENSSL_STREAM_SERVICE_HPP
diff --git a/boost/asio/ssl/old/stream.hpp b/boost/asio/ssl/old/stream.hpp
deleted file mode 100644
index a8c570ee08..0000000000
--- a/boost/asio/ssl/old/stream.hpp
+++ /dev/null
@@ -1,503 +0,0 @@
-//
-// ssl/old/stream.hpp
-// ~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_SSL_OLD_STREAM_HPP
-#define BOOST_ASIO_SSL_OLD_STREAM_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <cstddef>
-#include <boost/noncopyable.hpp>
-#include <boost/asio/detail/throw_error.hpp>
-#include <boost/asio/detail/type_traits.hpp>
-#include <boost/asio/error.hpp>
-#include <boost/asio/ssl/basic_context.hpp>
-#include <boost/asio/ssl/stream_base.hpp>
-#include <boost/asio/ssl/stream_service.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace ssl {
-namespace old {
-
-/// Provides stream-oriented functionality using SSL.
-/**
- * The stream class template provides asynchronous and blocking stream-oriented
- * functionality using SSL.
- *
- * @par Thread Safety
- * @e Distinct @e objects: Safe.@n
- * @e Shared @e objects: Unsafe.
- *
- * @par Example
- * To use the SSL stream template with an ip::tcp::socket, you would write:
- * @code
- * boost::asio::io_service io_service;
- * boost::asio::ssl::context context(io_service, boost::asio::ssl::context::sslv23);
- * boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sock(io_service, context);
- * @endcode
- *
- * @par Concepts:
- * AsyncReadStream, AsyncWriteStream, Stream, SyncRead_Stream, SyncWriteStream.
- */
-template <typename Stream, typename Service = old::stream_service>
-class stream
- : public stream_base,
- private boost::noncopyable
-{
-public:
- /// The type of the next layer.
- typedef typename remove_reference<Stream>::type next_layer_type;
-
- /// The type of the lowest layer.
- typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
-
- /// The type of the service that will be used to provide stream operations.
- typedef Service service_type;
-
- /// The native implementation type of the stream.
- typedef typename service_type::impl_type impl_type;
-
- /// Construct a stream.
- /**
- * This constructor creates a stream and initialises the underlying stream
- * object.
- *
- * @param arg The argument to be passed to initialise the underlying stream.
- *
- * @param context The SSL context to be used for the stream.
- */
- template <typename Arg, typename Context_Service>
- explicit stream(Arg& arg, basic_context<Context_Service>& context)
- : next_layer_(arg),
- service_(boost::asio::use_service<Service>(next_layer_.get_io_service())),
- impl_(service_.null())
- {
- service_.create(impl_, next_layer_, context);
- }
-
- /// Destructor.
- ~stream()
- {
- service_.destroy(impl_, next_layer_);
- }
-
- /// Get the io_service associated with the object.
- /**
- * This function may be used to obtain the io_service object that the stream
- * uses to dispatch handlers for asynchronous operations.
- *
- * @return A reference to the io_service object that stream will use to
- * dispatch handlers. Ownership is not transferred to the caller.
- */
- boost::asio::io_service& get_io_service()
- {
- return next_layer_.get_io_service();
- }
-
- /// Get a reference to the next layer.
- /**
- * This function returns a reference to the next layer in a stack of stream
- * layers.
- *
- * @return A reference to the next layer in the stack of stream layers.
- * Ownership is not transferred to the caller.
- */
- next_layer_type& next_layer()
- {
- return next_layer_;
- }
-
- /// Get a reference to the lowest layer.
- /**
- * This function returns a reference to the lowest layer in a stack of
- * stream layers.
- *
- * @return A reference to the lowest layer in the stack of stream layers.
- * Ownership is not transferred to the caller.
- */
- lowest_layer_type& lowest_layer()
- {
- return next_layer_.lowest_layer();
- }
-
- /// Get a const reference to the lowest layer.
- /**
- * This function returns a const reference to the lowest layer in a stack of
- * stream layers.
- *
- * @return A const reference to the lowest layer in the stack of stream
- * layers. Ownership is not transferred to the caller.
- */
- const lowest_layer_type& lowest_layer() const
- {
- return next_layer_.lowest_layer();
- }
-
- /// Get the underlying implementation in the native type.
- /**
- * This function may be used to obtain the underlying implementation of the
- * context. This is intended to allow access to stream functionality that is
- * not otherwise provided.
- */
- impl_type impl()
- {
- return impl_;
- }
-
- /// Perform SSL handshaking.
- /**
- * This function is used to perform SSL handshaking on the stream. The
- * function call will block until handshaking is complete or an error occurs.
- *
- * @param type The type of handshaking to be performed, i.e. as a client or as
- * a server.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- void handshake(handshake_type type)
- {
- boost::system::error_code ec;
- service_.handshake(impl_, next_layer_, type, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Perform SSL handshaking.
- /**
- * This function is used to perform SSL handshaking on the stream. The
- * function call will block until handshaking is complete or an error occurs.
- *
- * @param type The type of handshaking to be performed, i.e. as a client or as
- * a server.
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- boost::system::error_code handshake(handshake_type type,
- boost::system::error_code& ec)
- {
- return service_.handshake(impl_, next_layer_, type, ec);
- }
-
- /// Start an asynchronous SSL handshake.
- /**
- * This function is used to asynchronously perform an SSL handshake on the
- * stream. This function call 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:
- * @code void handler(
- * const boost::system::error_code& error // Result of operation.
- * ); @endcode
- */
- template <typename HandshakeHandler>
- void async_handshake(handshake_type type, HandshakeHandler handler)
- {
- service_.async_handshake(impl_, next_layer_, type, handler);
- }
-
- /// Shut down SSL on the stream.
- /**
- * This function is used to shut down SSL on the stream. The function call
- * will block until SSL has been shut down or an error occurs.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- void shutdown()
- {
- boost::system::error_code ec;
- service_.shutdown(impl_, next_layer_, ec);
- boost::asio::detail::throw_error(ec);
- }
-
- /// Shut down SSL on the stream.
- /**
- * This function is used to shut down SSL on the stream. The function call
- * will block until SSL has been shut down or an error occurs.
- *
- * @param ec Set to indicate what error occurred, if any.
- */
- boost::system::error_code shutdown(boost::system::error_code& ec)
- {
- return service_.shutdown(impl_, next_layer_, ec);
- }
-
- /// 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.
- *
- * @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:
- * @code void handler(
- * const boost::system::error_code& error // Result of operation.
- * ); @endcode
- */
- template <typename ShutdownHandler>
- void async_shutdown(ShutdownHandler handler)
- {
- service_.async_shutdown(impl_, next_layer_, handler);
- }
-
- /// Write some data to the stream.
- /**
- * This function is used to write data on the stream. The function call will
- * block until one or more bytes of data has been written successfully, or
- * until an error occurs.
- *
- * @param buffers The data to be written.
- *
- * @returns The number of bytes written.
- *
- * @throws boost::system::system_error Thrown on failure.
- *
- * @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)
- {
- boost::system::error_code ec;
- std::size_t s = service_.write_some(impl_, next_layer_, buffers, ec);
- boost::asio::detail::throw_error(ec);
- return s;
- }
-
- /// Write some data to the stream.
- /**
- * This function is used to write data on the stream. The function call will
- * block until one or more bytes of data has been written successfully, or
- * until an error occurs.
- *
- * @param buffers The data to be written to the stream.
- *
- * @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,
- boost::system::error_code& ec)
- {
- return service_.write_some(impl_, next_layer_, buffers, ec);
- }
-
- /// 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.
- *
- * @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.
- *
- * @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:
- * @code void handler(
- * const boost::system::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes written.
- * ); @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 blocking operation completes.
- */
- template <typename ConstBufferSequence, typename WriteHandler>
- void async_write_some(const ConstBufferSequence& buffers,
- WriteHandler handler)
- {
- service_.async_write_some(impl_, next_layer_, buffers, handler);
- }
-
- /// Read some data from the stream.
- /**
- * This function is used to read data from the stream. The function call will
- * block until one or more bytes of data has been read successfully, or until
- * an error occurs.
- *
- * @param buffers The buffers into which the data will be read.
- *
- * @returns The number of bytes read.
- *
- * @throws boost::system::system_error Thrown on failure.
- *
- * @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)
- {
- boost::system::error_code ec;
- std::size_t s = service_.read_some(impl_, next_layer_, buffers, ec);
- boost::asio::detail::throw_error(ec);
- return s;
- }
-
- /// Read some data from the stream.
- /**
- * This function is used to read data from the stream. The function call will
- * block until one or more bytes of data has been read successfully, or until
- * an error occurs.
- *
- * @param buffers The 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,
- boost::system::error_code& ec)
- {
- return service_.read_some(impl_, next_layer_, buffers, ec);
- }
-
- /// 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.
- *
- * @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.
- *
- * @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:
- * @code void handler(
- * const boost::system::error_code& error, // Result of operation.
- * std::size_t bytes_transferred // Number of bytes read.
- * ); @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.
- */
- template <typename MutableBufferSequence, typename ReadHandler>
- void async_read_some(const MutableBufferSequence& buffers,
- ReadHandler handler)
- {
- service_.async_read_some(impl_, next_layer_, buffers, handler);
- }
-
- /// Peek at the incoming data on the stream.
- /**
- * This function is used to peek at the incoming data on the stream, without
- * removing it from the input queue. The function call will block until data
- * has been read successfully or an error occurs.
- *
- * @param buffers The buffers into which the data will be read.
- *
- * @returns The number of bytes read.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- template <typename MutableBufferSequence>
- std::size_t peek(const MutableBufferSequence& buffers)
- {
- boost::system::error_code ec;
- std::size_t s = service_.peek(impl_, next_layer_, buffers, ec);
- boost::asio::detail::throw_error(ec);
- return s;
- }
-
- /// Peek at the incoming data on the stream.
- /**
- * This function is used to peek at the incoming data on the stream, withoutxi
- * removing it from the input queue. The function call will block until data
- * has been read successfully or an error occurs.
- *
- * @param buffers The 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.
- */
- template <typename MutableBufferSequence>
- std::size_t peek(const MutableBufferSequence& buffers,
- boost::system::error_code& ec)
- {
- return service_.peek(impl_, next_layer_, buffers, ec);
- }
-
- /// Determine the amount of data that may be read without blocking.
- /**
- * This function is used to determine the amount of data, in bytes, that may
- * be read from the stream without blocking.
- *
- * @returns The number of bytes of data that can be read without blocking.
- *
- * @throws boost::system::system_error Thrown on failure.
- */
- std::size_t in_avail()
- {
- boost::system::error_code ec;
- std::size_t s = service_.in_avail(impl_, next_layer_, ec);
- boost::asio::detail::throw_error(ec);
- return s;
- }
-
- /// Determine the amount of data that may be read without blocking.
- /**
- * This function is used to determine the amount of data, in bytes, that may
- * be read from the stream without blocking.
- *
- * @param ec Set to indicate what error occurred, if any.
- *
- * @returns The number of bytes of data that can be read without blocking.
- */
- std::size_t in_avail(boost::system::error_code& ec)
- {
- return service_.in_avail(impl_, next_layer_, ec);
- }
-
-private:
- /// The next layer.
- Stream next_layer_;
-
- /// The backend service implementation.
- service_type& service_;
-
- /// The underlying native implementation.
- impl_type impl_;
-};
-
-} // namespace old
-} // namespace ssl
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_SSL_OLD_STREAM_HPP
diff --git a/boost/asio/ssl/old/stream_service.hpp b/boost/asio/ssl/old/stream_service.hpp
deleted file mode 100644
index 282687c2ea..0000000000
--- a/boost/asio/ssl/old/stream_service.hpp
+++ /dev/null
@@ -1,186 +0,0 @@
-//
-// ssl/old/stream_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com
-// Copyright (c) 2005-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_SSL_OLD_STREAM_SERVICE_HPP
-#define BOOST_ASIO_SSL_OLD_STREAM_SERVICE_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-#include <cstddef>
-#include <boost/noncopyable.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/ssl/basic_context.hpp>
-#include <boost/asio/ssl/old/detail/openssl_stream_service.hpp>
-#include <boost/asio/ssl/stream_base.hpp>
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace ssl {
-namespace old {
-
-/// Default service implementation for an SSL stream.
-class stream_service
-#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
-#else
- : public boost::asio::detail::service_base<stream_service>
-#endif
-{
-private:
- // The type of the platform-specific implementation.
- typedef old::detail::openssl_stream_service service_impl_type;
-
-public:
-#if defined(GENERATING_DOCUMENTATION)
- /// The unique service identifier.
- static boost::asio::io_service::id id;
-#endif
-
- /// The type of a stream implementation.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined impl_type;
-#else
- typedef service_impl_type::impl_type impl_type;
-#endif
-
- /// Construct a new stream service for the specified io_service.
- explicit stream_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<stream_service>(io_service),
- service_impl_(boost::asio::use_service<service_impl_type>(io_service))
- {
- }
-
- /// Return a null stream implementation.
- impl_type null() const
- {
- return service_impl_.null();
- }
-
- /// Create a new stream implementation.
- template <typename Stream, typename Context_Service>
- void create(impl_type& impl, Stream& next_layer,
- basic_context<Context_Service>& context)
- {
- service_impl_.create(impl, next_layer, context);
- }
-
- /// Destroy a stream implementation.
- template <typename Stream>
- void destroy(impl_type& impl, Stream& next_layer)
- {
- service_impl_.destroy(impl, next_layer);
- }
-
- /// Perform SSL handshaking.
- template <typename Stream>
- boost::system::error_code handshake(impl_type& impl, Stream& next_layer,
- stream_base::handshake_type type, boost::system::error_code& ec)
- {
- return service_impl_.handshake(impl, next_layer, type, ec);
- }
-
- /// Start an asynchronous SSL handshake.
- template <typename Stream, typename HandshakeHandler>
- void async_handshake(impl_type& impl, Stream& next_layer,
- stream_base::handshake_type type, HandshakeHandler handler)
- {
- service_impl_.async_handshake(impl, next_layer, type, handler);
- }
-
- /// Shut down SSL on the stream.
- template <typename Stream>
- boost::system::error_code shutdown(impl_type& impl, Stream& next_layer,
- boost::system::error_code& ec)
- {
- return service_impl_.shutdown(impl, next_layer, ec);
- }
-
- /// Asynchronously shut down SSL on the stream.
- template <typename Stream, typename ShutdownHandler>
- void async_shutdown(impl_type& impl, Stream& next_layer,
- ShutdownHandler handler)
- {
- service_impl_.async_shutdown(impl, next_layer, handler);
- }
-
- /// Write some data to the stream.
- template <typename Stream, typename ConstBufferSequence>
- std::size_t write_some(impl_type& impl, Stream& next_layer,
- const ConstBufferSequence& buffers, boost::system::error_code& ec)
- {
- return service_impl_.write_some(impl, next_layer, buffers, ec);
- }
-
- /// Start an asynchronous write.
- template <typename Stream, typename ConstBufferSequence,
- typename WriteHandler>
- void async_write_some(impl_type& impl, Stream& next_layer,
- const ConstBufferSequence& buffers, WriteHandler handler)
- {
- service_impl_.async_write_some(impl, next_layer, buffers, handler);
- }
-
- /// Read some data from the stream.
- template <typename Stream, typename MutableBufferSequence>
- std::size_t read_some(impl_type& impl, Stream& next_layer,
- const MutableBufferSequence& buffers, boost::system::error_code& ec)
- {
- return service_impl_.read_some(impl, next_layer, buffers, ec);
- }
-
- /// Start an asynchronous read.
- template <typename Stream, typename MutableBufferSequence,
- typename ReadHandler>
- void async_read_some(impl_type& impl, Stream& next_layer,
- const MutableBufferSequence& buffers, ReadHandler handler)
- {
- service_impl_.async_read_some(impl, next_layer, buffers, handler);
- }
-
- /// Peek at the incoming data on the stream.
- template <typename Stream, typename MutableBufferSequence>
- std::size_t peek(impl_type& impl, Stream& next_layer,
- const MutableBufferSequence& buffers, boost::system::error_code& ec)
- {
- return service_impl_.peek(impl, next_layer, buffers, ec);
- }
-
- /// Determine the amount of data that may be read without blocking.
- template <typename Stream>
- std::size_t in_avail(impl_type& impl, Stream& next_layer,
- boost::system::error_code& ec)
- {
- return service_impl_.in_avail(impl, next_layer, ec);
- }
-
-private:
- // Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
- {
- }
-
- // The service that provides the platform-specific implementation.
- service_impl_type& service_impl_;
-};
-
-} // namespace old
-} // namespace ssl
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_SSL_OLD_STREAM_SERVICE_HPP
diff --git a/boost/asio/ssl/rfc2818_verification.hpp b/boost/asio/ssl/rfc2818_verification.hpp
index 21b0bca317..62919d79bf 100644
--- a/boost/asio/ssl/rfc2818_verification.hpp
+++ b/boost/asio/ssl/rfc2818_verification.hpp
@@ -17,11 +17,9 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <string>
-# include <boost/asio/ssl/detail/openssl_types.hpp>
-# include <boost/asio/ssl/verify_context.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <string>
+#include <boost/asio/ssl/detail/openssl_types.hpp>
+#include <boost/asio/ssl/verify_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -29,8 +27,6 @@ namespace boost {
namespace asio {
namespace ssl {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
/// Verifies a certificate against a hostname according to the rules described
/// in RFC 2818.
/**
@@ -47,9 +43,9 @@ namespace ssl {
* ctx.set_default_verify_paths();
*
* // Open a socket and connect it to the remote host.
- * boost::asio::io_service io_service;
- * ssl_socket sock(io_service, ctx);
- * tcp::resolver resolver(io_service);
+ * boost::asio::io_context io_context;
+ * ssl_socket sock(io_context, ctx);
+ * tcp::resolver resolver(io_context);
* tcp::resolver::query query("host.name", "https");
* boost::asio::connect(sock.lowest_layer(), resolver.resolve(query));
* sock.lowest_layer().set_option(tcp::no_delay(true));
@@ -87,8 +83,6 @@ private:
std::string host_;
};
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace ssl
} // namespace asio
} // namespace boost
diff --git a/boost/asio/ssl/stream.hpp b/boost/asio/ssl/stream.hpp
index 1b883d3245..860538156c 100644
--- a/boost/asio/ssl/stream.hpp
+++ b/boost/asio/ssl/stream.hpp
@@ -17,24 +17,20 @@
#include <boost/asio/detail/config.hpp>
-#if defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/ssl/old/stream.hpp>
-#else // defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/async_result.hpp>
-# include <boost/asio/detail/buffer_sequence_adapter.hpp>
-# include <boost/asio/detail/handler_type_requirements.hpp>
-# include <boost/asio/detail/noncopyable.hpp>
-# include <boost/asio/detail/type_traits.hpp>
-# include <boost/asio/ssl/context.hpp>
-# include <boost/asio/ssl/detail/buffered_handshake_op.hpp>
-# include <boost/asio/ssl/detail/handshake_op.hpp>
-# include <boost/asio/ssl/detail/io.hpp>
-# include <boost/asio/ssl/detail/read_op.hpp>
-# include <boost/asio/ssl/detail/shutdown_op.hpp>
-# include <boost/asio/ssl/detail/stream_core.hpp>
-# include <boost/asio/ssl/detail/write_op.hpp>
-# include <boost/asio/ssl/stream_base.hpp>
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/detail/buffer_sequence_adapter.hpp>
+#include <boost/asio/detail/handler_type_requirements.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+#include <boost/asio/ssl/context.hpp>
+#include <boost/asio/ssl/detail/buffered_handshake_op.hpp>
+#include <boost/asio/ssl/detail/handshake_op.hpp>
+#include <boost/asio/ssl/detail/io.hpp>
+#include <boost/asio/ssl/detail/read_op.hpp>
+#include <boost/asio/ssl/detail/shutdown_op.hpp>
+#include <boost/asio/ssl/detail/stream_core.hpp>
+#include <boost/asio/ssl/detail/write_op.hpp>
+#include <boost/asio/ssl/stream_base.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -42,12 +38,6 @@ namespace boost {
namespace asio {
namespace ssl {
-#if defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
-using boost::asio::ssl::old::stream;
-
-#else // defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
/// Provides stream-oriented functionality using SSL.
/**
* The stream class template provides asynchronous and blocking stream-oriented
@@ -62,9 +52,9 @@ using boost::asio::ssl::old::stream;
* @par Example
* To use the SSL stream template with an ip::tcp::socket, you would write:
* @code
- * boost::asio::io_service io_service;
+ * boost::asio::io_context io_context;
* boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
- * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(io_service, ctx);
+ * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(io_context, ctx);
* @endcode
*
* @par Concepts:
@@ -85,15 +75,16 @@ public:
SSL* ssl;
};
- /// (Deprecated: Use native_handle_type.) The underlying implementation type.
- typedef impl_struct* impl_type;
-
/// The type of the next layer.
typedef typename remove_reference<Stream>::type next_layer_type;
/// The type of the lowest layer.
typedef typename next_layer_type::lowest_layer_type lowest_layer_type;
+ /// The type of the executor associated with the object.
+ typedef typename lowest_layer_type::executor_type executor_type;
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Construct a stream.
/**
* This constructor creates a stream and initialises the underlying stream
@@ -104,30 +95,58 @@ public:
* @param ctx The SSL context to be used for the stream.
*/
template <typename Arg>
+ stream(Arg&& arg, context& ctx)
+ : next_layer_(BOOST_ASIO_MOVE_CAST(Arg)(arg)),
+ core_(ctx.native_handle(),
+ next_layer_.lowest_layer().get_executor().context())
+ {
+ }
+#else // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ template <typename Arg>
stream(Arg& arg, context& ctx)
: next_layer_(arg),
- core_(ctx.native_handle(), next_layer_.lowest_layer().get_io_service())
+ core_(ctx.native_handle(),
+ next_layer_.lowest_layer().get_executor().context())
{
- backwards_compatible_impl_.ssl = core_.engine_.native_handle();
}
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
/// Destructor.
+ /**
+ * @note A @c stream object must not be destroyed while there are pending
+ * asynchronous operations associated with it.
+ */
~stream()
{
}
- /// Get the io_service associated with the object.
+ /// Get the executor associated with the object.
/**
- * This function may be used to obtain the io_service object that the stream
+ * This function may be used to obtain the executor object that the stream
* uses to dispatch handlers for asynchronous operations.
*
- * @return A reference to the io_service object that stream will use to
- * dispatch handlers. Ownership is not transferred to the caller.
+ * @return A copy of the executor that stream will use to dispatch handlers.
*/
- boost::asio::io_service& get_io_service()
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return next_layer_.lowest_layer().get_executor();
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ boost::asio::io_context& get_io_context()
+ {
+ return next_layer_.lowest_layer().get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ boost::asio::io_context& get_io_service()
{
return next_layer_.lowest_layer().get_io_service();
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
/// Get the underlying implementation in the native type.
/**
@@ -140,7 +159,7 @@ public:
* suitable for passing to functions such as @c SSL_get_verify_result and
* @c SSL_get_peer_certificate:
* @code
- * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(io_service, ctx);
+ * boost::asio::ssl::stream<asio:ip::tcp::socket> sock(io_context, ctx);
*
* // ... establish connection and perform handshake ...
*
@@ -158,18 +177,6 @@ public:
return core_.engine_.native_handle();
}
- /// (Deprecated: Use native_handle().) Get the underlying implementation in
- /// the native type.
- /**
- * This function may be used to obtain the underlying implementation of the
- * context. This is intended to allow access to stream functionality that is
- * not otherwise provided.
- */
- impl_type impl()
- {
- return &backwards_compatible_impl_;
- }
-
/// Get a reference to the next layer.
/**
* This function returns a reference to the next layer in a stack of stream
@@ -253,10 +260,11 @@ public:
*
* @note Calls @c SSL_set_verify.
*/
- boost::system::error_code set_verify_mode(
+ BOOST_ASIO_SYNC_OP_VOID set_verify_mode(
verify_mode v, boost::system::error_code& ec)
{
- return core_.engine_.set_verify_mode(v, ec);
+ core_.engine_.set_verify_mode(v, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Set the peer verification depth.
@@ -290,10 +298,11 @@ public:
*
* @note Calls @c SSL_set_verify_depth.
*/
- boost::system::error_code set_verify_depth(
+ BOOST_ASIO_SYNC_OP_VOID set_verify_depth(
int depth, boost::system::error_code& ec)
{
- return core_.engine_.set_verify_depth(depth, ec);
+ core_.engine_.set_verify_depth(depth, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Set the callback used to verify peer certificates.
@@ -341,11 +350,12 @@ public:
* @note Calls @c SSL_set_verify.
*/
template <typename VerifyCallback>
- boost::system::error_code set_verify_callback(VerifyCallback callback,
+ BOOST_ASIO_SYNC_OP_VOID set_verify_callback(VerifyCallback callback,
boost::system::error_code& ec)
{
- return core_.engine_.set_verify_callback(
+ core_.engine_.set_verify_callback(
new detail::verify_callback<VerifyCallback>(callback), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform SSL handshaking.
@@ -375,11 +385,11 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code handshake(handshake_type type,
+ BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type,
boost::system::error_code& ec)
{
detail::io(next_layer_, core_, detail::handshake_op(type), ec);
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform SSL handshaking.
@@ -415,12 +425,12 @@ public:
* @param ec Set to indicate what error occurred, if any.
*/
template <typename ConstBufferSequence>
- boost::system::error_code handshake(handshake_type type,
+ BOOST_ASIO_SYNC_OP_VOID handshake(handshake_type type,
const ConstBufferSequence& buffers, boost::system::error_code& ec)
{
detail::io(next_layer_, core_,
detail::buffered_handshake_op<ConstBufferSequence>(type, buffers), ec);
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Start an asynchronous SSL handshake.
@@ -448,12 +458,11 @@ public:
// not meet the documented type requirements for a HandshakeHandler.
BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check;
- boost::asio::detail::async_result_init<
- HandshakeHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler));
+ boost::asio::async_completion<HandshakeHandler,
+ void (boost::system::error_code)> init(handler);
detail::async_io(next_layer_, core_,
- detail::handshake_op(type), init.handler);
+ detail::handshake_op(type), init.completion_handler);
return init.result.get();
}
@@ -490,13 +499,12 @@ public:
BOOST_ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK(
BufferedHandshakeHandler, handler) type_check;
- boost::asio::detail::async_result_init<BufferedHandshakeHandler,
- void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler));
+ boost::asio::async_completion<BufferedHandshakeHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
detail::async_io(next_layer_, core_,
detail::buffered_handshake_op<ConstBufferSequence>(type, buffers),
- init.handler);
+ init.completion_handler);
return init.result.get();
}
@@ -522,10 +530,10 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code shutdown(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID shutdown(boost::system::error_code& ec)
{
detail::io(next_layer_, core_, detail::shutdown_op(), ec);
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Asynchronously shut down SSL on the stream.
@@ -549,11 +557,11 @@ public:
// not meet the documented type requirements for a ShutdownHandler.
BOOST_ASIO_SHUTDOWN_HANDLER_CHECK(ShutdownHandler, handler) type_check;
- boost::asio::detail::async_result_init<
- ShutdownHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler));
+ boost::asio::async_completion<ShutdownHandler,
+ void (boost::system::error_code)> init(handler);
- detail::async_io(next_layer_, core_, detail::shutdown_op(), init.handler);
+ detail::async_io(next_layer_, core_, detail::shutdown_op(),
+ init.completion_handler);
return init.result.get();
}
@@ -639,12 +647,12 @@ public:
// not meet the documented type requirements for a WriteHandler.
BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
- boost::asio::detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ boost::asio::async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
detail::async_io(next_layer_, core_,
- detail::write_op<ConstBufferSequence>(buffers), init.handler);
+ detail::write_op<ConstBufferSequence>(buffers),
+ init.completion_handler);
return init.result.get();
}
@@ -731,12 +739,12 @@ public:
// not meet the documented type requirements for a ReadHandler.
BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
- boost::asio::detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ boost::asio::async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
detail::async_io(next_layer_, core_,
- detail::read_op<MutableBufferSequence>(buffers), init.handler);
+ detail::read_op<MutableBufferSequence>(buffers),
+ init.completion_handler);
return init.result.get();
}
@@ -744,11 +752,8 @@ public:
private:
Stream next_layer_;
detail::stream_core core_;
- impl_struct backwards_compatible_impl_;
};
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace ssl
} // namespace asio
} // namespace boost
diff --git a/boost/asio/ssl/stream_service.hpp b/boost/asio/ssl/stream_service.hpp
deleted file mode 100644
index 39e39f539c..0000000000
--- a/boost/asio/ssl/stream_service.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// ssl/stream_service.hpp
-// ~~~~~~~~~~~~~~~~~~~~~~
-//
-// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
-//
-// Distributed under the 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 BOOST_ASIO_SSL_STREAM_SERVICE_HPP
-#define BOOST_ASIO_SSL_STREAM_SERVICE_HPP
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1200)
-# pragma once
-#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
-
-#include <boost/asio/detail/config.hpp>
-
-#if defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/ssl/old/stream_service.hpp>
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
-#include <boost/asio/detail/push_options.hpp>
-
-namespace boost {
-namespace asio {
-namespace ssl {
-
-#if defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
-using boost::asio::ssl::old::stream_service;
-
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
-} // namespace ssl
-} // namespace asio
-} // namespace boost
-
-#include <boost/asio/detail/pop_options.hpp>
-
-#endif // BOOST_ASIO_SSL_STREAM_SERVICE_HPP
diff --git a/boost/asio/ssl/verify_context.hpp b/boost/asio/ssl/verify_context.hpp
index 6b7a884e77..4daf0c7e23 100644
--- a/boost/asio/ssl/verify_context.hpp
+++ b/boost/asio/ssl/verify_context.hpp
@@ -17,10 +17,8 @@
#include <boost/asio/detail/config.hpp>
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-# include <boost/asio/detail/noncopyable.hpp>
-# include <boost/asio/ssl/detail/openssl_types.hpp>
-#endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL)
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/ssl/detail/openssl_types.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -28,8 +26,6 @@ namespace boost {
namespace asio {
namespace ssl {
-#if !defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
/// A simple wrapper around the X509_STORE_CTX type, used during verification of
/// a peer certificate.
/**
@@ -64,8 +60,6 @@ private:
native_handle_type handle_;
};
-#endif // defined(BOOST_ASIO_ENABLE_OLD_SSL)
-
} // namespace ssl
} // namespace asio
} // namespace boost
diff --git a/boost/asio/steady_timer.hpp b/boost/asio/steady_timer.hpp
index f18ce399ae..af72adbf6e 100644
--- a/boost/asio/steady_timer.hpp
+++ b/boost/asio/steady_timer.hpp
@@ -17,22 +17,14 @@
#include <boost/asio/detail/config.hpp>
-#if defined(BOOST_ASIO_HAS_STD_CHRONO) \
- || defined(BOOST_ASIO_HAS_BOOST_CHRONO) \
- || defined(GENERATING_DOCUMENTATION)
-
-#if defined(BOOST_ASIO_HAS_STD_CHRONO)
-# include <chrono>
-#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
-# include <boost/chrono/system_clocks.hpp>
-#endif
+#if defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)
#include <boost/asio/basic_waitable_timer.hpp>
+#include <boost/asio/detail/chrono.hpp>
namespace boost {
namespace asio {
-#if defined(GENERATING_DOCUMENTATION)
/// Typedef for a timer based on the steady clock.
/**
* This typedef uses the C++11 @c &lt;chrono&gt; standard library facility, if
@@ -43,21 +35,10 @@ namespace asio {
* @endcode
*/
typedef basic_waitable_timer<chrono::steady_clock> steady_timer;
-#elif defined(BOOST_ASIO_HAS_STD_CHRONO)
-# if defined(BOOST_ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)
-typedef basic_waitable_timer<std::chrono::monotonic_clock> steady_timer;
-# else // defined(BOOST_ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)
-typedef basic_waitable_timer<std::chrono::steady_clock> steady_timer;
-# endif // defined(BOOST_ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)
-#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
-typedef basic_waitable_timer<boost::chrono::steady_clock> steady_timer;
-#endif
} // namespace asio
} // namespace boost
-#endif // defined(BOOST_ASIO_HAS_STD_CHRONO)
- // || defined(BOOST_ASIO_HAS_BOOST_CHRONO)
- // || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)
#endif // BOOST_ASIO_STEADY_TIMER_HPP
diff --git a/boost/asio/strand.hpp b/boost/asio/strand.hpp
index a4f3797e6a..9d0ad058f3 100644
--- a/boost/asio/strand.hpp
+++ b/boost/asio/strand.hpp
@@ -16,239 +16,273 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
-#include <boost/asio/async_result.hpp>
-#include <boost/asio/detail/handler_type_requirements.hpp>
-#include <boost/asio/detail/strand_service.hpp>
-#include <boost/asio/detail/wrapped_handler.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/detail/strand_executor_service.hpp>
+#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
-/// Provides serialised handler execution.
-/**
- * The io_service::strand class provides the ability to post and dispatch
- * handlers with the guarantee that none of those handlers will execute
- * concurrently.
- *
- * @par Order of handler invocation
- * Given:
- *
- * @li a strand object @c s
- *
- * @li an object @c a meeting completion handler requirements
- *
- * @li an object @c a1 which is an arbitrary copy of @c a made by the
- * implementation
- *
- * @li an object @c b meeting completion handler requirements
- *
- * @li an object @c b1 which is an arbitrary copy of @c b made by the
- * implementation
- *
- * if any of the following conditions are true:
- *
- * @li @c s.post(a) happens-before @c s.post(b)
- *
- * @li @c s.post(a) happens-before @c s.dispatch(b), where the latter is
- * performed outside the strand
- *
- * @li @c s.dispatch(a) happens-before @c s.post(b), where the former is
- * performed outside the strand
- *
- * @li @c s.dispatch(a) happens-before @c s.dispatch(b), where both are
- * performed outside the strand
- *
- * then @c asio_handler_invoke(a1, &a1) happens-before
- * @c asio_handler_invoke(b1, &b1).
- *
- * Note that in the following case:
- * @code async_op_1(..., s.wrap(a));
- * async_op_2(..., s.wrap(b)); @endcode
- * the completion of the first async operation will perform @c s.dispatch(a),
- * and the second will perform @c s.dispatch(b), but the order in which those
- * are performed is unspecified. That is, you cannot state whether one
- * happens-before the other. Therefore none of the above conditions are met and
- * no ordering guarantee is made.
- *
- * @note The implementation makes no guarantee that handlers posted or
- * dispatched through different @c strand objects will be invoked concurrently.
- *
- * @par Thread Safety
- * @e Distinct @e objects: Safe.@n
- * @e Shared @e objects: Safe.
- *
- * @par Concepts:
- * Dispatcher.
- */
-class io_service::strand
+/// Provides serialised function invocation for any executor type.
+template <typename Executor>
+class strand
{
public:
- /// Constructor.
+ /// The type of the underlying executor.
+ typedef Executor inner_executor_type;
+
+ /// Default constructor.
/**
- * Constructs the strand.
- *
- * @param io_service The io_service object that the strand will use to
- * dispatch handlers that are ready to be run.
+ * This constructor is only valid if the underlying executor type is default
+ * constructible.
*/
- explicit strand(boost::asio::io_service& io_service)
- : service_(boost::asio::use_service<
- boost::asio::detail::strand_service>(io_service))
+ strand()
+ : executor_(),
+ impl_(use_service<detail::strand_executor_service>(
+ executor_.context()).create_implementation())
{
- service_.construct(impl_);
}
- /// Destructor.
+ /// Construct a strand for the specified executor.
+ explicit strand(const Executor& e)
+ : executor_(e),
+ impl_(use_service<detail::strand_executor_service>(
+ executor_.context()).create_implementation())
+ {
+ }
+
+ /// Copy constructor.
+ strand(const strand& other) BOOST_ASIO_NOEXCEPT
+ : executor_(other.executor_),
+ impl_(other.impl_)
+ {
+ }
+
+ /// Converting constructor.
/**
- * Destroys a strand.
- *
- * Handlers posted through the strand that have not yet been invoked will
- * still be dispatched in a way that meets the guarantee of non-concurrency.
+ * This constructor is only valid if the @c OtherExecutor type is convertible
+ * to @c Executor.
*/
- ~strand()
+ template <class OtherExecutor>
+ strand(
+ const strand<OtherExecutor>& other) BOOST_ASIO_NOEXCEPT
+ : executor_(other.executor_),
+ impl_(other.impl_)
+ {
+ }
+
+ /// Assignment operator.
+ strand& operator=(const strand& other) BOOST_ASIO_NOEXCEPT
{
+ executor_ = other.executor_;
+ impl_ = other.impl_;
+ return *this;
}
- /// Get the io_service associated with the strand.
+ /// Converting assignment operator.
/**
- * This function may be used to obtain the io_service object that the strand
- * uses to dispatch handlers for asynchronous operations.
- *
- * @return A reference to the io_service object that the strand will use to
- * dispatch handlers. Ownership is not transferred to the caller.
+ * This assignment operator is only valid if the @c OtherExecutor type is
+ * convertible to @c Executor.
*/
- boost::asio::io_service& get_io_service()
+ template <class OtherExecutor>
+ strand& operator=(
+ const strand<OtherExecutor>& other) BOOST_ASIO_NOEXCEPT
+ {
+ executor_ = other.executor_;
+ impl_ = other.impl_;
+ return *this;
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move constructor.
+ strand(strand&& other) BOOST_ASIO_NOEXCEPT
+ : executor_(BOOST_ASIO_MOVE_CAST(Executor)(other.executor_)),
+ impl_(BOOST_ASIO_MOVE_CAST(implementation_type)(other.impl_))
{
- return service_.get_io_service();
}
- /// Request the strand to invoke the given handler.
+ /// Converting move constructor.
/**
- * This function is used to ask the strand to execute the given handler.
- *
- * The strand object guarantees that handlers posted or dispatched through
- * the strand will not be executed concurrently. The handler may be executed
- * inside this function if the guarantee can be met. If this function is
- * called from within a handler that was posted or dispatched through the same
- * strand, then the new handler will be executed immediately.
- *
- * The strand's guarantee is in addition to the guarantee provided by the
- * underlying io_service. The io_service guarantees that the handler will only
- * be called in a thread in which the io_service's run member function is
- * currently being invoked.
- *
- * @param handler The handler to be called. The strand will make a copy of the
- * handler object as required. The function signature of the handler must be:
- * @code void handler(); @endcode
+ * This constructor is only valid if the @c OtherExecutor type is convertible
+ * to @c Executor.
*/
- template <typename CompletionHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
- dispatch(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
+ template <class OtherExecutor>
+ strand(strand<OtherExecutor>&& other) BOOST_ASIO_NOEXCEPT
+ : executor_(BOOST_ASIO_MOVE_CAST(OtherExecutor)(other)),
+ impl_(BOOST_ASIO_MOVE_CAST(implementation_type)(other.impl_))
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a CompletionHandler.
- BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
+ }
- detail::async_result_init<
- CompletionHandler, void ()> init(
- BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
+ /// Move assignment operator.
+ strand& operator=(strand&& other) BOOST_ASIO_NOEXCEPT
+ {
+ executor_ = BOOST_ASIO_MOVE_CAST(Executor)(other);
+ impl_ = BOOST_ASIO_MOVE_CAST(implementation_type)(other.impl_);
+ return *this;
+ }
- service_.dispatch(impl_, init.handler);
+ /// Converting move assignment operator.
+ /**
+ * This assignment operator is only valid if the @c OtherExecutor type is
+ * convertible to @c Executor.
+ */
+ template <class OtherExecutor>
+ strand& operator=(
+ const strand<OtherExecutor>&& other) BOOST_ASIO_NOEXCEPT
+ {
+ executor_ = BOOST_ASIO_MOVE_CAST(OtherExecutor)(other);
+ impl_ = BOOST_ASIO_MOVE_CAST(implementation_type)(other.impl_);
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Destructor.
+ ~strand()
+ {
+ }
- return init.result.get();
+ /// Obtain the underlying executor.
+ inner_executor_type get_inner_executor() const BOOST_ASIO_NOEXCEPT
+ {
+ return executor_;
}
- /// Request the strand to invoke the given handler and return
- /// immediately.
+ /// Obtain the underlying execution context.
+ execution_context& context() const BOOST_ASIO_NOEXCEPT
+ {
+ return executor_.context();
+ }
+
+ /// Inform the strand that it has some outstanding work to do.
/**
- * This function is used to ask the strand to execute the given handler, but
- * without allowing the strand to call the handler from inside this function.
- *
- * The strand object guarantees that handlers posted or dispatched through
- * the strand will not be executed concurrently. The strand's guarantee is in
- * addition to the guarantee provided by the underlying io_service. The
- * io_service guarantees that the handler will only be called in a thread in
- * which the io_service's run member function is currently being invoked.
- *
- * @param handler The handler to be called. The strand will make a copy of the
- * handler object as required. The function signature of the handler must be:
- * @code void handler(); @endcode
+ * The strand delegates this call to its underlying executor.
*/
- template <typename CompletionHandler>
- BOOST_ASIO_INITFN_RESULT_TYPE(CompletionHandler, void ())
- post(BOOST_ASIO_MOVE_ARG(CompletionHandler) handler)
+ void on_work_started() const BOOST_ASIO_NOEXCEPT
{
- // If you get an error on the following line it means that your handler does
- // not meet the documented type requirements for a CompletionHandler.
- BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
+ executor_.on_work_started();
+ }
- detail::async_result_init<
- CompletionHandler, void ()> init(
- BOOST_ASIO_MOVE_CAST(CompletionHandler)(handler));
+ /// Inform the strand that some work is no longer outstanding.
+ /**
+ * The strand delegates this call to its underlying executor.
+ */
+ void on_work_finished() const BOOST_ASIO_NOEXCEPT
+ {
+ executor_.on_work_finished();
+ }
- service_.post(impl_, init.handler);
+ /// Request the strand to invoke the given function object.
+ /**
+ * This function is used to ask the strand to execute the given function
+ * object on its underlying executor. The function object will be executed
+ * inside this function if the strand is not otherwise busy and if the
+ * underlying executor's @c dispatch() function is also able to execute the
+ * function before returning.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+ {
+ detail::strand_executor_service::dispatch(impl_,
+ executor_, BOOST_ASIO_MOVE_CAST(Function)(f), a);
+ }
- return init.result.get();
+ /// Request the strand to invoke the given function object.
+ /**
+ * This function is used to ask the executor to execute the given function
+ * object. The function object will never be executed inside this function.
+ * Instead, it will be scheduled by the underlying executor's defer function.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void post(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
+ {
+ detail::strand_executor_service::post(impl_,
+ executor_, BOOST_ASIO_MOVE_CAST(Function)(f), a);
}
- /// Create a new handler that automatically dispatches the wrapped handler
- /// on the strand.
+ /// Request the strand to invoke the given function object.
/**
- * This function is used to create a new handler function object that, when
- * invoked, will automatically pass the wrapped handler to the strand's
- * dispatch function.
+ * This function is used to ask the executor to execute the given function
+ * object. The function object will never be executed inside this function.
+ * Instead, it will be scheduled by the underlying executor's defer function.
*
- * @param handler The handler to be wrapped. The strand will make a copy of
- * the handler object as required. The function signature of the handler must
- * be: @code void handler(A1 a1, ... An an); @endcode
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
*
- * @return A function object that, when invoked, passes the wrapped handler to
- * the strand's dispatch function. Given a function object with the signature:
- * @code R f(A1 a1, ... An an); @endcode
- * If this function object is passed to the wrap function like so:
- * @code strand.wrap(f); @endcode
- * then the return value is a function object with the signature
- * @code void g(A1 a1, ... An an); @endcode
- * that, when invoked, executes code equivalent to:
- * @code strand.dispatch(boost::bind(f, a1, ... an)); @endcode
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
*/
- template <typename Handler>
-#if defined(GENERATING_DOCUMENTATION)
- unspecified
-#else
- detail::wrapped_handler<strand, Handler, detail::is_continuation_if_running>
-#endif
- wrap(Handler handler)
+ template <typename Function, typename Allocator>
+ void defer(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const
{
- return detail::wrapped_handler<io_service::strand, Handler,
- detail::is_continuation_if_running>(*this, handler);
+ detail::strand_executor_service::defer(impl_,
+ executor_, BOOST_ASIO_MOVE_CAST(Function)(f), a);
}
/// Determine whether the strand is running in the current thread.
/**
- * @return @c true if the current thread is executing a handler that was
- * submitted to the strand using post(), dispatch() or wrap(). Otherwise
+ * @return @c true if the current thread is executing a function that was
+ * submitted to the strand using post(), dispatch() or defer(). Otherwise
* returns @c false.
*/
- bool running_in_this_thread() const
+ bool running_in_this_thread() const BOOST_ASIO_NOEXCEPT
+ {
+ return detail::strand_executor_service::running_in_this_thread(impl_);
+ }
+
+ /// Compare two strands for equality.
+ /**
+ * Two strands are equal if they refer to the same ordered, non-concurrent
+ * state.
+ */
+ friend bool operator==(const strand& a, const strand& b) BOOST_ASIO_NOEXCEPT
+ {
+ return a.impl_ == b.impl_;
+ }
+
+ /// Compare two strands for inequality.
+ /**
+ * Two strands are equal if they refer to the same ordered, non-concurrent
+ * state.
+ */
+ friend bool operator!=(const strand& a, const strand& b) BOOST_ASIO_NOEXCEPT
{
- return service_.running_in_this_thread(impl_);
+ return a.impl_ != b.impl_;
}
private:
- boost::asio::detail::strand_service& service_;
- boost::asio::detail::strand_service::implementation_type impl_;
+ Executor executor_;
+ typedef detail::strand_executor_service::implementation_type
+ implementation_type;
+ implementation_type impl_;
};
-/// (Deprecated: Use boost::asio::io_service::strand.) Typedef for backwards
-/// compatibility.
-typedef boost::asio::io_service::strand strand;
-
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
+// If both io_context.hpp and strand.hpp have been included, automatically
+// include the header file needed for the io_context::strand class.
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+# if defined(BOOST_ASIO_IO_CONTEXT_HPP)
+# include <boost/asio/io_context_strand.hpp>
+# endif // defined(BOOST_ASIO_IO_CONTEXT_HPP)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
#endif // BOOST_ASIO_STRAND_HPP
diff --git a/boost/asio/stream_socket_service.hpp b/boost/asio/stream_socket_service.hpp
index 09463f4718..534ce6528b 100644
--- a/boost/asio/stream_socket_service.hpp
+++ b/boost/asio/stream_socket_service.hpp
@@ -16,11 +16,14 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <cstddef>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#if defined(BOOST_ASIO_WINDOWS_RUNTIME)
# include <boost/asio/detail/winrt_ssocket_service.hpp>
@@ -39,7 +42,7 @@ namespace asio {
template <typename Protocol>
class stream_socket_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<stream_socket_service<Protocol> >
#endif
@@ -47,7 +50,7 @@ class stream_socket_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
/// The protocol type.
@@ -74,13 +77,6 @@ public:
typedef typename service_impl_type::implementation_type implementation_type;
#endif
- /// (Deprecated: Use native_handle_type.) The native socket type.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined native_type;
-#else
- typedef typename service_impl_type::native_handle_type native_type;
-#endif
-
/// The native socket type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
@@ -88,11 +84,11 @@ public:
typedef typename service_impl_type::native_handle_type native_handle_type;
#endif
- /// Construct a new stream socket service for the specified io_service.
- explicit stream_socket_service(boost::asio::io_service& io_service)
+ /// Construct a new stream socket service for the specified io_context.
+ explicit stream_socket_service(boost::asio::io_context& io_context)
: boost::asio::detail::service_base<
- stream_socket_service<Protocol> >(io_service),
- service_impl_(io_service)
+ stream_socket_service<Protocol> >(io_context),
+ service_impl_(io_context)
{
}
@@ -143,22 +139,23 @@ public:
}
/// Open a stream socket.
- boost::system::error_code open(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID open(implementation_type& impl,
const protocol_type& protocol, boost::system::error_code& ec)
{
if (protocol.type() == BOOST_ASIO_OS_DEF(SOCK_STREAM))
service_impl_.open(impl, protocol, ec);
else
ec = boost::asio::error::invalid_argument;
- return ec;
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Assign an existing native socket to a stream socket.
- boost::system::error_code assign(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl,
const protocol_type& protocol, const native_handle_type& native_socket,
boost::system::error_code& ec)
{
- return service_impl_.assign(impl, protocol, native_socket, ec);
+ service_impl_.assign(impl, protocol, native_socket, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is open.
@@ -168,16 +165,18 @@ public:
}
/// Close a stream socket implementation.
- boost::system::error_code close(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.close(impl, ec);
+ service_impl_.close(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
- /// (Deprecated: Use native_handle().) Get the native socket implementation.
- native_type native(implementation_type& impl)
+ /// Release ownership of the underlying socket.
+ native_handle_type release(implementation_type& impl,
+ boost::system::error_code& ec)
{
- return service_impl_.native_handle(impl);
+ return service_impl_.release(impl, ec);
}
/// Get the native socket implementation.
@@ -187,10 +186,11 @@ public:
}
/// Cancel all asynchronous operations associated with the socket.
- boost::system::error_code cancel(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.cancel(impl, ec);
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the socket is at the out-of-band data mark.
@@ -208,17 +208,19 @@ public:
}
/// Bind the stream socket to the specified local endpoint.
- boost::system::error_code bind(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID bind(implementation_type& impl,
const endpoint_type& endpoint, boost::system::error_code& ec)
{
- return service_impl_.bind(impl, endpoint, ec);
+ service_impl_.bind(impl, endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Connect the stream socket to the specified endpoint.
- boost::system::error_code connect(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID connect(implementation_type& impl,
const endpoint_type& peer_endpoint, boost::system::error_code& ec)
{
- return service_impl_.connect(impl, peer_endpoint, ec);
+ service_impl_.connect(impl, peer_endpoint, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Start an asynchronous connect.
@@ -229,37 +231,39 @@ public:
const endpoint_type& peer_endpoint,
BOOST_ASIO_MOVE_ARG(ConnectHandler) handler)
{
- detail::async_result_init<
- ConnectHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(ConnectHandler)(handler));
+ async_completion<ConnectHandler,
+ void (boost::system::error_code)> init(handler);
- service_impl_.async_connect(impl, peer_endpoint, init.handler);
+ service_impl_.async_connect(impl, peer_endpoint, init.completion_handler);
return init.result.get();
}
/// Set a socket option.
template <typename SettableSocketOption>
- boost::system::error_code set_option(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID set_option(implementation_type& impl,
const SettableSocketOption& option, boost::system::error_code& ec)
{
- return service_impl_.set_option(impl, option, ec);
+ service_impl_.set_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get a socket option.
template <typename GettableSocketOption>
- boost::system::error_code get_option(const implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID get_option(const implementation_type& impl,
GettableSocketOption& option, boost::system::error_code& ec) const
{
- return service_impl_.get_option(impl, option, ec);
+ service_impl_.get_option(impl, option, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Perform an IO control command on the socket.
template <typename IoControlCommand>
- boost::system::error_code io_control(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID io_control(implementation_type& impl,
IoControlCommand& command, boost::system::error_code& ec)
{
- return service_impl_.io_control(impl, command, ec);
+ service_impl_.io_control(impl, command, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the socket.
@@ -269,10 +273,11 @@ public:
}
/// Sets the non-blocking mode of the socket.
- boost::system::error_code non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.non_blocking(impl, mode, ec);
+ service_impl_.non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Gets the non-blocking mode of the native socket implementation.
@@ -282,10 +287,11 @@ public:
}
/// Sets the non-blocking mode of the native socket implementation.
- boost::system::error_code native_non_blocking(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID native_non_blocking(implementation_type& impl,
bool mode, boost::system::error_code& ec)
{
- return service_impl_.native_non_blocking(impl, mode, ec);
+ service_impl_.native_non_blocking(impl, mode, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the local endpoint.
@@ -303,10 +309,36 @@ public:
}
/// Disable sends or receives on the socket.
- boost::system::error_code shutdown(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID shutdown(implementation_type& impl,
socket_base::shutdown_type what, boost::system::error_code& ec)
{
- return service_impl_.shutdown(impl, what, ec);
+ service_impl_.shutdown(impl, what, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Wait for the socket to become ready to read, ready to write, or to have
+ /// pending error conditions.
+ BOOST_ASIO_SYNC_OP_VOID wait(implementation_type& impl,
+ socket_base::wait_type w, boost::system::error_code& ec)
+ {
+ service_impl_.wait(impl, w, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Asynchronously wait for the socket to become ready to read, ready to
+ /// write, or to have pending error conditions.
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(implementation_type& impl, socket_base::wait_type w,
+ BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ service_impl_.async_wait(impl, w, init.completion_handler);
+
+ return init.result.get();
}
/// Send the given data to the peer.
@@ -327,11 +359,10 @@ public:
socket_base::message_flags flags,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_send(impl, buffers, flags, init.handler);
+ service_impl_.async_send(impl, buffers, flags, init.completion_handler);
return init.result.get();
}
@@ -354,20 +385,19 @@ public:
socket_base::message_flags flags,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_receive(impl, buffers, flags, init.handler);
+ service_impl_.async_receive(impl, buffers, flags, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -379,4 +409,6 @@ private:
#include <boost/asio/detail/pop_options.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_STREAM_SOCKET_SERVICE_HPP
diff --git a/boost/asio/system_context.hpp b/boost/asio/system_context.hpp
new file mode 100644
index 0000000000..8479925e7a
--- /dev/null
+++ b/boost/asio/system_context.hpp
@@ -0,0 +1,80 @@
+//
+// system_context.hpp
+// ~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SYSTEM_CONTEXT_HPP
+#define BOOST_ASIO_SYSTEM_CONTEXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/scheduler.hpp>
+#include <boost/asio/detail/thread_group.hpp>
+#include <boost/asio/execution_context.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+class system_executor;
+
+/// The executor context for the system executor.
+class system_context : public execution_context
+{
+public:
+ /// The executor type associated with the context.
+ typedef system_executor executor_type;
+
+ /// Destructor shuts down all threads in the system thread pool.
+ BOOST_ASIO_DECL ~system_context();
+
+ /// Obtain an executor for the context.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT;
+
+ /// Signal all threads in the system thread pool to stop.
+ BOOST_ASIO_DECL void stop();
+
+ /// Determine whether the system thread pool has been stopped.
+ BOOST_ASIO_DECL bool stopped() const BOOST_ASIO_NOEXCEPT;
+
+ /// Join all threads in the system thread pool.
+ BOOST_ASIO_DECL void join();
+
+#if defined(GENERATING_DOCUMENTATION)
+private:
+#endif // defined(GENERATING_DOCUMENTATION)
+ // Constructor creates all threads in the system thread pool.
+ BOOST_ASIO_DECL system_context();
+
+private:
+ friend class system_executor;
+
+ struct thread_function;
+
+ // The underlying scheduler.
+ detail::scheduler& scheduler_;
+
+ // The threads in the system thread pool.
+ detail::thread_group threads_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/impl/system_context.hpp>
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/impl/system_context.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_ASIO_SYSTEM_CONTEXT_HPP
diff --git a/boost/asio/system_executor.hpp b/boost/asio/system_executor.hpp
new file mode 100644
index 0000000000..0d8eb0a535
--- /dev/null
+++ b/boost/asio/system_executor.hpp
@@ -0,0 +1,131 @@
+//
+// system_executor.hpp
+// ~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_SYSTEM_EXECUTOR_HPP
+#define BOOST_ASIO_SYSTEM_EXECUTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+class system_context;
+
+/// An executor that uses arbitrary threads.
+/**
+ * The system executor represents an execution context where functions are
+ * permitted to run on arbitrary threads. The post() and defer() functions
+ * schedule the function to run on an unspecified system thread pool, and
+ * dispatch() invokes the function immediately.
+ */
+class system_executor
+{
+public:
+ /// Obtain the underlying execution context.
+ system_context& context() const BOOST_ASIO_NOEXCEPT;
+
+ /// Inform the executor that it has some outstanding work to do.
+ /**
+ * For the system executor, this is a no-op.
+ */
+ void on_work_started() const BOOST_ASIO_NOEXCEPT
+ {
+ }
+
+ /// Inform the executor that some work is no longer outstanding.
+ /**
+ * For the system executor, this is a no-op.
+ */
+ void on_work_finished() const BOOST_ASIO_NOEXCEPT
+ {
+ }
+
+ /// Request the system executor to invoke the given function object.
+ /**
+ * This function is used to ask the executor to execute the given function
+ * object. The function object will always be executed inside this function.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ /// Request the system executor to invoke the given function object.
+ /**
+ * This function is used to ask the executor to execute the given function
+ * object. The function object will never be executed inside this function.
+ * Instead, it will be scheduled to run on an unspecified system thread pool.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void post(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ /// Request the system executor to invoke the given function object.
+ /**
+ * This function is used to ask the executor to execute the given function
+ * object. The function object will never be executed inside this function.
+ * Instead, it will be scheduled to run on an unspecified system thread pool.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void defer(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ /// Compare two executors for equality.
+ /**
+ * System executors always compare equal.
+ */
+ friend bool operator==(const system_executor&,
+ const system_executor&) BOOST_ASIO_NOEXCEPT
+ {
+ return true;
+ }
+
+ /// Compare two executors for inequality.
+ /**
+ * System executors always compare equal.
+ */
+ friend bool operator!=(const system_executor&,
+ const system_executor&) BOOST_ASIO_NOEXCEPT
+ {
+ return false;
+ }
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/impl/system_executor.hpp>
+
+#endif // BOOST_ASIO_SYSTEM_EXECUTOR_HPP
diff --git a/boost/asio/system_timer.hpp b/boost/asio/system_timer.hpp
index e95370dbbc..95c04409b5 100644
--- a/boost/asio/system_timer.hpp
+++ b/boost/asio/system_timer.hpp
@@ -17,22 +17,14 @@
#include <boost/asio/detail/config.hpp>
-#if defined(BOOST_ASIO_HAS_STD_CHRONO) \
- || defined(BOOST_ASIO_HAS_BOOST_CHRONO) \
- || defined(GENERATING_DOCUMENTATION)
-
-#if defined(BOOST_ASIO_HAS_STD_CHRONO)
-# include <chrono>
-#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
-# include <boost/chrono/system_clocks.hpp>
-#endif
+#if defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)
#include <boost/asio/basic_waitable_timer.hpp>
+#include <boost/asio/detail/chrono.hpp>
namespace boost {
namespace asio {
-#if defined(GENERATING_DOCUMENTATION)
/// Typedef for a timer based on the system clock.
/**
* This typedef uses the C++11 @c &lt;chrono&gt; standard library facility, if
@@ -43,17 +35,10 @@ namespace asio {
* @endcode
*/
typedef basic_waitable_timer<chrono::system_clock> system_timer;
-#elif defined(BOOST_ASIO_HAS_STD_CHRONO)
-typedef basic_waitable_timer<std::chrono::system_clock> system_timer;
-#elif defined(BOOST_ASIO_HAS_BOOST_CHRONO)
-typedef basic_waitable_timer<boost::chrono::system_clock> system_timer;
-#endif
} // namespace asio
} // namespace boost
-#endif // defined(BOOST_ASIO_HAS_STD_CHRONO)
- // || defined(BOOST_ASIO_HAS_BOOST_CHRONO)
- // || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)
#endif // BOOST_ASIO_SYSTEM_TIMER_HPP
diff --git a/boost/asio/thread_pool.hpp b/boost/asio/thread_pool.hpp
new file mode 100644
index 0000000000..5e3e7fd529
--- /dev/null
+++ b/boost/asio/thread_pool.hpp
@@ -0,0 +1,234 @@
+//
+// thread_pool.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_THREAD_POOL_HPP
+#define BOOST_ASIO_THREAD_POOL_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/noncopyable.hpp>
+#include <boost/asio/detail/scheduler.hpp>
+#include <boost/asio/detail/thread_group.hpp>
+#include <boost/asio/execution_context.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// A simple fixed-size thread pool.
+/**
+ * The thread pool class is an execution context where functions are permitted
+ * to run on one of a fixed number of threads.
+ *
+ * @par Submitting tasks to the pool
+ *
+ * To submit functions to the io_context, use the @ref boost::asio::dispatch,
+ * @ref boost::asio::post or @ref boost::asio::defer free functions.
+ *
+ * For example:
+ *
+ * @code void my_task()
+ * {
+ * ...
+ * }
+ *
+ * ...
+ *
+ * // Launch the pool with four threads.
+ * boost::asio::thread_pool pool(4);
+ *
+ * // Submit a function to the pool.
+ * boost::asio::post(pool, my_task);
+ *
+ * // Submit a lambda object to the pool.
+ * boost::asio::post(pool,
+ * []()
+ * {
+ * ...
+ * });
+ *
+ * // Wait for all tasks in the pool to complete.
+ * pool.join(); @endcode
+ */
+class thread_pool
+ : public execution_context
+{
+public:
+ class executor_type;
+
+ /// Constructs a pool with an automatically determined number of threads.
+ BOOST_ASIO_DECL thread_pool();
+
+ /// Constructs a pool with a specified number of threads.
+ BOOST_ASIO_DECL thread_pool(std::size_t num_threads);
+
+ /// Destructor.
+ /**
+ * Automatically stops and joins the pool, if not explicitly done beforehand.
+ */
+ BOOST_ASIO_DECL ~thread_pool();
+
+ /// Obtains the executor associated with the pool.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT;
+
+ /// Stops the threads.
+ /**
+ * This function stops the threads as soon as possible. As a result of calling
+ * @c stop(), pending function objects may be never be invoked.
+ */
+ BOOST_ASIO_DECL void stop();
+
+ /// Joins the threads.
+ /**
+ * This function blocks until the threads in the pool have completed. If @c
+ * stop() is not called prior to @c join(), the @c join() call will wait
+ * until the pool has no more outstanding work.
+ */
+ BOOST_ASIO_DECL void join();
+
+private:
+ friend class executor_type;
+ struct thread_function;
+
+ // The underlying scheduler.
+ detail::scheduler& scheduler_;
+
+ // The threads in the pool.
+ detail::thread_group threads_;
+};
+
+/// Executor used to submit functions to a thread pool.
+class thread_pool::executor_type
+{
+public:
+ /// Obtain the underlying execution context.
+ thread_pool& context() const BOOST_ASIO_NOEXCEPT;
+
+ /// Inform the thread pool that it has some outstanding work to do.
+ /**
+ * This function is used to inform the thread pool that some work has begun.
+ * This ensures that the thread pool's join() function will not return while
+ * the work is underway.
+ */
+ void on_work_started() const BOOST_ASIO_NOEXCEPT;
+
+ /// Inform the thread pool that some work is no longer outstanding.
+ /**
+ * This function is used to inform the thread pool that some work has
+ * finished. Once the count of unfinished work reaches zero, the thread
+ * pool's join() function is permitted to exit.
+ */
+ void on_work_finished() const BOOST_ASIO_NOEXCEPT;
+
+ /// Request the thread pool to invoke the given function object.
+ /**
+ * This function is used to ask the thread pool to execute the given function
+ * object. If the current thread belongs to the pool, @c dispatch() executes
+ * the function before returning. Otherwise, the function will be scheduled
+ * to run on the thread pool.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void dispatch(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ /// Request the thread pool to invoke the given function object.
+ /**
+ * This function is used to ask the thread pool to execute the given function
+ * object. The function object will never be executed inside @c post().
+ * Instead, it will be scheduled to run on the thread pool.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void post(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ /// Request the thread pool to invoke the given function object.
+ /**
+ * This function is used to ask the thread pool to execute the given function
+ * object. The function object will never be executed inside @c defer().
+ * Instead, it will be scheduled to run on the thread pool.
+ *
+ * If the current thread belongs to the thread pool, @c defer() will delay
+ * scheduling the function object until the current thread returns control to
+ * the pool.
+ *
+ * @param f The function object to be called. The executor will make
+ * a copy of the handler object as required. The function signature of the
+ * function object must be: @code void function(); @endcode
+ *
+ * @param a An allocator that may be used by the executor to allocate the
+ * internal storage needed for function invocation.
+ */
+ template <typename Function, typename Allocator>
+ void defer(BOOST_ASIO_MOVE_ARG(Function) f, const Allocator& a) const;
+
+ /// Determine whether the thread pool is running in the current thread.
+ /**
+ * @return @c true if the current thread belongs to the pool. Otherwise
+ * returns @c false.
+ */
+ bool running_in_this_thread() const BOOST_ASIO_NOEXCEPT;
+
+ /// Compare two executors for equality.
+ /**
+ * Two executors are equal if they refer to the same underlying thread pool.
+ */
+ friend bool operator==(const executor_type& a,
+ const executor_type& b) BOOST_ASIO_NOEXCEPT
+ {
+ return &a.pool_ == &b.pool_;
+ }
+
+ /// Compare two executors for inequality.
+ /**
+ * Two executors are equal if they refer to the same underlying thread pool.
+ */
+ friend bool operator!=(const executor_type& a,
+ const executor_type& b) BOOST_ASIO_NOEXCEPT
+ {
+ return &a.pool_ != &b.pool_;
+ }
+
+private:
+ friend class thread_pool;
+
+ // Constructor.
+ explicit executor_type(thread_pool& p) : pool_(p) {}
+
+ // The underlying thread pool.
+ thread_pool& pool_;
+};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#include <boost/asio/impl/thread_pool.hpp>
+#if defined(BOOST_ASIO_HEADER_ONLY)
+# include <boost/asio/impl/thread_pool.ipp>
+#endif // defined(BOOST_ASIO_HEADER_ONLY)
+
+#endif // BOOST_ASIO_THREAD_POOL_HPP
diff --git a/boost/asio/ts/buffer.hpp b/boost/asio/ts/buffer.hpp
new file mode 100644
index 0000000000..cc632102b7
--- /dev/null
+++ b/boost/asio/ts/buffer.hpp
@@ -0,0 +1,24 @@
+//
+// ts/buffer.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_TS_BUFFER_HPP
+#define BOOST_ASIO_TS_BUFFER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/completion_condition.hpp>
+#include <boost/asio/read.hpp>
+#include <boost/asio/write.hpp>
+#include <boost/asio/read_until.hpp>
+
+#endif // BOOST_ASIO_TS_BUFFER_HPP
diff --git a/boost/asio/ts/executor.hpp b/boost/asio/ts/executor.hpp
new file mode 100644
index 0000000000..ac986c0a79
--- /dev/null
+++ b/boost/asio/ts/executor.hpp
@@ -0,0 +1,35 @@
+//
+// ts/executor.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_TS_EXECUTOR_HPP
+#define BOOST_ASIO_TS_EXECUTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/handler_type.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/associated_allocator.hpp>
+#include <boost/asio/execution_context.hpp>
+#include <boost/asio/is_executor.hpp>
+#include <boost/asio/associated_executor.hpp>
+#include <boost/asio/bind_executor.hpp>
+#include <boost/asio/executor_work_guard.hpp>
+#include <boost/asio/system_executor.hpp>
+#include <boost/asio/executor.hpp>
+#include <boost/asio/dispatch.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/defer.hpp>
+#include <boost/asio/strand.hpp>
+#include <boost/asio/packaged_task.hpp>
+#include <boost/asio/use_future.hpp>
+
+#endif // BOOST_ASIO_TS_EXECUTOR_HPP
diff --git a/boost/asio/ts/internet.hpp b/boost/asio/ts/internet.hpp
new file mode 100644
index 0000000000..507f990df3
--- /dev/null
+++ b/boost/asio/ts/internet.hpp
@@ -0,0 +1,40 @@
+//
+// ts/internet.hpp
+// ~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_TS_INTERNET_HPP
+#define BOOST_ASIO_TS_INTERNET_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+#include <boost/asio/ip/address_v4_iterator.hpp>
+#include <boost/asio/ip/address_v4_range.hpp>
+#include <boost/asio/ip/address_v6.hpp>
+#include <boost/asio/ip/address_v6_iterator.hpp>
+#include <boost/asio/ip/address_v6_range.hpp>
+#include <boost/asio/ip/bad_address_cast.hpp>
+#include <boost/asio/ip/basic_endpoint.hpp>
+#include <boost/asio/ip/basic_resolver_query.hpp>
+#include <boost/asio/ip/basic_resolver_entry.hpp>
+#include <boost/asio/ip/basic_resolver_iterator.hpp>
+#include <boost/asio/ip/basic_resolver.hpp>
+#include <boost/asio/ip/host_name.hpp>
+#include <boost/asio/ip/network_v4.hpp>
+#include <boost/asio/ip/network_v6.hpp>
+#include <boost/asio/ip/tcp.hpp>
+#include <boost/asio/ip/udp.hpp>
+#include <boost/asio/ip/v6_only.hpp>
+#include <boost/asio/ip/unicast.hpp>
+#include <boost/asio/ip/multicast.hpp>
+
+#endif // BOOST_ASIO_TS_INTERNET_HPP
diff --git a/boost/asio/ts/io_context.hpp b/boost/asio/ts/io_context.hpp
new file mode 100644
index 0000000000..d5e88607c2
--- /dev/null
+++ b/boost/asio/ts/io_context.hpp
@@ -0,0 +1,20 @@
+//
+// ts/io_context.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_TS_IO_CONTEXT_HPP
+#define BOOST_ASIO_TS_IO_CONTEXT_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/io_context.hpp>
+
+#endif // BOOST_ASIO_TS_IO_CONTEXT_HPP
diff --git a/boost/asio/ts/net.hpp b/boost/asio/ts/net.hpp
new file mode 100644
index 0000000000..0f60da2ee2
--- /dev/null
+++ b/boost/asio/ts/net.hpp
@@ -0,0 +1,26 @@
+//
+// ts/net.hpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_TS_NET_HPP
+#define BOOST_ASIO_TS_NET_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/ts/netfwd.hpp>
+#include <boost/asio/ts/executor.hpp>
+#include <boost/asio/ts/io_context.hpp>
+#include <boost/asio/ts/timer.hpp>
+#include <boost/asio/ts/buffer.hpp>
+#include <boost/asio/ts/socket.hpp>
+#include <boost/asio/ts/internet.hpp>
+
+#endif // BOOST_ASIO_TS_NET_HPP
diff --git a/boost/asio/ts/netfwd.hpp b/boost/asio/ts/netfwd.hpp
new file mode 100644
index 0000000000..0b084d7e60
--- /dev/null
+++ b/boost/asio/ts/netfwd.hpp
@@ -0,0 +1,199 @@
+//
+// ts/netfwd.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_TS_NETFWD_HPP
+#define BOOST_ASIO_TS_NETFWD_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_CHRONO)
+# include <boost/asio/detail/chrono.hpp>
+#endif // defined(BOOST_ASIO_HAS_CHRONO)
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+# include <boost/asio/detail/date_time_fwd.hpp>
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+class execution_context;
+
+template <typename T, typename Executor>
+class executor_binder;
+
+template <typename Executor>
+class executor_work_guard;
+
+class system_executor;
+
+class executor;
+
+template <typename Executor>
+class strand;
+
+class io_context;
+
+template <typename Clock>
+struct wait_traits;
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+template <typename Time>
+struct time_traits;
+
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+template <typename Clock, typename WaitTraits>
+class waitable_timer_service;
+
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+template <typename TimeType, typename TimeTraits>
+class deadline_timer_service;
+
+#endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
+
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#if !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
+#define BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL
+
+template <typename Clock,
+ typename WaitTraits = boost::asio::wait_traits<Clock>
+ BOOST_ASIO_SVC_TPARAM_DEF2(= waitable_timer_service<Clock, WaitTraits>)>
+class basic_waitable_timer;
+
+#endif // !defined(BOOST_ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)
+
+#if defined(BOOST_ASIO_HAS_CHRONO)
+
+typedef basic_waitable_timer<chrono::system_clock> system_timer;
+
+typedef basic_waitable_timer<chrono::steady_clock> steady_timer;
+
+typedef basic_waitable_timer<chrono::high_resolution_clock>
+ high_resolution_timer;
+
+#endif // defined(BOOST_ASIO_HAS_CHRONO)
+
+template <class Protocol BOOST_ASIO_SVC_TPARAM>
+class basic_socket;
+
+template <typename Protocol BOOST_ASIO_SVC_TPARAM>
+class basic_datagram_socket;
+
+template <typename Protocol BOOST_ASIO_SVC_TPARAM>
+class basic_stream_socket;
+
+template <typename Protocol BOOST_ASIO_SVC_TPARAM>
+class basic_socket_acceptor;
+
+#if !defined(BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)
+#define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL
+
+// Forward declaration with defaulted arguments.
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>),
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
+ || defined(GENERATING_DOCUMENTATION)
+ typename Clock = boost::posix_time::ptime,
+ typename WaitTraits = time_traits<Clock>
+ BOOST_ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)>
+#else
+ typename Clock = chrono::steady_clock,
+ typename WaitTraits = wait_traits<Clock>
+ BOOST_ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)>
+#endif
+class basic_socket_streambuf;
+
+#endif // !defined(BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)
+
+#if !defined(BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
+#define BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL
+
+// Forward declaration with defaulted arguments.
+template <typename Protocol
+ BOOST_ASIO_SVC_TPARAM_DEF1(= stream_socket_service<Protocol>),
+#if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
+ || defined(GENERATING_DOCUMENTATION)
+ typename Clock = boost::posix_time::ptime,
+ typename WaitTraits = time_traits<Clock>
+ BOOST_ASIO_SVC_TPARAM1_DEF2(= deadline_timer_service<Clock, WaitTraits>)>
+#else
+ typename Clock = chrono::steady_clock,
+ typename WaitTraits = wait_traits<Clock>
+ BOOST_ASIO_SVC_TPARAM1_DEF1(= steady_timer::service_type)>
+#endif
+class basic_socket_iostream;
+
+#endif // !defined(BOOST_ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)
+
+namespace ip {
+
+class address;
+
+class address_v4;
+
+class address_v6;
+
+template <typename Address>
+class basic_address_iterator;
+
+typedef basic_address_iterator<address_v4> address_v4_iterator;
+
+typedef basic_address_iterator<address_v6> address_v6_iterator;
+
+template <typename Address>
+class basic_address_range;
+
+typedef basic_address_range<address_v4> address_v4_range;
+
+typedef basic_address_range<address_v6> address_v6_range;
+
+class network_v4;
+
+class network_v6;
+
+template <typename InternetProtocol>
+class basic_endpoint;
+
+template <typename InternetProtocol>
+class basic_resolver_entry;
+
+template <typename InternetProtocol>
+class basic_resolver_results;
+
+template <typename InternetProtocol BOOST_ASIO_SVC_TPARAM>
+class basic_resolver;
+
+class tcp;
+
+class udp;
+
+} // namespace ip
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+#endif // BOOST_ASIO_TS_NETFWD_HPP
diff --git a/boost/asio/ts/socket.hpp b/boost/asio/ts/socket.hpp
new file mode 100644
index 0000000000..538bf3c303
--- /dev/null
+++ b/boost/asio/ts/socket.hpp
@@ -0,0 +1,27 @@
+//
+// ts/socket.hpp
+// ~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_TS_SOCKET_HPP
+#define BOOST_ASIO_TS_SOCKET_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/socket_base.hpp>
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/basic_datagram_socket.hpp>
+#include <boost/asio/basic_stream_socket.hpp>
+#include <boost/asio/basic_socket_acceptor.hpp>
+#include <boost/asio/basic_socket_streambuf.hpp>
+#include <boost/asio/basic_socket_iostream.hpp>
+#include <boost/asio/connect.hpp>
+
+#endif // BOOST_ASIO_TS_SOCKET_HPP
diff --git a/boost/asio/ts/timer.hpp b/boost/asio/ts/timer.hpp
new file mode 100644
index 0000000000..a9482838d6
--- /dev/null
+++ b/boost/asio/ts/timer.hpp
@@ -0,0 +1,26 @@
+//
+// ts/timer.hpp
+// ~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_TS_TIMER_HPP
+#define BOOST_ASIO_TS_TIMER_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/chrono.hpp>
+
+#include <boost/asio/wait_traits.hpp>
+#include <boost/asio/basic_waitable_timer.hpp>
+#include <boost/asio/system_timer.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/asio/high_resolution_timer.hpp>
+
+#endif // BOOST_ASIO_TS_TIMER_HPP
diff --git a/boost/asio/use_future.hpp b/boost/asio/use_future.hpp
index e4ce7f7975..4ad61ba0cd 100644
--- a/boost/asio/use_future.hpp
+++ b/boost/asio/use_future.hpp
@@ -16,12 +16,26 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_HAS_STD_FUTURE) \
+ || defined(GENERATING_DOCUMENTATION)
+
#include <memory>
+#include <boost/asio/detail/type_traits.hpp>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
+namespace detail {
+
+template <typename Function, typename Allocator>
+class packaged_token;
+
+template <typename Function, typename Allocator, typename Result>
+class packaged_handler;
+
+} // namespace detail
/// Class used to specify that an asynchronous operation should return a future.
/**
@@ -57,12 +71,21 @@ public:
{
}
- /// Specify an alternate allocator.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use rebind().) Specify an alternate allocator.
template <typename OtherAllocator>
use_future_t<OtherAllocator> operator[](const OtherAllocator& allocator) const
{
return use_future_t<OtherAllocator>(allocator);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Specify an alternate allocator.
+ template <typename OtherAllocator>
+ use_future_t<OtherAllocator> rebind(const OtherAllocator& allocator) const
+ {
+ return use_future_t<OtherAllocator>(allocator);
+ }
/// Obtain allocator.
allocator_type get_allocator() const
@@ -70,18 +93,59 @@ public:
return allocator_;
}
+ /// Wrap a function object in a packaged task.
+ /**
+ * The @c package function is used to adapt a function object as a packaged
+ * task. When this adapter is passed as a completion token to an asynchronous
+ * operation, the result of the function object is retuned via a std::future.
+ *
+ * @par Example
+ *
+ * @code std::future<std::size_t> fut =
+ * my_socket.async_read_some(buffer,
+ * use_future([](boost::system::error_code ec, std::size_t n)
+ * {
+ * return ec ? 0 : n;
+ * }));
+ * ...
+ * std::size_t n = fut.get(); @endcode
+ */
+ template <typename Function>
+#if defined(GENERATING_DOCUMENTATION)
+ unspecified
+#else // defined(GENERATING_DOCUMENTATION)
+ detail::packaged_token<typename decay<Function>::type, Allocator>
+#endif // defined(GENERATING_DOCUMENTATION)
+ operator()(BOOST_ASIO_MOVE_ARG(Function) f) const;
+
private:
- Allocator allocator_;
+ // Helper type to ensure that use_future can be constexpr default-constructed
+ // even when std::allocator<void> can't be.
+ struct std_allocator_void
+ {
+ BOOST_ASIO_CONSTEXPR std_allocator_void()
+ {
+ }
+
+ operator std::allocator<void>() const
+ {
+ return std::allocator<void>();
+ }
+ };
+
+ typename conditional<
+ is_same<std::allocator<void>, Allocator>::value,
+ std_allocator_void, Allocator>::type allocator_;
};
/// A special value, similar to std::nothrow.
/**
* See the documentation for boost::asio::use_future_t for a usage example.
*/
-#if defined(BOOST_ASIO_MSVC)
-__declspec(selectany) use_future_t<> use_future;
-#elif defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
+#if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
constexpr use_future_t<> use_future;
+#elif defined(BOOST_ASIO_MSVC)
+__declspec(selectany) use_future_t<> use_future;
#endif
} // namespace asio
@@ -91,4 +155,7 @@ constexpr use_future_t<> use_future;
#include <boost/asio/impl/use_future.hpp>
+#endif // defined(BOOST_ASIO_HAS_STD_FUTURE)
+ // || defined(GENERATING_DOCUMENTATION)
+
#endif // BOOST_ASIO_USE_FUTURE_HPP
diff --git a/boost/asio/uses_executor.hpp b/boost/asio/uses_executor.hpp
new file mode 100644
index 0000000000..0951a86a2d
--- /dev/null
+++ b/boost/asio/uses_executor.hpp
@@ -0,0 +1,73 @@
+//
+// uses_executor.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_USES_EXECUTOR_HPP
+#define BOOST_ASIO_USES_EXECUTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+#include <boost/asio/detail/type_traits.hpp>
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+
+/// A special type, similar to std::nothrow_t, used to disambiguate
+/// constructors that accept executor arguments.
+/**
+ * The executor_arg_t struct is an empty structure type used as a unique type
+ * to disambiguate constructor and function overloading. Specifically, some
+ * types have constructors with executor_arg_t as the first argument,
+ * immediately followed by an argument of a type that satisfies the Executor
+ * type requirements.
+ */
+struct executor_arg_t
+{
+ /// Constructor.
+ BOOST_ASIO_CONSTEXPR executor_arg_t() BOOST_ASIO_NOEXCEPT
+ {
+ }
+};
+
+/// A special value, similar to std::nothrow, used to disambiguate constructors
+/// that accept executor arguments.
+/**
+ * See boost::asio::executor_arg_t and boost::asio::uses_executor
+ * for more information.
+ */
+#if defined(BOOST_ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
+constexpr executor_arg_t executor_arg;
+#elif defined(BOOST_ASIO_MSVC)
+__declspec(selectany) executor_arg_t executor_arg;
+#endif
+
+/// The uses_executor trait detects whether a type T has an associated executor
+/// that is convertible from type Executor.
+/**
+ * Meets the BinaryTypeTrait requirements. The Asio library provides a
+ * definition that is derived from false_type. A program may specialize this
+ * template to derive from true_type for a user-defined type T that can be
+ * constructed with an executor, where the first argument of a constructor has
+ * type executor_arg_t and the second argument is convertible from type
+ * Executor.
+ */
+template <typename T, typename Executor>
+struct uses_executor : false_type {};
+
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#endif // BOOST_ASIO_USES_EXECUTOR_HPP
diff --git a/boost/asio/version.hpp b/boost/asio/version.hpp
index 76b6440b01..5b78f0fad8 100644
--- a/boost/asio/version.hpp
+++ b/boost/asio/version.hpp
@@ -18,6 +18,6 @@
// BOOST_ASIO_VERSION % 100 is the sub-minor version
// BOOST_ASIO_VERSION / 100 % 1000 is the minor version
// BOOST_ASIO_VERSION / 100000 is the major version
-#define BOOST_ASIO_VERSION 101010 // 1.10.10
+#define BOOST_ASIO_VERSION 101200 // 1.12.0
#endif // BOOST_ASIO_VERSION_HPP
diff --git a/boost/asio/wait_traits.hpp b/boost/asio/wait_traits.hpp
index f1a3c18243..76b8593c34 100644
--- a/boost/asio/wait_traits.hpp
+++ b/boost/asio/wait_traits.hpp
@@ -25,7 +25,7 @@ template <typename Clock>
struct wait_traits
{
/// Convert a clock duration into a duration used for waiting.
- /**
+ /**
* @returns @c d.
*/
static typename Clock::duration to_wait_duration(
@@ -33,6 +33,21 @@ struct wait_traits
{
return d;
}
+
+ /// Convert a clock duration into a duration used for waiting.
+ /**
+ * @returns @c d.
+ */
+ static typename Clock::duration to_wait_duration(
+ const typename Clock::time_point& t)
+ {
+ typename Clock::time_point now = Clock::now();
+ if (now + (Clock::duration::max)() < t)
+ return (Clock::duration::max)();
+ if (now + (Clock::duration::min)() > t)
+ return (Clock::duration::min)();
+ return t - now;
+ }
};
} // namespace asio
diff --git a/boost/asio/waitable_timer_service.hpp b/boost/asio/waitable_timer_service.hpp
index 139d124ec5..882c6be66a 100644
--- a/boost/asio/waitable_timer_service.hpp
+++ b/boost/asio/waitable_timer_service.hpp
@@ -16,11 +16,14 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#include <cstddef>
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/chrono_time_traits.hpp>
#include <boost/asio/detail/deadline_timer_service.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/wait_traits.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -33,7 +36,7 @@ template <typename Clock,
typename WaitTraits = boost::asio::wait_traits<Clock> >
class waitable_timer_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<
waitable_timer_service<Clock, WaitTraits> >
@@ -42,7 +45,7 @@ class waitable_timer_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
/// The clock type.
@@ -70,11 +73,11 @@ public:
typedef typename service_impl_type::implementation_type implementation_type;
#endif
- /// Construct a new timer service for the specified io_service.
- explicit waitable_timer_service(boost::asio::io_service& io_service)
+ /// Construct a new timer service for the specified io_context.
+ explicit waitable_timer_service(boost::asio::io_context& io_context)
: boost::asio::detail::service_base<
- waitable_timer_service<Clock, WaitTraits> >(io_service),
- service_impl_(io_service)
+ waitable_timer_service<Clock, WaitTraits> >(io_context),
+ service_impl_(io_context)
{
}
@@ -90,6 +93,23 @@ public:
service_impl_.destroy(impl);
}
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a new timer implementation.
+ void move_construct(implementation_type& impl,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_construct(impl, other_impl);
+ }
+
+ /// Move-assign from another timer implementation.
+ void move_assign(implementation_type& impl,
+ waitable_timer_service& other_service,
+ implementation_type& other_impl)
+ {
+ service_impl_.move_assign(impl, other_service.service_impl_, other_impl);
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
/// Cancel any asynchronous wait operations associated with the timer.
std::size_t cancel(implementation_type& impl, boost::system::error_code& ec)
{
@@ -103,10 +123,19 @@ public:
return service_impl_.cancel_one(impl, ec);
}
- /// Get the expiry time for the timer as an absolute time.
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use expiry().) Get the expiry time for the timer as an
+ /// absolute time.
time_point expires_at(const implementation_type& impl) const
{
- return service_impl_.expires_at(impl);
+ return service_impl_.expiry(impl);
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the expiry time for the timer as an absolute time.
+ time_point expiry(const implementation_type& impl) const
+ {
+ return service_impl_.expiry(impl);
}
/// Set the expiry time for the timer as an absolute time.
@@ -116,18 +145,30 @@ public:
return service_impl_.expires_at(impl, expiry_time, ec);
}
- /// Get the expiry time for the timer relative to now.
+ /// Set the expiry time for the timer relative to now.
+ std::size_t expires_after(implementation_type& impl,
+ const duration& expiry_time, boost::system::error_code& ec)
+ {
+ return service_impl_.expires_after(impl, expiry_time, ec);
+ }
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use expiry().) Get the expiry time for the timer relative to
+ /// now.
duration expires_from_now(const implementation_type& impl) const
{
- return service_impl_.expires_from_now(impl);
+ typedef detail::chrono_time_traits<Clock, WaitTraits> traits;
+ return traits::subtract(service_impl_.expiry(impl), traits::now());
}
- /// Set the expiry time for the timer relative to now.
+ /// (Deprecated: Use expires_after().) Set the expiry time for the timer
+ /// relative to now.
std::size_t expires_from_now(implementation_type& impl,
const duration& expiry_time, boost::system::error_code& ec)
{
- return service_impl_.expires_from_now(impl, expiry_time, ec);
+ return service_impl_.expires_after(impl, expiry_time, ec);
}
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
// Perform a blocking wait on the timer.
void wait(implementation_type& impl, boost::system::error_code& ec)
@@ -142,20 +183,19 @@ public:
async_wait(implementation_type& impl,
BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
{
- detail::async_result_init<
- WaitHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
+ async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
- service_impl_.async_wait(impl, init.handler);
+ service_impl_.async_wait(impl, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -167,4 +207,6 @@ private:
#include <boost/asio/detail/pop_options.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_WAITABLE_TIMER_SERVICE_HPP
diff --git a/boost/asio/windows/basic_handle.hpp b/boost/asio/windows/basic_handle.hpp
index 6f903fd454..d0eda784e5 100644
--- a/boost/asio/windows/basic_handle.hpp
+++ b/boost/asio/windows/basic_handle.hpp
@@ -17,6 +17,8 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
|| defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
|| defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \
@@ -46,10 +48,6 @@ class basic_handle
: public basic_io_object<HandleService>
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// handle.
- typedef typename HandleService::native_handle_type native_type;
-
/// The native representation of a handle.
typedef typename HandleService::native_handle_type native_handle_type;
@@ -60,11 +58,11 @@ public:
/**
* This constructor creates a handle without opening it.
*
- * @param io_service The io_service object that the handle will use to
+ * @param io_context The io_context object that the handle will use to
* dispatch handlers for any asynchronous operations performed on the handle.
*/
- explicit basic_handle(boost::asio::io_service& io_service)
- : basic_io_object<HandleService>(io_service)
+ explicit basic_handle(boost::asio::io_context& io_context)
+ : basic_io_object<HandleService>(io_context)
{
}
@@ -72,16 +70,16 @@ public:
/**
* This constructor creates a handle object to hold an existing native handle.
*
- * @param io_service The io_service object that the handle will use to
+ * @param io_context The io_context object that the handle will use to
* dispatch handlers for any asynchronous operations performed on the handle.
*
* @param handle A native handle.
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_handle(boost::asio::io_service& io_service,
+ basic_handle(boost::asio::io_context& io_context,
const native_handle_type& handle)
- : basic_io_object<HandleService>(io_service)
+ : basic_io_object<HandleService>(io_context)
{
boost::system::error_code ec;
this->get_service().assign(this->get_implementation(), handle, ec);
@@ -96,7 +94,7 @@ public:
* @param other The other basic_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_handle(io_service&) constructor.
+ * constructed using the @c basic_handle(io_context&) constructor.
*/
basic_handle(basic_handle&& other)
: basic_io_object<HandleService>(
@@ -111,7 +109,7 @@ public:
* @param other The other basic_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_handle(io_service&) constructor.
+ * constructed using the @c basic_handle(io_context&) constructor.
*/
basic_handle& operator=(basic_handle&& other)
{
@@ -172,10 +170,11 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code assign(const native_handle_type& handle,
+ BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,
boost::system::error_code& ec)
{
- return this->get_service().assign(this->get_implementation(), handle, ec);
+ this->get_service().assign(this->get_implementation(), handle, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the handle is open.
@@ -207,20 +206,10 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code close(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
{
- return this->get_service().close(this->get_implementation(), ec);
- }
-
- /// (Deprecated: Use native_handle().) Get the native handle representation.
- /**
- * This function may be used to obtain the underlying representation of the
- * handle. This is intended to allow access to native handle functionality
- * that is not otherwise provided.
- */
- native_type native()
- {
- return this->get_service().native_handle(this->get_implementation());
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the native handle representation.
@@ -257,9 +246,10 @@ public:
*
* @param ec Set to indicate what error occurred, if any.
*/
- boost::system::error_code cancel(boost::system::error_code& ec)
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
{
- return this->get_service().cancel(this->get_implementation(), ec);
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
protected:
@@ -280,4 +270,6 @@ protected:
// || defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_WINDOWS_BASIC_HANDLE_HPP
diff --git a/boost/asio/windows/basic_object_handle.hpp b/boost/asio/windows/basic_object_handle.hpp
index c82c2a7039..0f2f278592 100644
--- a/boost/asio/windows/basic_object_handle.hpp
+++ b/boost/asio/windows/basic_object_handle.hpp
@@ -18,6 +18,8 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \
|| defined(GENERATING_DOCUMENTATION)
@@ -53,11 +55,11 @@ public:
/**
* This constructor creates an object handle without opening it.
*
- * @param io_service The io_service object that the object handle will use to
+ * @param io_context The io_context object that the object handle will use to
* dispatch handlers for any asynchronous operations performed on the handle.
*/
- explicit basic_object_handle(boost::asio::io_service& io_service)
- : basic_handle<ObjectHandleService>(io_service)
+ explicit basic_object_handle(boost::asio::io_context& io_context)
+ : basic_handle<ObjectHandleService>(io_context)
{
}
@@ -66,16 +68,16 @@ public:
* This constructor creates an object handle object to hold an existing native
* handle.
*
- * @param io_service The io_service object that the object handle will use to
+ * @param io_context The io_context object that the object handle will use to
* dispatch handlers for any asynchronous operations performed on the handle.
*
* @param native_handle The new underlying handle implementation.
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_object_handle(boost::asio::io_service& io_service,
+ basic_object_handle(boost::asio::io_context& io_context,
const native_handle_type& native_handle)
- : basic_handle<ObjectHandleService>(io_service, native_handle)
+ : basic_handle<ObjectHandleService>(io_context, native_handle)
{
}
@@ -88,7 +90,7 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_object_handle(io_service&) constructor.
+ * constructed using the @c basic_object_handle(io_context&) constructor.
*/
basic_object_handle(basic_object_handle&& other)
: basic_handle<ObjectHandleService>(
@@ -104,7 +106,7 @@ public:
* occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_object_handle(io_service&) constructor.
+ * constructed using the @c basic_object_handle(io_context&) constructor.
*/
basic_object_handle& operator=(basic_object_handle&& other)
{
@@ -156,7 +158,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename WaitHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
@@ -177,4 +179,6 @@ public:
#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
diff --git a/boost/asio/windows/basic_random_access_handle.hpp b/boost/asio/windows/basic_random_access_handle.hpp
index 0d4184fb64..ae071896f8 100644
--- a/boost/asio/windows/basic_random_access_handle.hpp
+++ b/boost/asio/windows/basic_random_access_handle.hpp
@@ -17,6 +17,8 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
|| defined(GENERATING_DOCUMENTATION)
@@ -47,10 +49,6 @@ class basic_random_access_handle
: public basic_handle<RandomAccessHandleService>
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// handle.
- typedef typename RandomAccessHandleService::native_handle_type native_type;
-
/// The native representation of a handle.
typedef typename RandomAccessHandleService::native_handle_type
native_handle_type;
@@ -60,12 +58,12 @@ public:
* This constructor creates a random-access handle without opening it. The
* handle needs to be opened before data can be written to or read from it.
*
- * @param io_service The io_service object that the random-access handle will
+ * @param io_context The io_context object that the random-access handle will
* use to dispatch handlers for any asynchronous operations performed on the
* handle.
*/
- explicit basic_random_access_handle(boost::asio::io_service& io_service)
- : basic_handle<RandomAccessHandleService>(io_service)
+ explicit basic_random_access_handle(boost::asio::io_context& io_context)
+ : basic_handle<RandomAccessHandleService>(io_context)
{
}
@@ -74,7 +72,7 @@ public:
* This constructor creates a random-access handle object to hold an existing
* native handle.
*
- * @param io_service The io_service object that the random-access handle will
+ * @param io_context The io_context object that the random-access handle will
* use to dispatch handlers for any asynchronous operations performed on the
* handle.
*
@@ -82,9 +80,9 @@ public:
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_random_access_handle(boost::asio::io_service& io_service,
+ basic_random_access_handle(boost::asio::io_context& io_context,
const native_handle_type& handle)
- : basic_handle<RandomAccessHandleService>(io_service, handle)
+ : basic_handle<RandomAccessHandleService>(io_context, handle)
{
}
@@ -97,7 +95,7 @@ public:
* 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(io_service&)
+ * constructed using the @c basic_random_access_handle(io_context&)
* constructor.
*/
basic_random_access_handle(basic_random_access_handle&& other)
@@ -115,7 +113,7 @@ public:
* 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(io_service&)
+ * constructed using the @c basic_random_access_handle(io_context&)
* constructor.
*/
basic_random_access_handle& operator=(basic_random_access_handle&& other)
@@ -214,7 +212,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -334,7 +332,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -375,4 +373,6 @@ public:
#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP
diff --git a/boost/asio/windows/basic_stream_handle.hpp b/boost/asio/windows/basic_stream_handle.hpp
index 1b954fffbd..2270847670 100644
--- a/boost/asio/windows/basic_stream_handle.hpp
+++ b/boost/asio/windows/basic_stream_handle.hpp
@@ -17,6 +17,8 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
|| defined(GENERATING_DOCUMENTATION)
@@ -50,10 +52,6 @@ class basic_stream_handle
: public basic_handle<StreamHandleService>
{
public:
- /// (Deprecated: Use native_handle_type.) The native representation of a
- /// handle.
- typedef typename StreamHandleService::native_handle_type native_type;
-
/// The native representation of a handle.
typedef typename StreamHandleService::native_handle_type native_handle_type;
@@ -63,11 +61,11 @@ public:
* needs to be opened and then connected or accepted before data can be sent
* or received on it.
*
- * @param io_service The io_service object that the stream handle will use to
+ * @param io_context The io_context object that the stream handle will use to
* dispatch handlers for any asynchronous operations performed on the handle.
*/
- explicit basic_stream_handle(boost::asio::io_service& io_service)
- : basic_handle<StreamHandleService>(io_service)
+ explicit basic_stream_handle(boost::asio::io_context& io_context)
+ : basic_handle<StreamHandleService>(io_context)
{
}
@@ -76,16 +74,16 @@ public:
* This constructor creates a stream handle object to hold an existing native
* handle.
*
- * @param io_service The io_service object that the stream handle will use to
+ * @param io_context The io_context object that the stream handle will use to
* dispatch handlers for any asynchronous operations performed on the handle.
*
* @param handle The new underlying handle implementation.
*
* @throws boost::system::system_error Thrown on failure.
*/
- basic_stream_handle(boost::asio::io_service& io_service,
+ basic_stream_handle(boost::asio::io_context& io_context,
const native_handle_type& handle)
- : basic_handle<StreamHandleService>(io_service, handle)
+ : basic_handle<StreamHandleService>(io_context, handle)
{
}
@@ -98,7 +96,7 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_stream_handle(io_service&) constructor.
+ * constructed using the @c basic_stream_handle(io_context&) constructor.
*/
basic_stream_handle(basic_stream_handle&& other)
: basic_handle<StreamHandleService>(
@@ -115,7 +113,7 @@ public:
* will occur.
*
* @note Following the move, the moved-from object is in the same state as if
- * constructed using the @c basic_stream_handle(io_service&) constructor.
+ * constructed using the @c basic_stream_handle(io_context&) constructor.
*/
basic_stream_handle& operator=(basic_stream_handle&& other)
{
@@ -206,7 +204,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -318,7 +316,7 @@ public:
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation
* of the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @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
@@ -358,4 +356,6 @@ public:
#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
diff --git a/boost/asio/windows/object_handle.hpp b/boost/asio/windows/object_handle.hpp
index 614cc6bf3e..33b252d495 100644
--- a/boost/asio/windows/object_handle.hpp
+++ b/boost/asio/windows/object_handle.hpp
@@ -21,19 +21,362 @@
#if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \
|| defined(GENERATING_DOCUMENTATION)
-#include <boost/asio/windows/basic_object_handle.hpp>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/win_object_handle_service.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/windows/basic_object_handle.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#define BOOST_ASIO_SVC_T boost::asio::detail::win_object_handle_service
+
+#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace windows {
-/// Typedef for the typical usage of an object handle.
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+// Typedef for the typical usage of an object handle.
typedef basic_object_handle<> object_handle;
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+/// Provides object-oriented handle functionality.
+/**
+ * The windows::object_handle class provides asynchronous and blocking
+ * object-oriented handle functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+class object_handle
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
+
+ /// The native representation of a handle.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef BOOST_ASIO_SVC_T::native_handle_type native_handle_type;
+#endif
+
+ /// An object_handle is always the lowest layer.
+ typedef object_handle lowest_layer_type;
+
+ /// Construct an object_handle without opening it.
+ /**
+ * This constructor creates an object handle without opening it.
+ *
+ * @param io_context The io_context object that the object handle will use to
+ * dispatch handlers for any asynchronous operations performed on the handle.
+ */
+ explicit object_handle(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ }
+
+ /// Construct an object_handle on an existing native handle.
+ /**
+ * This constructor creates an object handle object to hold an existing native
+ * handle.
+ *
+ * @param io_context The io_context object that the object handle will use to
+ * dispatch handlers for any asynchronous operations performed on the handle.
+ *
+ * @param native_handle The new underlying handle implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ object_handle(boost::asio::io_context& io_context,
+ const native_handle_type& native_handle)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(), native_handle, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct an object_handle from another.
+ /**
+ * 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 object_handle(io_context&) constructor.
+ */
+ object_handle(object_handle&& other)
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
+ {
+ }
+
+ /// Move-assign an object_handle from another.
+ /**
+ * 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 object_handle(io_context&) constructor.
+ */
+ object_handle& operator=(object_handle&& other)
+ {
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
+ }
+
+ /// Get a reference to the lowest layer.
+ /**
+ * This function returns a reference to the lowest layer in a stack of
+ * layers. Since an object_handle 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 an object_handle 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 handle to the handle.
+ /*
+ * This function opens the handle to hold an existing native handle.
+ *
+ * @param handle A native handle.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const native_handle_type& handle)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(), handle, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Assign an existing native handle to the handle.
+ /*
+ * This function opens the handle to hold an existing native handle.
+ *
+ * @param handle A native handle.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,
+ boost::system::error_code& ec)
+ {
+ this->get_service().assign(this->get_implementation(), handle, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the handle is open.
+ bool is_open() const
+ {
+ return this->get_service().is_open(this->get_implementation());
+ }
+
+ /// Close the handle.
+ /**
+ * This function is used to close the handle. Any asynchronous read or write
+ * operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->get_service().close(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "close");
+ }
+
+ /// Close the handle.
+ /**
+ * This function is used to close the handle. Any asynchronous read or write
+ * operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
+ {
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get the native handle representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * handle. This is intended to allow access to native handle functionality
+ * that is not otherwise provided.
+ */
+ native_handle_type native_handle()
+ {
+ return this->get_service().native_handle(this->get_implementation());
+ }
+
+ /// Cancel all asynchronous operations associated with the handle.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->get_service().cancel(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all asynchronous operations associated with the handle.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
+ {
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Perform a blocking wait on the object handle.
+ /**
+ * This function is used to wait for the object handle to be set to the
+ * signalled state. This function blocks and does not return until the object
+ * handle has been set to the signalled state.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void wait()
+ {
+ boost::system::error_code ec;
+ this->get_service().wait(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "wait");
+ }
+
+ /// Perform a blocking wait on the object handle.
+ /**
+ * This function is used to wait for the object handle to be set to the
+ * signalled state. This function blocks and does not return until the object
+ * handle has been set to the signalled state.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ void wait(boost::system::error_code& ec)
+ {
+ this->get_service().wait(this->get_implementation(), ec);
+ }
+
+ /// 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ */
+ template <typename WaitHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WaitHandler,
+ void (boost::system::error_code))
+ async_wait(BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
+ {
+ boost::asio::async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
+
+ this->get_service().async_wait(this->get_implementation(),
+ init.completion_handler);
+
+ return init.result.get();
+ }
+};
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
} // namespace windows
} // namespace asio
} // namespace boost
+#include <boost/asio/detail/pop_options.hpp>
+
+#undef BOOST_ASIO_SVC_T
+
#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
diff --git a/boost/asio/windows/object_handle_service.hpp b/boost/asio/windows/object_handle_service.hpp
index 26ef6ed507..6932d43c2b 100644
--- a/boost/asio/windows/object_handle_service.hpp
+++ b/boost/asio/windows/object_handle_service.hpp
@@ -18,13 +18,15 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE) \
|| defined(GENERATING_DOCUMENTATION)
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/win_object_handle_service.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -35,7 +37,7 @@ namespace windows {
/// Default service implementation for an object handle.
class object_handle_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<object_handle_service>
#endif
@@ -43,7 +45,7 @@ class object_handle_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
private:
@@ -65,10 +67,10 @@ public:
typedef service_impl_type::native_handle_type native_handle_type;
#endif
- /// Construct a new object handle service for the specified io_service.
- explicit object_handle_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<object_handle_service>(io_service),
- service_impl_(io_service)
+ /// Construct a new object handle service for the specified io_context.
+ explicit object_handle_service(boost::asio::io_context& io_context)
+ : boost::asio::detail::service_base<object_handle_service>(io_context),
+ service_impl_(io_context)
{
}
@@ -102,10 +104,11 @@ public:
}
/// Assign an existing native handle to an object handle.
- boost::system::error_code assign(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl,
const native_handle_type& handle, boost::system::error_code& ec)
{
- return service_impl_.assign(impl, handle, ec);
+ service_impl_.assign(impl, handle, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the handle is open.
@@ -115,10 +118,11 @@ public:
}
/// Close an object handle implementation.
- boost::system::error_code close(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.close(impl, ec);
+ service_impl_.close(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the native handle implementation.
@@ -128,10 +132,11 @@ public:
}
/// Cancel all asynchronous operations associated with the handle.
- boost::system::error_code cancel(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.cancel(impl, ec);
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
// Wait for a signaled state.
@@ -147,20 +152,19 @@ public:
async_wait(implementation_type& impl,
BOOST_ASIO_MOVE_ARG(WaitHandler) handler)
{
- boost::asio::detail::async_result_init<
- WaitHandler, void (boost::system::error_code)> init(
- BOOST_ASIO_MOVE_CAST(WaitHandler)(handler));
+ boost::asio::async_completion<WaitHandler,
+ void (boost::system::error_code)> init(handler);
- service_impl_.async_wait(impl, init.handler);
+ service_impl_.async_wait(impl, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -176,4 +180,6 @@ private:
#endif // defined(BOOST_ASIO_HAS_WINDOWS_OBJECT_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_WINDOWS_OBJECT_HANDLE_SERVICE_HPP
diff --git a/boost/asio/windows/overlapped_handle.hpp b/boost/asio/windows/overlapped_handle.hpp
new file mode 100644
index 0000000000..a21e11e965
--- /dev/null
+++ b/boost/asio/windows/overlapped_handle.hpp
@@ -0,0 +1,333 @@
+//
+// windows/overlapped_handle.hpp
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the 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 BOOST_ASIO_WINDOWS_OVERLAPPED_HANDLE_HPP
+#define BOOST_ASIO_WINDOWS_OVERLAPPED_HANDLE_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include <boost/asio/detail/config.hpp>
+
+#if !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
+ || defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
+ || defined(GENERATING_DOCUMENTATION)
+
+#include <cstddef>
+#include <boost/asio/async_result.hpp>
+#include <boost/asio/basic_io_object.hpp>
+#include <boost/asio/detail/throw_error.hpp>
+#include <boost/asio/detail/win_iocp_handle_service.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+
+#if defined(BOOST_ASIO_HAS_MOVE)
+# include <utility>
+#endif // defined(BOOST_ASIO_HAS_MOVE)
+
+#define BOOST_ASIO_SVC_T boost::asio::detail::win_iocp_handle_service
+
+#include <boost/asio/detail/push_options.hpp>
+
+namespace boost {
+namespace asio {
+namespace windows {
+
+/// Provides Windows handle functionality for objects that support
+/// overlapped I/O.
+/**
+ * The windows::overlapped_handle class provides the ability to wrap a Windows
+ * handle. The underlying object referred to by the handle must support
+ * overlapped I/O.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+class overlapped_handle
+ : BOOST_ASIO_SVC_ACCESS basic_io_object<BOOST_ASIO_SVC_T>
+{
+public:
+ /// The type of the executor associated with the object.
+ typedef io_context::executor_type executor_type;
+
+ /// The native representation of a handle.
+#if defined(GENERATING_DOCUMENTATION)
+ typedef implementation_defined native_handle_type;
+#else
+ typedef BOOST_ASIO_SVC_T::native_handle_type native_handle_type;
+#endif
+
+ /// An overlapped_handle is always the lowest layer.
+ typedef overlapped_handle lowest_layer_type;
+
+ /// Construct an overlapped_handle without opening it.
+ /**
+ * This constructor creates a handle without opening it.
+ *
+ * @param io_context The io_context object that the handle will use to
+ * dispatch handlers for any asynchronous operations performed on the handle.
+ */
+ explicit overlapped_handle(boost::asio::io_context& io_context)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ }
+
+ /// Construct an overlapped_handle on an existing native handle.
+ /**
+ * This constructor creates a handle object to hold an existing native handle.
+ *
+ * @param io_context The io_context object that the handle will use to
+ * dispatch handlers for any asynchronous operations performed on the handle.
+ *
+ * @param handle A native handle.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ overlapped_handle(boost::asio::io_context& io_context,
+ const native_handle_type& handle)
+ : basic_io_object<BOOST_ASIO_SVC_T>(io_context)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(), handle, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct an overlapped_handle from another.
+ /**
+ * 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(io_context&) constructor.
+ */
+ overlapped_handle(overlapped_handle&& other)
+ : basic_io_object<BOOST_ASIO_SVC_T>(std::move(other))
+ {
+ }
+
+ /// Move-assign an overlapped_handle from another.
+ /**
+ * 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(io_context&) constructor.
+ */
+ overlapped_handle& operator=(overlapped_handle&& other)
+ {
+ basic_io_object<BOOST_ASIO_SVC_T>::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+#if !defined(BOOST_ASIO_NO_DEPRECATED)
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_context()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_context();
+ }
+
+ /// (Deprecated: Use get_executor().) Get the io_context associated with the
+ /// object.
+ /**
+ * This function may be used to obtain the io_context object that the I/O
+ * object uses to dispatch handlers for asynchronous operations.
+ *
+ * @return A reference to the io_context object that the I/O object will use
+ * to dispatch handlers. Ownership is not transferred to the caller.
+ */
+ boost::asio::io_context& get_io_service()
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_io_service();
+ }
+#endif // !defined(BOOST_ASIO_NO_DEPRECATED)
+
+ /// Get the executor associated with the object.
+ executor_type get_executor() BOOST_ASIO_NOEXCEPT
+ {
+ return basic_io_object<BOOST_ASIO_SVC_T>::get_executor();
+ }
+
+ /// Get a reference to the lowest layer.
+ /**
+ * This function returns a reference to the lowest layer in a stack of
+ * layers. Since an overlapped_handle 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 an overlapped_handle 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 handle to the handle.
+ /*
+ * This function opens the handle to hold an existing native handle.
+ *
+ * @param handle A native handle.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void assign(const native_handle_type& handle)
+ {
+ boost::system::error_code ec;
+ this->get_service().assign(this->get_implementation(), handle, ec);
+ boost::asio::detail::throw_error(ec, "assign");
+ }
+
+ /// Assign an existing native handle to the handle.
+ /*
+ * This function opens the handle to hold an existing native handle.
+ *
+ * @param handle A native handle.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,
+ boost::system::error_code& ec)
+ {
+ this->get_service().assign(this->get_implementation(), handle, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Determine whether the handle is open.
+ bool is_open() const
+ {
+ return this->get_service().is_open(this->get_implementation());
+ }
+
+ /// Close the handle.
+ /**
+ * This function is used to close the handle. Any asynchronous read or write
+ * operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void close()
+ {
+ boost::system::error_code ec;
+ this->get_service().close(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "close");
+ }
+
+ /// Close the handle.
+ /**
+ * This function is used to close the handle. Any asynchronous read or write
+ * operations will be cancelled immediately, and will complete with the
+ * boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID close(boost::system::error_code& ec)
+ {
+ this->get_service().close(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+ /// Get the native handle representation.
+ /**
+ * This function may be used to obtain the underlying representation of the
+ * handle. This is intended to allow access to native handle functionality
+ * that is not otherwise provided.
+ */
+ native_handle_type native_handle()
+ {
+ return this->get_service().native_handle(this->get_implementation());
+ }
+
+ /// Cancel all asynchronous operations associated with the handle.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ void cancel()
+ {
+ boost::system::error_code ec;
+ this->get_service().cancel(this->get_implementation(), ec);
+ boost::asio::detail::throw_error(ec, "cancel");
+ }
+
+ /// Cancel all asynchronous operations associated with the handle.
+ /**
+ * This function causes all outstanding asynchronous read or write operations
+ * to finish immediately, and the handlers for cancelled operations will be
+ * passed the boost::asio::error::operation_aborted error.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ */
+ BOOST_ASIO_SYNC_OP_VOID cancel(boost::system::error_code& ec)
+ {
+ this->get_service().cancel(this->get_implementation(), ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
+ }
+
+protected:
+ /// Protected destructor to prevent deletion through this type.
+ /**
+ * This function destroys the handle, cancelling any outstanding asynchronous
+ * wait operations associated with the handle as if by calling @c cancel.
+ */
+ ~overlapped_handle()
+ {
+ }
+};
+
+} // namespace windows
+} // namespace asio
+} // namespace boost
+
+#include <boost/asio/detail/pop_options.hpp>
+
+#undef BOOST_ASIO_SVC_T
+
+#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
+ // || defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
+ // || defined(GENERATING_DOCUMENTATION)
+
+#endif // !defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#endif // BOOST_ASIO_WINDOWS_OVERLAPPED_HANDLE_HPP
diff --git a/boost/asio/windows/overlapped_ptr.hpp b/boost/asio/windows/overlapped_ptr.hpp
index fa9fb3d200..5c6ce3a541 100644
--- a/boost/asio/windows/overlapped_ptr.hpp
+++ b/boost/asio/windows/overlapped_ptr.hpp
@@ -22,7 +22,7 @@
#include <boost/asio/detail/noncopyable.hpp>
#include <boost/asio/detail/win_iocp_overlapped_ptr.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -51,9 +51,9 @@ public:
/// Construct an overlapped_ptr to contain the specified handler.
template <typename Handler>
- explicit overlapped_ptr(boost::asio::io_service& io_service,
+ explicit overlapped_ptr(boost::asio::io_context& io_context,
BOOST_ASIO_MOVE_ARG(Handler) handler)
- : impl_(io_service, BOOST_ASIO_MOVE_CAST(Handler)(handler))
+ : impl_(io_context, BOOST_ASIO_MOVE_CAST(Handler)(handler))
{
}
@@ -71,10 +71,10 @@ public:
/// Reset to contain the specified handler, freeing any current OVERLAPPED
/// object.
template <typename Handler>
- void reset(boost::asio::io_service& io_service,
+ void reset(boost::asio::io_context& io_context,
BOOST_ASIO_MOVE_ARG(Handler) handler)
{
- impl_.reset(io_service, BOOST_ASIO_MOVE_CAST(Handler)(handler));
+ impl_.reset(io_context, BOOST_ASIO_MOVE_CAST(Handler)(handler));
}
/// Get the contained OVERLAPPED object.
diff --git a/boost/asio/windows/random_access_handle.hpp b/boost/asio/windows/random_access_handle.hpp
index 993e193278..76d2bd7010 100644
--- a/boost/asio/windows/random_access_handle.hpp
+++ b/boost/asio/windows/random_access_handle.hpp
@@ -16,23 +16,364 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+#include <boost/asio/windows/overlapped_handle.hpp>
#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
|| defined(GENERATING_DOCUMENTATION)
-#include <boost/asio/windows/basic_random_access_handle.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/windows/basic_random_access_handle.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace windows {
-/// Typedef for the typical usage of a random-access handle.
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+// Typedef for the typical usage of a random-access handle.
typedef basic_random_access_handle<> random_access_handle;
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+/// Provides random-access handle functionality.
+/**
+ * The windows::random_access_handle class provides asynchronous and
+ * blocking random-access handle functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ */
+class random_access_handle
+ : public overlapped_handle
+{
+public:
+ /// Construct a random_access_handle without opening it.
+ /**
+ * This constructor creates a random-access handle without opening it. The
+ * handle needs to be opened before data can be written to or read from it.
+ *
+ * @param io_context The io_context object that the random-access handle will
+ * use to dispatch handlers for any asynchronous operations performed on the
+ * handle.
+ */
+ explicit random_access_handle(boost::asio::io_context& io_context)
+ : overlapped_handle(io_context)
+ {
+ }
+
+ /// Construct a random_access_handle on an existing native handle.
+ /**
+ * This constructor creates a random-access handle object to hold an existing
+ * native handle.
+ *
+ * @param io_context The io_context object that the random-access handle will
+ * use to dispatch handlers for any asynchronous operations performed on the
+ * handle.
+ *
+ * @param handle The new underlying handle implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ random_access_handle(boost::asio::io_context& io_context,
+ const native_handle_type& handle)
+ : overlapped_handle(io_context, handle)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a random_access_handle from another.
+ /**
+ * 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 random_access_handle(io_context&)
+ * constructor.
+ */
+ random_access_handle(random_access_handle&& other)
+ : overlapped_handle(std::move(other))
+ {
+ }
+
+ /// Move-assign a random_access_handle from another.
+ /**
+ * 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 random_access_handle(io_context&)
+ * constructor.
+ */
+ random_access_handle& operator=(random_access_handle&& other)
+ {
+ overlapped_handle::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// 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 boost::system::system_error Thrown on failure. An error code of
+ * boost::asio::error::eof indicates that the connection was closed by the
+ * peer.
+ *
+ * @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, boost::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)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().write_some_at(
+ this->get_implementation(), offset, buffers, ec);
+ boost::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 transmit all of the data to the
+ * peer. 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, boost::system::error_code& ec)
+ {
+ return this->get_service().write_some_at(
+ this->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. The function call 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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 handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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.
+ *
+ * @par Example
+ * To write a single data buffer use the @ref buffer function as follows:
+ * @code
+ * handle.async_write_some_at(42, boost::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, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_write_some_at(uint64_t offset,
+ const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ boost::asio::async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_write_some_at(this->get_implementation(),
+ offset, buffers, init.completion_handler);
+
+ return init.result.get();
+ }
+
+ /// 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 boost::system::system_error Thrown on failure. An error code of
+ * boost::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_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, boost::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)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().read_some_at(
+ this->get_implementation(), offset, buffers, ec);
+ boost::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, boost::system::error_code& ec)
+ {
+ return this->get_service().read_some_at(
+ this->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. The function call 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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 handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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, boost::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, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+ async_read_some_at(uint64_t offset,
+ const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ boost::asio::async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_read_some_at(this->get_implementation(),
+ offset, buffers, init.completion_handler);
+
+ return init.result.get();
+ }
+};
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
} // namespace windows
} // namespace asio
} // namespace boost
+#include <boost/asio/detail/pop_options.hpp>
+
#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
diff --git a/boost/asio/windows/random_access_handle_service.hpp b/boost/asio/windows/random_access_handle_service.hpp
index 15a808f69a..a49a3955bd 100644
--- a/boost/asio/windows/random_access_handle_service.hpp
+++ b/boost/asio/windows/random_access_handle_service.hpp
@@ -17,6 +17,8 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \
|| defined(GENERATING_DOCUMENTATION)
@@ -25,7 +27,7 @@
#include <boost/asio/detail/cstdint.hpp>
#include <boost/asio/detail/win_iocp_handle_service.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -36,7 +38,7 @@ namespace windows {
/// Default service implementation for a random-access handle.
class random_access_handle_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<random_access_handle_service>
#endif
@@ -44,7 +46,7 @@ class random_access_handle_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
private:
@@ -59,13 +61,6 @@ public:
typedef service_impl_type::implementation_type implementation_type;
#endif
- /// (Deprecated: Use native_handle_type.) The native handle type.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined native_type;
-#else
- typedef service_impl_type::native_handle_type native_type;
-#endif
-
/// The native handle type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
@@ -73,11 +68,11 @@ public:
typedef service_impl_type::native_handle_type native_handle_type;
#endif
- /// Construct a new random-access handle service for the specified io_service.
- explicit random_access_handle_service(boost::asio::io_service& io_service)
+ /// Construct a new random-access handle service for the specified io_context.
+ explicit random_access_handle_service(boost::asio::io_context& io_context)
: boost::asio::detail::service_base<
- random_access_handle_service>(io_service),
- service_impl_(io_service)
+ random_access_handle_service>(io_context),
+ service_impl_(io_context)
{
}
@@ -111,10 +106,11 @@ public:
}
/// Assign an existing native handle to a random-access handle.
- boost::system::error_code assign(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl,
const native_handle_type& handle, boost::system::error_code& ec)
{
- return service_impl_.assign(impl, handle, ec);
+ service_impl_.assign(impl, handle, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the handle is open.
@@ -124,16 +120,11 @@ public:
}
/// Close a random-access handle implementation.
- boost::system::error_code close(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.close(impl, ec);
- }
-
- /// (Deprecated: Use native_handle().) Get the native handle implementation.
- native_type native(implementation_type& impl)
- {
- return service_impl_.native_handle(impl);
+ service_impl_.close(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the native handle implementation.
@@ -143,10 +134,11 @@ public:
}
/// Cancel all asynchronous operations associated with the handle.
- boost::system::error_code cancel(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.cancel(impl, ec);
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Write the given data at the specified offset.
@@ -165,11 +157,11 @@ public:
uint64_t offset, const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- boost::asio::detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ boost::asio::async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_write_some_at(impl, offset, buffers, init.handler);
+ service_impl_.async_write_some_at(impl,
+ offset, buffers, init.completion_handler);
return init.result.get();
}
@@ -190,20 +182,20 @@ public:
uint64_t offset, const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- boost::asio::detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ boost::asio::async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_read_some_at(impl, offset, buffers, init.handler);
+ service_impl_.async_read_some_at(impl,
+ offset, buffers, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -219,4 +211,6 @@ private:
#endif // defined(BOOST_ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_SERVICE_HPP
diff --git a/boost/asio/windows/stream_handle.hpp b/boost/asio/windows/stream_handle.hpp
index e52b8a16a6..1c7646a266 100644
--- a/boost/asio/windows/stream_handle.hpp
+++ b/boost/asio/windows/stream_handle.hpp
@@ -16,23 +16,348 @@
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/detail/config.hpp>
+#include <boost/asio/windows/overlapped_handle.hpp>
#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
|| defined(GENERATING_DOCUMENTATION)
-#include <boost/asio/windows/basic_stream_handle.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+# include <boost/asio/windows/basic_stream_handle.hpp>
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
+#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
namespace windows {
-/// Typedef for the typical usage of a stream-oriented handle.
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+// Typedef for the typical usage of a stream-oriented handle.
typedef basic_stream_handle<> stream_handle;
+#else // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+/// Provides stream-oriented handle functionality.
+/**
+ * The windows::stream_handle class provides asynchronous and blocking
+ * stream-oriented handle functionality.
+ *
+ * @par Thread Safety
+ * @e Distinct @e objects: Safe.@n
+ * @e Shared @e objects: Unsafe.
+ *
+ * @par Concepts:
+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
+ */
+class stream_handle
+ : public overlapped_handle
+{
+public:
+ /// Construct a stream_handle without opening it.
+ /**
+ * This constructor creates a stream handle without opening it. The handle
+ * needs to be opened and then connected or accepted before data can be sent
+ * or received on it.
+ *
+ * @param io_context The io_context object that the stream handle will use to
+ * dispatch handlers for any asynchronous operations performed on the handle.
+ */
+ explicit stream_handle(boost::asio::io_context& io_context)
+ : overlapped_handle(io_context)
+ {
+ }
+
+ /// Construct a stream_handle on an existing native handle.
+ /**
+ * This constructor creates a stream handle object to hold an existing native
+ * handle.
+ *
+ * @param io_context The io_context object that the stream handle will use to
+ * dispatch handlers for any asynchronous operations performed on the handle.
+ *
+ * @param handle The new underlying handle implementation.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+ stream_handle(boost::asio::io_context& io_context,
+ const native_handle_type& handle)
+ : overlapped_handle(io_context, handle)
+ {
+ }
+
+#if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+ /// Move-construct a stream_handle from another.
+ /**
+ * 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 stream_handle(io_context&) constructor.
+ */
+ stream_handle(stream_handle&& other)
+ : overlapped_handle(std::move(other))
+ {
+ }
+
+ /// Move-assign a stream_handle from another.
+ /**
+ * 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 stream_handle(io_context&) constructor.
+ */
+ stream_handle& operator=(stream_handle&& other)
+ {
+ overlapped_handle::operator=(std::move(other));
+ return *this;
+ }
+#endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+ /// Write some data to the handle.
+ /**
+ * This function is used to write data to the stream handle. 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 handle.
+ *
+ * @returns The number of bytes written.
+ *
+ * @throws boost::system::system_error Thrown on failure. An error code of
+ * boost::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
+ * handle.write_some(boost::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)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().write_some(
+ this->get_implementation(), buffers, ec);
+ boost::asio::detail::throw_error(ec, "write_some");
+ return s;
+ }
+
+ /// Write some data to the handle.
+ /**
+ * This function is used to write data to the stream handle. 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 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 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,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().write_some(
+ this->get_implementation(), buffers, ec);
+ }
+
+ /// Start an asynchronous write.
+ /**
+ * This function is used to asynchronously write data to the stream handle.
+ * The function call 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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 handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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
+ * handle.async_write_some(boost::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, typename WriteHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+ async_write_some(const ConstBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a WriteHandler.
+ BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+ boost::asio::async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_write_some(
+ this->get_implementation(), buffers, init.completion_handler);
+
+ return init.result.get();
+ }
+
+ /// Read some data from the handle.
+ /**
+ * This function is used to read data from the stream handle. 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 boost::system::system_error Thrown on failure. An error code of
+ * boost::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
+ * handle.read_some(boost::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)
+ {
+ boost::system::error_code ec;
+ std::size_t s = this->get_service().read_some(
+ this->get_implementation(), buffers, ec);
+ boost::asio::detail::throw_error(ec, "read_some");
+ return s;
+ }
+
+ /// Read some data from the handle.
+ /**
+ * This function is used to read data from the stream handle. 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,
+ boost::system::error_code& ec)
+ {
+ return this->get_service().read_some(
+ this->get_implementation(), buffers, ec);
+ }
+
+ /// Start an asynchronous read.
+ /**
+ * This function is used to asynchronously read data from the stream handle.
+ * The function call 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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::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 handler will not be invoked from within this function. Invocation
+ * of the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ *
+ * @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
+ * handle.async_read_some(boost::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, typename ReadHandler>
+ BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler,
+ void (boost::system::error_code, std::size_t))
+ async_read_some(const MutableBufferSequence& buffers,
+ BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
+ {
+ // If you get an error on the following line it means that your handler does
+ // not meet the documented type requirements for a ReadHandler.
+ BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+
+ boost::asio::async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
+
+ this->get_service().async_read_some(
+ this->get_implementation(), buffers, init.completion_handler);
+
+ return init.result.get();
+ }
+};
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
} // namespace windows
} // namespace asio
} // namespace boost
+#include <boost/asio/detail/pop_options.hpp>
+
#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
diff --git a/boost/asio/windows/stream_handle_service.hpp b/boost/asio/windows/stream_handle_service.hpp
index 5adcfaed1b..438954723c 100644
--- a/boost/asio/windows/stream_handle_service.hpp
+++ b/boost/asio/windows/stream_handle_service.hpp
@@ -17,6 +17,8 @@
#include <boost/asio/detail/config.hpp>
+#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#if defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE) \
|| defined(GENERATING_DOCUMENTATION)
@@ -24,7 +26,7 @@
#include <boost/asio/async_result.hpp>
#include <boost/asio/detail/win_iocp_handle_service.hpp>
#include <boost/asio/error.hpp>
-#include <boost/asio/io_service.hpp>
+#include <boost/asio/io_context.hpp>
#include <boost/asio/detail/push_options.hpp>
@@ -35,7 +37,7 @@ namespace windows {
/// Default service implementation for a stream handle.
class stream_handle_service
#if defined(GENERATING_DOCUMENTATION)
- : public boost::asio::io_service::service
+ : public boost::asio::io_context::service
#else
: public boost::asio::detail::service_base<stream_handle_service>
#endif
@@ -43,7 +45,7 @@ class stream_handle_service
public:
#if defined(GENERATING_DOCUMENTATION)
/// The unique service identifier.
- static boost::asio::io_service::id id;
+ static boost::asio::io_context::id id;
#endif
private:
@@ -58,13 +60,6 @@ public:
typedef service_impl_type::implementation_type implementation_type;
#endif
- /// (Deprecated: Use native_handle_type.) The native handle type.
-#if defined(GENERATING_DOCUMENTATION)
- typedef implementation_defined native_type;
-#else
- typedef service_impl_type::native_handle_type native_type;
-#endif
-
/// The native handle type.
#if defined(GENERATING_DOCUMENTATION)
typedef implementation_defined native_handle_type;
@@ -72,10 +67,10 @@ public:
typedef service_impl_type::native_handle_type native_handle_type;
#endif
- /// Construct a new stream handle service for the specified io_service.
- explicit stream_handle_service(boost::asio::io_service& io_service)
- : boost::asio::detail::service_base<stream_handle_service>(io_service),
- service_impl_(io_service)
+ /// Construct a new stream handle service for the specified io_context.
+ explicit stream_handle_service(boost::asio::io_context& io_context)
+ : boost::asio::detail::service_base<stream_handle_service>(io_context),
+ service_impl_(io_context)
{
}
@@ -109,10 +104,11 @@ public:
}
/// Assign an existing native handle to a stream handle.
- boost::system::error_code assign(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID assign(implementation_type& impl,
const native_handle_type& handle, boost::system::error_code& ec)
{
- return service_impl_.assign(impl, handle, ec);
+ service_impl_.assign(impl, handle, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Determine whether the handle is open.
@@ -122,16 +118,11 @@ public:
}
/// Close a stream handle implementation.
- boost::system::error_code close(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID close(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.close(impl, ec);
- }
-
- /// (Deprecated: Use native_handle().) Get the native handle implementation.
- native_type native(implementation_type& impl)
- {
- return service_impl_.native_handle(impl);
+ service_impl_.close(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Get the native handle implementation.
@@ -141,10 +132,11 @@ public:
}
/// Cancel all asynchronous operations associated with the handle.
- boost::system::error_code cancel(implementation_type& impl,
+ BOOST_ASIO_SYNC_OP_VOID cancel(implementation_type& impl,
boost::system::error_code& ec)
{
- return service_impl_.cancel(impl, ec);
+ service_impl_.cancel(impl, ec);
+ BOOST_ASIO_SYNC_OP_VOID_RETURN(ec);
}
/// Write the given data to the stream.
@@ -163,11 +155,10 @@ public:
const ConstBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
{
- boost::asio::detail::async_result_init<
- WriteHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(WriteHandler)(handler));
+ boost::asio::async_completion<WriteHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_write_some(impl, buffers, init.handler);
+ service_impl_.async_write_some(impl, buffers, init.completion_handler);
return init.result.get();
}
@@ -188,20 +179,19 @@ public:
const MutableBufferSequence& buffers,
BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
{
- boost::asio::detail::async_result_init<
- ReadHandler, void (boost::system::error_code, std::size_t)> init(
- BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
+ boost::asio::async_completion<ReadHandler,
+ void (boost::system::error_code, std::size_t)> init(handler);
- service_impl_.async_read_some(impl, buffers, init.handler);
+ service_impl_.async_read_some(impl, buffers, init.completion_handler);
return init.result.get();
}
private:
// Destroy all user-defined handler objects owned by the service.
- void shutdown_service()
+ void shutdown()
{
- service_impl_.shutdown_service();
+ service_impl_.shutdown();
}
// The platform-specific implementation.
@@ -217,4 +207,6 @@ private:
#endif // defined(BOOST_ASIO_HAS_WINDOWS_STREAM_HANDLE)
// || defined(GENERATING_DOCUMENTATION)
+#endif // defined(BOOST_ASIO_ENABLE_OLD_SERVICES)
+
#endif // BOOST_ASIO_WINDOWS_STREAM_HANDLE_SERVICE_HPP
diff --git a/boost/asio/write.hpp b/boost/asio/write.hpp
index b70e6f5bf5..87187c3d06 100644
--- a/boost/asio/write.hpp
+++ b/boost/asio/write.hpp
@@ -18,9 +18,13 @@
#include <boost/asio/detail/config.hpp>
#include <cstddef>
#include <boost/asio/async_result.hpp>
-#include <boost/asio/basic_streambuf_fwd.hpp>
+#include <boost/asio/buffer.hpp>
#include <boost/asio/error.hpp>
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+# include <boost/asio/basic_streambuf_fwd.hpp>
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
@@ -70,7 +74,10 @@ namespace asio {
* boost::asio::transfer_all()); @endcode
*/
template <typename SyncWriteStream, typename ConstBufferSequence>
-std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers);
+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type* = 0);
/// Write all of the supplied data to a stream before returning.
/**
@@ -110,7 +117,10 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers);
*/
template <typename SyncWriteStream, typename ConstBufferSequence>
std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
- boost::system::error_code& ec);
+ boost::system::error_code& ec,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type* = 0);
/// Write a certain amount of data to a stream before returning.
/**
@@ -161,7 +171,10 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
template <typename SyncWriteStream, typename ConstBufferSequence,
typename CompletionCondition>
std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
- CompletionCondition completion_condition);
+ CompletionCondition completion_condition,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type* = 0);
/// Write a certain amount of data to a stream before returning.
/**
@@ -205,8 +218,172 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
template <typename SyncWriteStream, typename ConstBufferSequence,
typename CompletionCondition>
std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
- CompletionCondition completion_condition, boost::system::error_code& ec);
+ CompletionCondition completion_condition, boost::system::error_code& ec,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type* = 0);
+
+/// Write all of the supplied data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param buffers The dynamic buffer sequence from which data will be written.
+ * Successfully written data is automatically consumed from the buffers.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::write(
+ * s, buffers,
+ * boost::asio::transfer_all()); @endcode
+ */
+template <typename SyncWriteStream, typename DynamicBuffer>
+std::size_t write(SyncWriteStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+
+/// Write all of the supplied data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param buffers The dynamic buffer sequence from which data will be written.
+ * Successfully written data is automatically consumed from the buffers.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @note This overload is equivalent to calling:
+ * @code boost::asio::write(
+ * s, buffers,
+ * boost::asio::transfer_all(), ec); @endcode
+ */
+template <typename SyncWriteStream, typename DynamicBuffer>
+std::size_t write(SyncWriteStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+
+/// Write a certain amount of data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param buffers The dynamic buffer sequence from which data will be written.
+ * 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
+ * must be:
+ * @code std::size_t completion_condition(
+ * // Result of latest write_some operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the write operation is complete. A
+ * non-zero return value indicates the maximum number of bytes to be written on
+ * the next call to the stream's write_some function.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws boost::system::system_error Thrown on failure.
+ */
+template <typename SyncWriteStream, typename DynamicBuffer,
+ typename CompletionCondition>
+std::size_t write(SyncWriteStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ CompletionCondition completion_condition,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+
+/// Write a certain amount of data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param buffers The dynamic buffer sequence from which data will be written.
+ * 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
+ * must be:
+ * @code std::size_t completion_condition(
+ * // Result of latest write_some operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the write operation is complete. A
+ * non-zero return value indicates the maximum number of bytes to be written on
+ * the next call to the stream's write_some function.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncWriteStream, typename DynamicBuffer,
+ typename CompletionCondition>
+std::size_t write(SyncWriteStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ CompletionCondition completion_condition, boost::system::error_code& ec,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// Write all of the supplied data to a stream before returning.
@@ -350,6 +527,7 @@ std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b,
CompletionCondition completion_condition, boost::system::error_code& ec);
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
/*@}*/
/**
@@ -401,7 +579,7 @@ std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
@@ -417,7 +595,10 @@ template <typename AsyncWriteStream, typename ConstBufferSequence,
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (boost::system::error_code, std::size_t))
async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler);
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type* = 0);
/// Start an asynchronous operation to write a certain amount of data to a
/// stream.
@@ -474,7 +655,7 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
@@ -492,8 +673,135 @@ BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
void (boost::system::error_code, std::size_t))
async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
CompletionCondition completion_condition,
- BOOST_ASIO_MOVE_ARG(WriteHandler) handler);
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ typename enable_if<
+ is_const_buffer_sequence<ConstBufferSequence>::value
+ >::type* = 0);
+
+/// Start an asynchronous operation to write all of the supplied 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:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_write_some function, and is known as a <em>composed operation</em>. The
+ * program must ensure that the stream performs no other write operations (such
+ * as async_write, the stream's async_write_some function, or any other composed
+ * operations that perform writes) until this operation completes.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the AsyncWriteStream concept.
+ *
+ * @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.
+ *
+ * @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:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * 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.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ */
+template <typename AsyncWriteStream,
+ typename DynamicBuffer, typename WriteHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+async_write(AsyncWriteStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+
+/// 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:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_write_some function, and is known as a <em>composed operation</em>. The
+ * program must ensure that the stream performs no other write operations (such
+ * as async_write, the stream's async_write_some function, or any other composed
+ * operations that perform writes) until this operation completes.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the AsyncWriteStream concept.
+ *
+ * @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.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code std::size_t completion_condition(
+ * // Result of latest async_write_some operation.
+ * const boost::system::error_code& error,
+ *
+ * // Number of bytes transferred so far.
+ * std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the write operation is complete. A
+ * 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:
+ * @code void handler(
+ * const boost::system::error_code& error, // Result of operation.
+ *
+ * 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.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * boost::asio::io_context::post().
+ */
+template <typename AsyncWriteStream, typename DynamicBuffer,
+ typename CompletionCondition, typename WriteHandler>
+BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
+ void (boost::system::error_code, std::size_t))
+async_write(AsyncWriteStream& s,
+ BOOST_ASIO_MOVE_ARG(DynamicBuffer) buffers,
+ CompletionCondition completion_condition,
+ BOOST_ASIO_MOVE_ARG(WriteHandler) handler,
+ typename enable_if<
+ is_dynamic_buffer<DynamicBuffer>::value
+ >::type* = 0);
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// Start an asynchronous operation to write all of the supplied data to a
@@ -535,7 +843,7 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler,
@@ -596,7 +904,7 @@ async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename AsyncWriteStream, typename Allocator,
typename CompletionCondition, typename WriteHandler>
@@ -607,6 +915,7 @@ async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler);
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
/*@}*/
diff --git a/boost/asio/write_at.hpp b/boost/asio/write_at.hpp
index 266fc5bcaf..91eb52ef34 100644
--- a/boost/asio/write_at.hpp
+++ b/boost/asio/write_at.hpp
@@ -18,10 +18,13 @@
#include <boost/asio/detail/config.hpp>
#include <cstddef>
#include <boost/asio/async_result.hpp>
-#include <boost/asio/basic_streambuf_fwd.hpp>
#include <boost/asio/detail/cstdint.hpp>
#include <boost/asio/error.hpp>
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
+# include <boost/asio/basic_streambuf_fwd.hpp>
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
+
#include <boost/asio/detail/push_options.hpp>
namespace boost {
@@ -225,6 +228,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d,
uint64_t offset, const ConstBufferSequence& buffers,
CompletionCondition completion_condition, boost::system::error_code& ec);
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// Write all of the supplied data at the specified offset before returning.
@@ -383,6 +387,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, uint64_t offset,
boost::system::error_code& ec);
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
/*@}*/
/**
@@ -438,7 +443,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, uint64_t offset,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
@@ -516,7 +521,7 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*
* @par Example
* To write a single data buffer use the @ref buffer function as follows:
@@ -537,6 +542,7 @@ async_write_at(AsyncRandomAccessWriteDevice& d,
CompletionCondition completion_condition,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler);
+#if !defined(BOOST_ASIO_NO_EXTENSIONS)
#if !defined(BOOST_ASIO_NO_IOSTREAM)
/// Start an asynchronous operation to write all of the supplied data at the
@@ -582,7 +588,7 @@ async_write_at(AsyncRandomAccessWriteDevice& d,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename AsyncRandomAccessWriteDevice, typename Allocator,
typename WriteHandler>
@@ -648,7 +654,7 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset,
* Regardless of whether the asynchronous operation completes immediately or
* not, the handler will not be invoked from within this function. Invocation of
* the handler will be performed in a manner equivalent to using
- * boost::asio::io_service::post().
+ * boost::asio::io_context::post().
*/
template <typename AsyncRandomAccessWriteDevice, typename Allocator,
typename CompletionCondition, typename WriteHandler>
@@ -659,6 +665,7 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset,
BOOST_ASIO_MOVE_ARG(WriteHandler) handler);
#endif // !defined(BOOST_ASIO_NO_IOSTREAM)
+#endif // !defined(BOOST_ASIO_NO_EXTENSIONS)
/*@}*/