diff options
Diffstat (limited to '3rdparty/asio/include')
685 files changed, 46462 insertions, 34136 deletions
diff --git a/3rdparty/asio/include/Makefile.am b/3rdparty/asio/include/Makefile.am index 74933ee7d35..8f43766563e 100644 --- a/3rdparty/asio/include/Makefile.am +++ b/3rdparty/asio/include/Makefile.am @@ -1,16 +1,24 @@ # find . -name "*.*pp" | sed -e 's/^\.\///' | sed -e 's/^.*$/ & \\/' | sort nobase_include_HEADERS = \ + asio/any_completion_executor.hpp \ + asio/any_completion_handler.hpp \ asio/any_io_executor.hpp \ + asio/append.hpp \ + asio/as_tuple.hpp \ asio/associated_allocator.hpp \ asio/associated_cancellation_slot.hpp \ asio/associated_executor.hpp \ + asio/associated_immediate_executor.hpp \ asio/associator.hpp \ asio/async_result.hpp \ asio/awaitable.hpp \ asio/basic_datagram_socket.hpp \ asio/basic_deadline_timer.hpp \ + asio/basic_file.hpp \ asio/basic_io_object.hpp \ + asio/basic_random_access_file.hpp \ asio/basic_raw_socket.hpp \ + asio/basic_readable_pipe.hpp \ asio/basic_seq_packet_socket.hpp \ asio/basic_serial_port.hpp \ asio/basic_signal_set.hpp \ @@ -20,10 +28,14 @@ nobase_include_HEADERS = \ asio/basic_socket_streambuf.hpp \ asio/basic_streambuf_fwd.hpp \ asio/basic_streambuf.hpp \ + asio/basic_stream_file.hpp \ asio/basic_stream_socket.hpp \ asio/basic_waitable_timer.hpp \ + asio/basic_writable_pipe.hpp \ + asio/bind_allocator.hpp \ asio/bind_cancellation_slot.hpp \ asio/bind_executor.hpp \ + asio/bind_immediate_executor.hpp \ asio/buffered_read_stream_fwd.hpp \ asio/buffered_read_stream.hpp \ asio/buffered_stream_fwd.hpp \ @@ -31,6 +43,7 @@ nobase_include_HEADERS = \ asio/buffered_write_stream_fwd.hpp \ asio/buffered_write_stream.hpp \ asio/buffer.hpp \ + asio/buffer_registration.hpp \ asio/buffers_iterator.hpp \ asio/cancellation_signal.hpp \ asio/cancellation_state.hpp \ @@ -39,9 +52,12 @@ nobase_include_HEADERS = \ asio/completion_condition.hpp \ asio/compose.hpp \ asio/connect.hpp \ + asio/connect_pipe.hpp \ + asio/consign.hpp \ asio/coroutine.hpp \ asio/deadline_timer.hpp \ asio/defer.hpp \ + asio/deferred.hpp \ asio/detached.hpp \ asio/detail/array_fwd.hpp \ asio/detail/array.hpp \ @@ -54,11 +70,11 @@ nobase_include_HEADERS = \ asio/detail/buffered_stream_storage.hpp \ asio/detail/buffer_resize_guard.hpp \ asio/detail/buffer_sequence_adapter.hpp \ - asio/detail/bulk_executor_op.hpp \ asio/detail/call_stack.hpp \ asio/detail/chrono.hpp \ asio/detail/chrono_time_traits.hpp \ asio/detail/completion_handler.hpp \ + asio/detail/composed_work.hpp \ asio/detail/concurrency_hint.hpp \ asio/detail/conditionally_enabled_event.hpp \ asio/detail/conditionally_enabled_mutex.hpp \ @@ -76,20 +92,16 @@ nobase_include_HEADERS = \ asio/detail/epoll_reactor.hpp \ asio/detail/eventfd_select_interrupter.hpp \ asio/detail/event.hpp \ + asio/detail/exception.hpp \ asio/detail/executor_function.hpp \ asio/detail/executor_op.hpp \ asio/detail/fd_set_adapter.hpp \ asio/detail/fenced_block.hpp \ asio/detail/functional.hpp \ asio/detail/future.hpp \ - asio/detail/gcc_arm_fenced_block.hpp \ - asio/detail/gcc_hppa_fenced_block.hpp \ - asio/detail/gcc_sync_fenced_block.hpp \ - asio/detail/gcc_x86_fenced_block.hpp \ asio/detail/global.hpp \ asio/detail/handler_alloc_helpers.hpp \ asio/detail/handler_cont_helpers.hpp \ - asio/detail/handler_invoke_helpers.hpp \ asio/detail/handler_tracking.hpp \ asio/detail/handler_type_requirements.hpp \ asio/detail/handler_work.hpp \ @@ -102,16 +114,21 @@ nobase_include_HEADERS = \ asio/detail/impl/epoll_reactor.ipp \ asio/detail/impl/eventfd_select_interrupter.ipp \ asio/detail/impl/handler_tracking.ipp \ + asio/detail/impl/io_uring_descriptor_service.ipp \ + asio/detail/impl/io_uring_file_service.ipp \ + asio/detail/impl/io_uring_service.hpp \ + asio/detail/impl/io_uring_service.ipp \ + asio/detail/impl/io_uring_socket_service_base.ipp \ asio/detail/impl/kqueue_reactor.hpp \ asio/detail/impl/kqueue_reactor.ipp \ asio/detail/impl/null_event.ipp \ asio/detail/impl/pipe_select_interrupter.ipp \ asio/detail/impl/posix_event.ipp \ asio/detail/impl/posix_mutex.ipp \ + asio/detail/impl/posix_serial_port_service.ipp \ asio/detail/impl/posix_thread.ipp \ asio/detail/impl/posix_tss_ptr.ipp \ asio/detail/impl/reactive_descriptor_service.ipp \ - asio/detail/impl/reactive_serial_port_service.ipp \ asio/detail/impl/reactive_socket_service_base.ipp \ asio/detail/impl/resolver_service_base.ipp \ asio/detail/impl/scheduler.ipp \ @@ -131,6 +148,7 @@ nobase_include_HEADERS = \ asio/detail/impl/timer_queue_ptime.ipp \ asio/detail/impl/timer_queue_set.ipp \ asio/detail/impl/win_event.ipp \ + asio/detail/impl/win_iocp_file_service.ipp \ asio/detail/impl/win_iocp_handle_service.ipp \ asio/detail/impl/win_iocp_io_context.hpp \ asio/detail/impl/win_iocp_io_context.ipp \ @@ -145,15 +163,36 @@ nobase_include_HEADERS = \ asio/detail/impl/win_static_mutex.ipp \ asio/detail/impl/win_thread.ipp \ asio/detail/impl/win_tss_ptr.ipp \ + asio/detail/initiate_defer.hpp \ + asio/detail/initiate_dispatch.hpp \ + asio/detail/initiate_post.hpp \ asio/detail/io_control.hpp \ asio/detail/io_object_impl.hpp \ + asio/detail/io_uring_descriptor_read_at_op.hpp \ + asio/detail/io_uring_descriptor_read_op.hpp \ + asio/detail/io_uring_descriptor_service.hpp \ + asio/detail/io_uring_descriptor_write_at_op.hpp \ + asio/detail/io_uring_descriptor_write_op.hpp \ + asio/detail/io_uring_file_service.hpp \ + asio/detail/io_uring_null_buffers_op.hpp \ + asio/detail/io_uring_operation.hpp \ + asio/detail/io_uring_service.hpp \ + asio/detail/io_uring_socket_accept_op.hpp \ + asio/detail/io_uring_socket_connect_op.hpp \ + asio/detail/io_uring_socket_recvfrom_op.hpp \ + asio/detail/io_uring_socket_recvmsg_op.hpp \ + asio/detail/io_uring_socket_recv_op.hpp \ + asio/detail/io_uring_socket_send_op.hpp \ + asio/detail/io_uring_socket_sendto_op.hpp \ + asio/detail/io_uring_socket_service_base.hpp \ + asio/detail/io_uring_socket_service.hpp \ + asio/detail/io_uring_wait_op.hpp \ asio/detail/is_buffer_sequence.hpp \ asio/detail/is_executor.hpp \ asio/detail/keyword_tss_ptr.hpp \ asio/detail/kqueue_reactor.hpp \ asio/detail/limits.hpp \ asio/detail/local_free_on_block_exit.hpp \ - asio/detail/macos_fenced_block.hpp \ asio/detail/memory.hpp \ asio/detail/mutex.hpp \ asio/detail/non_const_lvalue.hpp \ @@ -178,6 +217,7 @@ nobase_include_HEADERS = \ asio/detail/posix_fd_set_adapter.hpp \ asio/detail/posix_global.hpp \ asio/detail/posix_mutex.hpp \ + asio/detail/posix_serial_port_service.hpp \ asio/detail/posix_signal_blocker.hpp \ asio/detail/posix_static_mutex.hpp \ asio/detail/posix_thread.hpp \ @@ -185,7 +225,6 @@ nobase_include_HEADERS = \ asio/detail/push_options.hpp \ asio/detail/reactive_descriptor_service.hpp \ asio/detail/reactive_null_buffers_op.hpp \ - asio/detail/reactive_serial_port_service.hpp \ asio/detail/reactive_socket_accept_op.hpp \ asio/detail/reactive_socket_connect_op.hpp \ asio/detail/reactive_socket_recvfrom_op.hpp \ @@ -196,7 +235,6 @@ nobase_include_HEADERS = \ asio/detail/reactive_socket_service_base.hpp \ asio/detail/reactive_socket_service.hpp \ asio/detail/reactive_wait_op.hpp \ - asio/detail/reactor_fwd.hpp \ asio/detail/reactor.hpp \ asio/detail/reactor_op.hpp \ asio/detail/reactor_op_queue.hpp \ @@ -209,6 +247,7 @@ nobase_include_HEADERS = \ asio/detail/resolver_service.hpp \ asio/detail/scheduler.hpp \ asio/detail/scheduler_operation.hpp \ + asio/detail/scheduler_task.hpp \ asio/detail/scheduler_thread_info.hpp \ asio/detail/scoped_lock.hpp \ asio/detail/scoped_ptr.hpp \ @@ -225,7 +264,6 @@ nobase_include_HEADERS = \ asio/detail/socket_option.hpp \ asio/detail/socket_select_interrupter.hpp \ asio/detail/socket_types.hpp \ - asio/detail/solaris_fenced_block.hpp \ asio/detail/source_location.hpp \ asio/detail/static_mutex.hpp \ asio/detail/std_event.hpp \ @@ -251,15 +289,15 @@ nobase_include_HEADERS = \ asio/detail/timer_scheduler.hpp \ asio/detail/tss_ptr.hpp \ asio/detail/type_traits.hpp \ - asio/detail/variadic_templates.hpp \ + asio/detail/utility.hpp \ asio/detail/wait_handler.hpp \ asio/detail/wait_op.hpp \ asio/detail/winapp_thread.hpp \ asio/detail/wince_thread.hpp \ asio/detail/win_event.hpp \ asio/detail/win_fd_set_adapter.hpp \ - asio/detail/win_fenced_block.hpp \ asio/detail/win_global.hpp \ + asio/detail/win_iocp_file_service.hpp \ asio/detail/win_iocp_handle_read_op.hpp \ asio/detail/win_iocp_handle_service.hpp \ asio/detail/win_iocp_handle_write_op.hpp \ @@ -308,62 +346,61 @@ nobase_include_HEADERS = \ asio/execution/bad_executor.hpp \ asio/execution/blocking.hpp \ asio/execution/blocking_adaptation.hpp \ - asio/execution/bulk_execute.hpp \ - asio/execution/bulk_guarantee.hpp \ - asio/execution/connect.hpp \ asio/execution/context.hpp \ asio/execution/context_as.hpp \ - asio/execution/detail/as_invocable.hpp \ - asio/execution/detail/as_operation.hpp \ - asio/execution/detail/as_receiver.hpp \ - asio/execution/detail/bulk_sender.hpp \ - asio/execution/detail/submit_receiver.hpp \ - asio/execution/detail/void_receiver.hpp \ - asio/execution/execute.hpp \ asio/execution/executor.hpp \ asio/execution/impl/bad_executor.ipp \ - asio/execution/impl/receiver_invocation_error.ipp \ asio/execution/invocable_archetype.hpp \ asio/execution/mapping.hpp \ asio/execution/occupancy.hpp \ - asio/execution/operation_state.hpp \ asio/execution/outstanding_work.hpp \ asio/execution/prefer_only.hpp \ - asio/execution/receiver.hpp \ - asio/execution/receiver_invocation_error.hpp \ asio/execution/relationship.hpp \ - asio/execution/schedule.hpp \ - asio/execution/scheduler.hpp \ - asio/execution/sender.hpp \ - asio/execution/set_done.hpp \ - asio/execution/set_error.hpp \ - asio/execution/set_value.hpp \ - asio/execution/start.hpp \ - asio/execution/submit.hpp \ asio/executor.hpp \ asio/executor_work_guard.hpp \ asio/experimental/append.hpp \ asio/experimental/as_single.hpp \ asio/experimental/as_tuple.hpp \ asio/experimental/awaitable_operators.hpp \ + asio/experimental/basic_channel.hpp \ + asio/experimental/basic_concurrent_channel.hpp \ asio/experimental/cancellation_condition.hpp \ + asio/experimental/channel.hpp \ + asio/experimental/channel_error.hpp \ + asio/experimental/channel_traits.hpp \ + asio/experimental/co_composed.hpp \ + asio/experimental/co_spawn.hpp \ + asio/experimental/concurrent_channel.hpp \ asio/experimental/coro.hpp \ + asio/experimental/coro_traits.hpp \ asio/experimental/deferred.hpp \ - asio/experimental/detail/completion_handler_erasure.hpp \ + asio/experimental/detail/channel_handler.hpp \ + asio/experimental/detail/channel_message.hpp \ + asio/experimental/detail/channel_operation.hpp \ + asio/experimental/detail/channel_payload.hpp \ + asio/experimental/detail/channel_receive_op.hpp \ + asio/experimental/detail/channel_send_functions.hpp \ + asio/experimental/detail/channel_send_op.hpp \ + asio/experimental/detail/channel_service.hpp \ + asio/experimental/detail/coro_completion_handler.hpp \ asio/experimental/detail/coro_promise_allocator.hpp \ - asio/experimental/detail/coro_traits.hpp \ + asio/experimental/detail/has_signature.hpp \ + asio/experimental/detail/impl/channel_service.hpp \ asio/experimental/detail/partial_promise.hpp \ - asio/experimental/impl/append.hpp \ asio/experimental/impl/as_single.hpp \ - asio/experimental/impl/as_tuple.hpp \ - asio/experimental/impl/deferred.hpp \ + asio/experimental/impl/channel_error.ipp \ + asio/experimental/impl/co_composed.hpp \ + asio/experimental/impl/coro.hpp \ asio/experimental/impl/parallel_group.hpp \ - asio/experimental/impl/prepend.hpp \ asio/experimental/impl/promise.hpp \ + asio/experimental/impl/use_coro.hpp \ + asio/experimental/impl/use_promise.hpp \ asio/experimental/parallel_group.hpp \ asio/experimental/prepend.hpp \ asio/experimental/promise.hpp \ asio/experimental/use_coro.hpp \ + asio/experimental/use_promise.hpp \ + asio/file_base.hpp \ asio/generic/basic_endpoint.hpp \ asio/generic/datagram_protocol.hpp \ asio/generic/detail/endpoint.hpp \ @@ -371,31 +408,34 @@ nobase_include_HEADERS = \ asio/generic/raw_protocol.hpp \ asio/generic/seq_packet_protocol.hpp \ asio/generic/stream_protocol.hpp \ - asio/handler_alloc_hook.hpp \ asio/handler_continuation_hook.hpp \ - asio/handler_invoke_hook.hpp \ asio/high_resolution_timer.hpp \ asio.hpp \ + asio/impl/any_completion_executor.ipp \ + asio/impl/any_io_executor.ipp \ + asio/impl/append.hpp \ + asio/impl/as_tuple.hpp \ asio/impl/awaitable.hpp \ asio/impl/buffered_read_stream.hpp \ asio/impl/buffered_write_stream.hpp \ + asio/impl/cancellation_signal.ipp \ asio/impl/co_spawn.hpp \ - asio/impl/compose.hpp \ asio/impl/connect.hpp \ - asio/impl/defer.hpp \ + asio/impl/connect_pipe.hpp \ + asio/impl/connect_pipe.ipp \ + asio/impl/consign.hpp \ + asio/impl/deferred.hpp \ asio/impl/detached.hpp \ - asio/impl/dispatch.hpp \ asio/impl/error_code.ipp \ asio/impl/error.ipp \ asio/impl/execution_context.hpp \ asio/impl/execution_context.ipp \ asio/impl/executor.hpp \ asio/impl/executor.ipp \ - asio/impl/handler_alloc_hook.ipp \ asio/impl/io_context.hpp \ asio/impl/io_context.ipp \ asio/impl/multiple_exceptions.ipp \ - asio/impl/post.hpp \ + asio/impl/prepend.hpp \ asio/impl/read_at.hpp \ asio/impl/read.hpp \ asio/impl/read_until.hpp \ @@ -458,6 +498,7 @@ nobase_include_HEADERS = \ asio/ip/unicast.hpp \ asio/ip/v6_only.hpp \ asio/is_applicable_property.hpp \ + asio/is_contiguous_iterator.hpp \ asio/is_executor.hpp \ asio/is_read_buffered.hpp \ asio/is_write_buffered.hpp \ @@ -466,6 +507,7 @@ nobase_include_HEADERS = \ asio/local/datagram_protocol.hpp \ asio/local/detail/endpoint.hpp \ asio/local/detail/impl/endpoint.ipp \ + asio/local/seq_packet_protocol.hpp \ asio/local/stream_protocol.hpp \ asio/multiple_exceptions.hpp \ asio/packaged_task.hpp \ @@ -477,15 +519,21 @@ nobase_include_HEADERS = \ asio/posix/stream_descriptor.hpp \ asio/post.hpp \ asio/prefer.hpp \ + asio/prepend.hpp \ asio/query.hpp \ + asio/random_access_file.hpp \ asio/read_at.hpp \ asio/read.hpp \ asio/read_until.hpp \ + asio/readable_pipe.hpp \ + asio/recycling_allocator.hpp \ asio/redirect_error.hpp \ + asio/registered_buffer.hpp \ asio/require.hpp \ asio/require_concept.hpp \ asio/serial_port_base.hpp \ asio/serial_port.hpp \ + asio/signal_set_base.hpp \ asio/signal_set.hpp \ asio/socket_base.hpp \ asio/spawn.hpp \ @@ -523,6 +571,7 @@ nobase_include_HEADERS = \ asio/steady_timer.hpp \ asio/strand.hpp \ asio/streambuf.hpp \ + asio/stream_file.hpp \ asio/system_context.hpp \ asio/system_error.hpp \ asio/system_executor.hpp \ @@ -531,12 +580,7 @@ nobase_include_HEADERS = \ asio/thread.hpp \ asio/thread_pool.hpp \ asio/time_traits.hpp \ - asio/traits/bulk_execute_free.hpp \ - asio/traits/bulk_execute_member.hpp \ - asio/traits/connect_free.hpp \ - asio/traits/connect_member.hpp \ asio/traits/equality_comparable.hpp \ - asio/traits/execute_free.hpp \ asio/traits/execute_member.hpp \ asio/traits/prefer_free.hpp \ asio/traits/prefer_member.hpp \ @@ -547,21 +591,9 @@ nobase_include_HEADERS = \ asio/traits/require_concept_member.hpp \ asio/traits/require_free.hpp \ asio/traits/require_member.hpp \ - asio/traits/schedule_free.hpp \ - asio/traits/schedule_member.hpp \ - asio/traits/set_done_free.hpp \ - asio/traits/set_done_member.hpp \ - asio/traits/set_error_free.hpp \ - asio/traits/set_error_member.hpp \ - asio/traits/set_value_free.hpp \ - asio/traits/set_value_member.hpp \ - asio/traits/start_free.hpp \ - asio/traits/start_member.hpp \ asio/traits/static_query.hpp \ asio/traits/static_require.hpp \ asio/traits/static_require_concept.hpp \ - asio/traits/submit_free.hpp \ - asio/traits/submit_member.hpp \ asio/ts/buffer.hpp \ asio/ts/executor.hpp \ asio/ts/internet.hpp \ @@ -585,6 +617,7 @@ nobase_include_HEADERS = \ asio/windows/overlapped_ptr.hpp \ asio/windows/random_access_handle.hpp \ asio/windows/stream_handle.hpp \ + asio/writable_pipe.hpp \ asio/write_at.hpp \ asio/write.hpp \ asio/yield.hpp diff --git a/3rdparty/asio/include/Makefile.in b/3rdparty/asio/include/Makefile.in index 4bb29452b71..e71be1bf590 100644 --- a/3rdparty/asio/include/Makefile.in +++ b/3rdparty/asio/include/Makefile.in @@ -1,7 +1,7 @@ -# Makefile.in generated by automake 1.16.1 from Makefile.am. +# Makefile.in generated by automake 1.16.5 from Makefile.am. # @configure_input@ -# Copyright (C) 1994-2018 Free Software Foundation, Inc. +# Copyright (C) 1994-2021 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -163,8 +163,6 @@ am__define_uniq_tagged_files = \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` -ETAGS = etags -CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ @@ -178,8 +176,9 @@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ CXX = @CXX@ -CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ @@ -188,9 +187,8 @@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ -EGREP = @EGREP@ +ETAGS = @ETAGS@ EXEEXT = @EXEEXT@ -GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ @@ -257,9 +255,11 @@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ +pkgconfigdir = @pkgconfigdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -271,17 +271,25 @@ top_srcdir = @top_srcdir@ # find . -name "*.*pp" | sed -e 's/^\.\///' | sed -e 's/^.*$/ & \\/' | sort nobase_include_HEADERS = \ + asio/any_completion_executor.hpp \ + asio/any_completion_handler.hpp \ asio/any_io_executor.hpp \ + asio/append.hpp \ + asio/as_tuple.hpp \ asio/associated_allocator.hpp \ asio/associated_cancellation_slot.hpp \ asio/associated_executor.hpp \ + asio/associated_immediate_executor.hpp \ asio/associator.hpp \ asio/async_result.hpp \ asio/awaitable.hpp \ asio/basic_datagram_socket.hpp \ asio/basic_deadline_timer.hpp \ + asio/basic_file.hpp \ asio/basic_io_object.hpp \ + asio/basic_random_access_file.hpp \ asio/basic_raw_socket.hpp \ + asio/basic_readable_pipe.hpp \ asio/basic_seq_packet_socket.hpp \ asio/basic_serial_port.hpp \ asio/basic_signal_set.hpp \ @@ -291,10 +299,14 @@ nobase_include_HEADERS = \ asio/basic_socket_streambuf.hpp \ asio/basic_streambuf_fwd.hpp \ asio/basic_streambuf.hpp \ + asio/basic_stream_file.hpp \ asio/basic_stream_socket.hpp \ asio/basic_waitable_timer.hpp \ + asio/basic_writable_pipe.hpp \ + asio/bind_allocator.hpp \ asio/bind_cancellation_slot.hpp \ asio/bind_executor.hpp \ + asio/bind_immediate_executor.hpp \ asio/buffered_read_stream_fwd.hpp \ asio/buffered_read_stream.hpp \ asio/buffered_stream_fwd.hpp \ @@ -302,6 +314,7 @@ nobase_include_HEADERS = \ asio/buffered_write_stream_fwd.hpp \ asio/buffered_write_stream.hpp \ asio/buffer.hpp \ + asio/buffer_registration.hpp \ asio/buffers_iterator.hpp \ asio/cancellation_signal.hpp \ asio/cancellation_state.hpp \ @@ -310,9 +323,12 @@ nobase_include_HEADERS = \ asio/completion_condition.hpp \ asio/compose.hpp \ asio/connect.hpp \ + asio/connect_pipe.hpp \ + asio/consign.hpp \ asio/coroutine.hpp \ asio/deadline_timer.hpp \ asio/defer.hpp \ + asio/deferred.hpp \ asio/detached.hpp \ asio/detail/array_fwd.hpp \ asio/detail/array.hpp \ @@ -325,11 +341,11 @@ nobase_include_HEADERS = \ asio/detail/buffered_stream_storage.hpp \ asio/detail/buffer_resize_guard.hpp \ asio/detail/buffer_sequence_adapter.hpp \ - asio/detail/bulk_executor_op.hpp \ asio/detail/call_stack.hpp \ asio/detail/chrono.hpp \ asio/detail/chrono_time_traits.hpp \ asio/detail/completion_handler.hpp \ + asio/detail/composed_work.hpp \ asio/detail/concurrency_hint.hpp \ asio/detail/conditionally_enabled_event.hpp \ asio/detail/conditionally_enabled_mutex.hpp \ @@ -347,20 +363,16 @@ nobase_include_HEADERS = \ asio/detail/epoll_reactor.hpp \ asio/detail/eventfd_select_interrupter.hpp \ asio/detail/event.hpp \ + asio/detail/exception.hpp \ asio/detail/executor_function.hpp \ asio/detail/executor_op.hpp \ asio/detail/fd_set_adapter.hpp \ asio/detail/fenced_block.hpp \ asio/detail/functional.hpp \ asio/detail/future.hpp \ - asio/detail/gcc_arm_fenced_block.hpp \ - asio/detail/gcc_hppa_fenced_block.hpp \ - asio/detail/gcc_sync_fenced_block.hpp \ - asio/detail/gcc_x86_fenced_block.hpp \ asio/detail/global.hpp \ asio/detail/handler_alloc_helpers.hpp \ asio/detail/handler_cont_helpers.hpp \ - asio/detail/handler_invoke_helpers.hpp \ asio/detail/handler_tracking.hpp \ asio/detail/handler_type_requirements.hpp \ asio/detail/handler_work.hpp \ @@ -373,16 +385,21 @@ nobase_include_HEADERS = \ asio/detail/impl/epoll_reactor.ipp \ asio/detail/impl/eventfd_select_interrupter.ipp \ asio/detail/impl/handler_tracking.ipp \ + asio/detail/impl/io_uring_descriptor_service.ipp \ + asio/detail/impl/io_uring_file_service.ipp \ + asio/detail/impl/io_uring_service.hpp \ + asio/detail/impl/io_uring_service.ipp \ + asio/detail/impl/io_uring_socket_service_base.ipp \ asio/detail/impl/kqueue_reactor.hpp \ asio/detail/impl/kqueue_reactor.ipp \ asio/detail/impl/null_event.ipp \ asio/detail/impl/pipe_select_interrupter.ipp \ asio/detail/impl/posix_event.ipp \ asio/detail/impl/posix_mutex.ipp \ + asio/detail/impl/posix_serial_port_service.ipp \ asio/detail/impl/posix_thread.ipp \ asio/detail/impl/posix_tss_ptr.ipp \ asio/detail/impl/reactive_descriptor_service.ipp \ - asio/detail/impl/reactive_serial_port_service.ipp \ asio/detail/impl/reactive_socket_service_base.ipp \ asio/detail/impl/resolver_service_base.ipp \ asio/detail/impl/scheduler.ipp \ @@ -402,6 +419,7 @@ nobase_include_HEADERS = \ asio/detail/impl/timer_queue_ptime.ipp \ asio/detail/impl/timer_queue_set.ipp \ asio/detail/impl/win_event.ipp \ + asio/detail/impl/win_iocp_file_service.ipp \ asio/detail/impl/win_iocp_handle_service.ipp \ asio/detail/impl/win_iocp_io_context.hpp \ asio/detail/impl/win_iocp_io_context.ipp \ @@ -416,15 +434,36 @@ nobase_include_HEADERS = \ asio/detail/impl/win_static_mutex.ipp \ asio/detail/impl/win_thread.ipp \ asio/detail/impl/win_tss_ptr.ipp \ + asio/detail/initiate_defer.hpp \ + asio/detail/initiate_dispatch.hpp \ + asio/detail/initiate_post.hpp \ asio/detail/io_control.hpp \ asio/detail/io_object_impl.hpp \ + asio/detail/io_uring_descriptor_read_at_op.hpp \ + asio/detail/io_uring_descriptor_read_op.hpp \ + asio/detail/io_uring_descriptor_service.hpp \ + asio/detail/io_uring_descriptor_write_at_op.hpp \ + asio/detail/io_uring_descriptor_write_op.hpp \ + asio/detail/io_uring_file_service.hpp \ + asio/detail/io_uring_null_buffers_op.hpp \ + asio/detail/io_uring_operation.hpp \ + asio/detail/io_uring_service.hpp \ + asio/detail/io_uring_socket_accept_op.hpp \ + asio/detail/io_uring_socket_connect_op.hpp \ + asio/detail/io_uring_socket_recvfrom_op.hpp \ + asio/detail/io_uring_socket_recvmsg_op.hpp \ + asio/detail/io_uring_socket_recv_op.hpp \ + asio/detail/io_uring_socket_send_op.hpp \ + asio/detail/io_uring_socket_sendto_op.hpp \ + asio/detail/io_uring_socket_service_base.hpp \ + asio/detail/io_uring_socket_service.hpp \ + asio/detail/io_uring_wait_op.hpp \ asio/detail/is_buffer_sequence.hpp \ asio/detail/is_executor.hpp \ asio/detail/keyword_tss_ptr.hpp \ asio/detail/kqueue_reactor.hpp \ asio/detail/limits.hpp \ asio/detail/local_free_on_block_exit.hpp \ - asio/detail/macos_fenced_block.hpp \ asio/detail/memory.hpp \ asio/detail/mutex.hpp \ asio/detail/non_const_lvalue.hpp \ @@ -449,6 +488,7 @@ nobase_include_HEADERS = \ asio/detail/posix_fd_set_adapter.hpp \ asio/detail/posix_global.hpp \ asio/detail/posix_mutex.hpp \ + asio/detail/posix_serial_port_service.hpp \ asio/detail/posix_signal_blocker.hpp \ asio/detail/posix_static_mutex.hpp \ asio/detail/posix_thread.hpp \ @@ -456,7 +496,6 @@ nobase_include_HEADERS = \ asio/detail/push_options.hpp \ asio/detail/reactive_descriptor_service.hpp \ asio/detail/reactive_null_buffers_op.hpp \ - asio/detail/reactive_serial_port_service.hpp \ asio/detail/reactive_socket_accept_op.hpp \ asio/detail/reactive_socket_connect_op.hpp \ asio/detail/reactive_socket_recvfrom_op.hpp \ @@ -467,7 +506,6 @@ nobase_include_HEADERS = \ asio/detail/reactive_socket_service_base.hpp \ asio/detail/reactive_socket_service.hpp \ asio/detail/reactive_wait_op.hpp \ - asio/detail/reactor_fwd.hpp \ asio/detail/reactor.hpp \ asio/detail/reactor_op.hpp \ asio/detail/reactor_op_queue.hpp \ @@ -480,6 +518,7 @@ nobase_include_HEADERS = \ asio/detail/resolver_service.hpp \ asio/detail/scheduler.hpp \ asio/detail/scheduler_operation.hpp \ + asio/detail/scheduler_task.hpp \ asio/detail/scheduler_thread_info.hpp \ asio/detail/scoped_lock.hpp \ asio/detail/scoped_ptr.hpp \ @@ -496,7 +535,6 @@ nobase_include_HEADERS = \ asio/detail/socket_option.hpp \ asio/detail/socket_select_interrupter.hpp \ asio/detail/socket_types.hpp \ - asio/detail/solaris_fenced_block.hpp \ asio/detail/source_location.hpp \ asio/detail/static_mutex.hpp \ asio/detail/std_event.hpp \ @@ -522,15 +560,15 @@ nobase_include_HEADERS = \ asio/detail/timer_scheduler.hpp \ asio/detail/tss_ptr.hpp \ asio/detail/type_traits.hpp \ - asio/detail/variadic_templates.hpp \ + asio/detail/utility.hpp \ asio/detail/wait_handler.hpp \ asio/detail/wait_op.hpp \ asio/detail/winapp_thread.hpp \ asio/detail/wince_thread.hpp \ asio/detail/win_event.hpp \ asio/detail/win_fd_set_adapter.hpp \ - asio/detail/win_fenced_block.hpp \ asio/detail/win_global.hpp \ + asio/detail/win_iocp_file_service.hpp \ asio/detail/win_iocp_handle_read_op.hpp \ asio/detail/win_iocp_handle_service.hpp \ asio/detail/win_iocp_handle_write_op.hpp \ @@ -579,62 +617,61 @@ nobase_include_HEADERS = \ asio/execution/bad_executor.hpp \ asio/execution/blocking.hpp \ asio/execution/blocking_adaptation.hpp \ - asio/execution/bulk_execute.hpp \ - asio/execution/bulk_guarantee.hpp \ - asio/execution/connect.hpp \ asio/execution/context.hpp \ asio/execution/context_as.hpp \ - asio/execution/detail/as_invocable.hpp \ - asio/execution/detail/as_operation.hpp \ - asio/execution/detail/as_receiver.hpp \ - asio/execution/detail/bulk_sender.hpp \ - asio/execution/detail/submit_receiver.hpp \ - asio/execution/detail/void_receiver.hpp \ - asio/execution/execute.hpp \ asio/execution/executor.hpp \ asio/execution/impl/bad_executor.ipp \ - asio/execution/impl/receiver_invocation_error.ipp \ asio/execution/invocable_archetype.hpp \ asio/execution/mapping.hpp \ asio/execution/occupancy.hpp \ - asio/execution/operation_state.hpp \ asio/execution/outstanding_work.hpp \ asio/execution/prefer_only.hpp \ - asio/execution/receiver.hpp \ - asio/execution/receiver_invocation_error.hpp \ asio/execution/relationship.hpp \ - asio/execution/schedule.hpp \ - asio/execution/scheduler.hpp \ - asio/execution/sender.hpp \ - asio/execution/set_done.hpp \ - asio/execution/set_error.hpp \ - asio/execution/set_value.hpp \ - asio/execution/start.hpp \ - asio/execution/submit.hpp \ asio/executor.hpp \ asio/executor_work_guard.hpp \ asio/experimental/append.hpp \ asio/experimental/as_single.hpp \ asio/experimental/as_tuple.hpp \ asio/experimental/awaitable_operators.hpp \ + asio/experimental/basic_channel.hpp \ + asio/experimental/basic_concurrent_channel.hpp \ asio/experimental/cancellation_condition.hpp \ + asio/experimental/channel.hpp \ + asio/experimental/channel_error.hpp \ + asio/experimental/channel_traits.hpp \ + asio/experimental/co_composed.hpp \ + asio/experimental/co_spawn.hpp \ + asio/experimental/concurrent_channel.hpp \ asio/experimental/coro.hpp \ + asio/experimental/coro_traits.hpp \ asio/experimental/deferred.hpp \ - asio/experimental/detail/completion_handler_erasure.hpp \ + asio/experimental/detail/channel_handler.hpp \ + asio/experimental/detail/channel_message.hpp \ + asio/experimental/detail/channel_operation.hpp \ + asio/experimental/detail/channel_payload.hpp \ + asio/experimental/detail/channel_receive_op.hpp \ + asio/experimental/detail/channel_send_functions.hpp \ + asio/experimental/detail/channel_send_op.hpp \ + asio/experimental/detail/channel_service.hpp \ + asio/experimental/detail/coro_completion_handler.hpp \ asio/experimental/detail/coro_promise_allocator.hpp \ - asio/experimental/detail/coro_traits.hpp \ + asio/experimental/detail/has_signature.hpp \ + asio/experimental/detail/impl/channel_service.hpp \ asio/experimental/detail/partial_promise.hpp \ - asio/experimental/impl/append.hpp \ asio/experimental/impl/as_single.hpp \ - asio/experimental/impl/as_tuple.hpp \ - asio/experimental/impl/deferred.hpp \ + asio/experimental/impl/channel_error.ipp \ + asio/experimental/impl/co_composed.hpp \ + asio/experimental/impl/coro.hpp \ asio/experimental/impl/parallel_group.hpp \ - asio/experimental/impl/prepend.hpp \ asio/experimental/impl/promise.hpp \ + asio/experimental/impl/use_coro.hpp \ + asio/experimental/impl/use_promise.hpp \ asio/experimental/parallel_group.hpp \ asio/experimental/prepend.hpp \ asio/experimental/promise.hpp \ asio/experimental/use_coro.hpp \ + asio/experimental/use_promise.hpp \ + asio/file_base.hpp \ asio/generic/basic_endpoint.hpp \ asio/generic/datagram_protocol.hpp \ asio/generic/detail/endpoint.hpp \ @@ -642,31 +679,34 @@ nobase_include_HEADERS = \ asio/generic/raw_protocol.hpp \ asio/generic/seq_packet_protocol.hpp \ asio/generic/stream_protocol.hpp \ - asio/handler_alloc_hook.hpp \ asio/handler_continuation_hook.hpp \ - asio/handler_invoke_hook.hpp \ asio/high_resolution_timer.hpp \ asio.hpp \ + asio/impl/any_completion_executor.ipp \ + asio/impl/any_io_executor.ipp \ + asio/impl/append.hpp \ + asio/impl/as_tuple.hpp \ asio/impl/awaitable.hpp \ asio/impl/buffered_read_stream.hpp \ asio/impl/buffered_write_stream.hpp \ + asio/impl/cancellation_signal.ipp \ asio/impl/co_spawn.hpp \ - asio/impl/compose.hpp \ asio/impl/connect.hpp \ - asio/impl/defer.hpp \ + asio/impl/connect_pipe.hpp \ + asio/impl/connect_pipe.ipp \ + asio/impl/consign.hpp \ + asio/impl/deferred.hpp \ asio/impl/detached.hpp \ - asio/impl/dispatch.hpp \ asio/impl/error_code.ipp \ asio/impl/error.ipp \ asio/impl/execution_context.hpp \ asio/impl/execution_context.ipp \ asio/impl/executor.hpp \ asio/impl/executor.ipp \ - asio/impl/handler_alloc_hook.ipp \ asio/impl/io_context.hpp \ asio/impl/io_context.ipp \ asio/impl/multiple_exceptions.ipp \ - asio/impl/post.hpp \ + asio/impl/prepend.hpp \ asio/impl/read_at.hpp \ asio/impl/read.hpp \ asio/impl/read_until.hpp \ @@ -729,6 +769,7 @@ nobase_include_HEADERS = \ asio/ip/unicast.hpp \ asio/ip/v6_only.hpp \ asio/is_applicable_property.hpp \ + asio/is_contiguous_iterator.hpp \ asio/is_executor.hpp \ asio/is_read_buffered.hpp \ asio/is_write_buffered.hpp \ @@ -737,6 +778,7 @@ nobase_include_HEADERS = \ asio/local/datagram_protocol.hpp \ asio/local/detail/endpoint.hpp \ asio/local/detail/impl/endpoint.ipp \ + asio/local/seq_packet_protocol.hpp \ asio/local/stream_protocol.hpp \ asio/multiple_exceptions.hpp \ asio/packaged_task.hpp \ @@ -748,15 +790,21 @@ nobase_include_HEADERS = \ asio/posix/stream_descriptor.hpp \ asio/post.hpp \ asio/prefer.hpp \ + asio/prepend.hpp \ asio/query.hpp \ + asio/random_access_file.hpp \ asio/read_at.hpp \ asio/read.hpp \ asio/read_until.hpp \ + asio/readable_pipe.hpp \ + asio/recycling_allocator.hpp \ asio/redirect_error.hpp \ + asio/registered_buffer.hpp \ asio/require.hpp \ asio/require_concept.hpp \ asio/serial_port_base.hpp \ asio/serial_port.hpp \ + asio/signal_set_base.hpp \ asio/signal_set.hpp \ asio/socket_base.hpp \ asio/spawn.hpp \ @@ -794,6 +842,7 @@ nobase_include_HEADERS = \ asio/steady_timer.hpp \ asio/strand.hpp \ asio/streambuf.hpp \ + asio/stream_file.hpp \ asio/system_context.hpp \ asio/system_error.hpp \ asio/system_executor.hpp \ @@ -802,12 +851,7 @@ nobase_include_HEADERS = \ asio/thread.hpp \ asio/thread_pool.hpp \ asio/time_traits.hpp \ - asio/traits/bulk_execute_free.hpp \ - asio/traits/bulk_execute_member.hpp \ - asio/traits/connect_free.hpp \ - asio/traits/connect_member.hpp \ asio/traits/equality_comparable.hpp \ - asio/traits/execute_free.hpp \ asio/traits/execute_member.hpp \ asio/traits/prefer_free.hpp \ asio/traits/prefer_member.hpp \ @@ -818,21 +862,9 @@ nobase_include_HEADERS = \ asio/traits/require_concept_member.hpp \ asio/traits/require_free.hpp \ asio/traits/require_member.hpp \ - asio/traits/schedule_free.hpp \ - asio/traits/schedule_member.hpp \ - asio/traits/set_done_free.hpp \ - asio/traits/set_done_member.hpp \ - asio/traits/set_error_free.hpp \ - asio/traits/set_error_member.hpp \ - asio/traits/set_value_free.hpp \ - asio/traits/set_value_member.hpp \ - asio/traits/start_free.hpp \ - asio/traits/start_member.hpp \ asio/traits/static_query.hpp \ asio/traits/static_require.hpp \ asio/traits/static_require_concept.hpp \ - asio/traits/submit_free.hpp \ - asio/traits/submit_member.hpp \ asio/ts/buffer.hpp \ asio/ts/executor.hpp \ asio/ts/internet.hpp \ @@ -856,6 +888,7 @@ nobase_include_HEADERS = \ asio/windows/overlapped_ptr.hpp \ asio/windows/random_access_handle.hpp \ asio/windows/stream_handle.hpp \ + asio/writable_pipe.hpp \ asio/write_at.hpp \ asio/write.hpp \ asio/yield.hpp @@ -971,7 +1004,6 @@ cscopelist-am: $(am__tagged_files) distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags - distdir: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) distdir-am diff --git a/3rdparty/asio/include/asio.hpp b/3rdparty/asio/include/asio.hpp index 94db21e8173..3421b58bdae 100644 --- a/3rdparty/asio/include/asio.hpp +++ b/3rdparty/asio/include/asio.hpp @@ -2,7 +2,7 @@ // asio.hpp // ~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -15,16 +15,25 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +#include "asio/any_completion_executor.hpp" +#include "asio/any_completion_handler.hpp" +#include "asio/any_io_executor.hpp" +#include "asio/append.hpp" +#include "asio/as_tuple.hpp" #include "asio/associated_allocator.hpp" -#include "asio/associated_executor.hpp" #include "asio/associated_cancellation_slot.hpp" +#include "asio/associated_executor.hpp" +#include "asio/associated_immediate_executor.hpp" #include "asio/associator.hpp" #include "asio/async_result.hpp" #include "asio/awaitable.hpp" #include "asio/basic_datagram_socket.hpp" #include "asio/basic_deadline_timer.hpp" +#include "asio/basic_file.hpp" #include "asio/basic_io_object.hpp" +#include "asio/basic_random_access_file.hpp" #include "asio/basic_raw_socket.hpp" +#include "asio/basic_readable_pipe.hpp" #include "asio/basic_seq_packet_socket.hpp" #include "asio/basic_serial_port.hpp" #include "asio/basic_signal_set.hpp" @@ -32,12 +41,17 @@ #include "asio/basic_socket_acceptor.hpp" #include "asio/basic_socket_iostream.hpp" #include "asio/basic_socket_streambuf.hpp" +#include "asio/basic_stream_file.hpp" #include "asio/basic_stream_socket.hpp" #include "asio/basic_streambuf.hpp" #include "asio/basic_waitable_timer.hpp" +#include "asio/basic_writable_pipe.hpp" +#include "asio/bind_allocator.hpp" #include "asio/bind_cancellation_slot.hpp" #include "asio/bind_executor.hpp" +#include "asio/bind_immediate_executor.hpp" #include "asio/buffer.hpp" +#include "asio/buffer_registration.hpp" #include "asio/buffered_read_stream_fwd.hpp" #include "asio/buffered_read_stream.hpp" #include "asio/buffered_stream_fwd.hpp" @@ -52,9 +66,12 @@ #include "asio/completion_condition.hpp" #include "asio/compose.hpp" #include "asio/connect.hpp" +#include "asio/connect_pipe.hpp" +#include "asio/consign.hpp" #include "asio/coroutine.hpp" #include "asio/deadline_timer.hpp" #include "asio/defer.hpp" +#include "asio/deferred.hpp" #include "asio/detached.hpp" #include "asio/dispatch.hpp" #include "asio/error.hpp" @@ -64,40 +81,24 @@ #include "asio/execution/any_executor.hpp" #include "asio/execution/blocking.hpp" #include "asio/execution/blocking_adaptation.hpp" -#include "asio/execution/bulk_execute.hpp" -#include "asio/execution/bulk_guarantee.hpp" -#include "asio/execution/connect.hpp" #include "asio/execution/context.hpp" #include "asio/execution/context_as.hpp" -#include "asio/execution/execute.hpp" #include "asio/execution/executor.hpp" #include "asio/execution/invocable_archetype.hpp" #include "asio/execution/mapping.hpp" #include "asio/execution/occupancy.hpp" -#include "asio/execution/operation_state.hpp" #include "asio/execution/outstanding_work.hpp" #include "asio/execution/prefer_only.hpp" -#include "asio/execution/receiver.hpp" -#include "asio/execution/receiver_invocation_error.hpp" #include "asio/execution/relationship.hpp" -#include "asio/execution/schedule.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" -#include "asio/execution/set_done.hpp" -#include "asio/execution/set_error.hpp" -#include "asio/execution/set_value.hpp" -#include "asio/execution/start.hpp" -#include "asio/execution_context.hpp" #include "asio/executor.hpp" #include "asio/executor_work_guard.hpp" +#include "asio/file_base.hpp" #include "asio/generic/basic_endpoint.hpp" #include "asio/generic/datagram_protocol.hpp" #include "asio/generic/raw_protocol.hpp" #include "asio/generic/seq_packet_protocol.hpp" #include "asio/generic/stream_protocol.hpp" -#include "asio/handler_alloc_hook.hpp" #include "asio/handler_continuation_hook.hpp" -#include "asio/handler_invoke_hook.hpp" #include "asio/high_resolution_timer.hpp" #include "asio/io_context.hpp" #include "asio/io_context_strand.hpp" @@ -128,12 +129,14 @@ #include "asio/ip/unicast.hpp" #include "asio/ip/v6_only.hpp" #include "asio/is_applicable_property.hpp" +#include "asio/is_contiguous_iterator.hpp" #include "asio/is_executor.hpp" #include "asio/is_read_buffered.hpp" #include "asio/is_write_buffered.hpp" #include "asio/local/basic_endpoint.hpp" #include "asio/local/connect_pair.hpp" #include "asio/local/datagram_protocol.hpp" +#include "asio/local/seq_packet_protocol.hpp" #include "asio/local/stream_protocol.hpp" #include "asio/multiple_exceptions.hpp" #include "asio/packaged_task.hpp" @@ -145,20 +148,27 @@ #include "asio/posix/stream_descriptor.hpp" #include "asio/post.hpp" #include "asio/prefer.hpp" +#include "asio/prepend.hpp" #include "asio/query.hpp" +#include "asio/random_access_file.hpp" #include "asio/read.hpp" #include "asio/read_at.hpp" #include "asio/read_until.hpp" +#include "asio/readable_pipe.hpp" +#include "asio/recycling_allocator.hpp" #include "asio/redirect_error.hpp" +#include "asio/registered_buffer.hpp" #include "asio/require.hpp" #include "asio/require_concept.hpp" #include "asio/serial_port.hpp" #include "asio/serial_port_base.hpp" #include "asio/signal_set.hpp" +#include "asio/signal_set_base.hpp" #include "asio/socket_base.hpp" #include "asio/static_thread_pool.hpp" #include "asio/steady_timer.hpp" #include "asio/strand.hpp" +#include "asio/stream_file.hpp" #include "asio/streambuf.hpp" #include "asio/system_context.hpp" #include "asio/system_error.hpp" @@ -182,6 +192,7 @@ #include "asio/windows/overlapped_ptr.hpp" #include "asio/windows/random_access_handle.hpp" #include "asio/windows/stream_handle.hpp" +#include "asio/writable_pipe.hpp" #include "asio/write.hpp" #include "asio/write_at.hpp" diff --git a/3rdparty/asio/include/asio/any_completion_executor.hpp b/3rdparty/asio/include/asio/any_completion_executor.hpp new file mode 100644 index 00000000000..650ff7bafdd --- /dev/null +++ b/3rdparty/asio/include/asio/any_completion_executor.hpp @@ -0,0 +1,336 @@ +// +// any_completion_executor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_ANY_COMPLETION_EXECUTOR_HPP +#define ASIO_ANY_COMPLETION_EXECUTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#if defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) +# include "asio/executor.hpp" +#else // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) +# include "asio/execution.hpp" +#endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) + +#include "asio/detail/push_options.hpp" + +namespace asio { + +#if defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) + +typedef executor any_completion_executor; + +#else // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) + +/// Polymorphic executor type for use with I/O objects. +/** + * The @c any_completion_executor type is a polymorphic executor that supports + * the set of properties required for the execution of completion handlers. It + * is defined as the execution::any_executor class template parameterised as + * follows: + * @code execution::any_executor< + * execution::prefer_only<execution::outstanding_work_t::tracked_t>, + * execution::prefer_only<execution::outstanding_work_t::untracked_t> + * execution::prefer_only<execution::relationship_t::fork_t>, + * execution::prefer_only<execution::relationship_t::continuation_t> + * > @endcode + */ +class any_completion_executor : +#if defined(GENERATING_DOCUMENTATION) + public execution::any_executor<...> +#else // defined(GENERATING_DOCUMENTATION) + public execution::any_executor< + execution::prefer_only<execution::outstanding_work_t::tracked_t>, + execution::prefer_only<execution::outstanding_work_t::untracked_t>, + execution::prefer_only<execution::relationship_t::fork_t>, + execution::prefer_only<execution::relationship_t::continuation_t> + > +#endif // defined(GENERATING_DOCUMENTATION) +{ +public: +#if !defined(GENERATING_DOCUMENTATION) + typedef execution::any_executor< + execution::prefer_only<execution::outstanding_work_t::tracked_t>, + execution::prefer_only<execution::outstanding_work_t::untracked_t>, + execution::prefer_only<execution::relationship_t::fork_t>, + execution::prefer_only<execution::relationship_t::continuation_t> + > base_type; + + typedef void supportable_properties_type( + execution::prefer_only<execution::outstanding_work_t::tracked_t>, + execution::prefer_only<execution::outstanding_work_t::untracked_t>, + execution::prefer_only<execution::relationship_t::fork_t>, + execution::prefer_only<execution::relationship_t::continuation_t> + ); +#endif // !defined(GENERATING_DOCUMENTATION) + + /// Default constructor. + ASIO_DECL any_completion_executor() noexcept; + + /// Construct in an empty state. Equivalent effects to default constructor. + ASIO_DECL any_completion_executor(nullptr_t) noexcept; + + /// Copy constructor. + ASIO_DECL any_completion_executor( + const any_completion_executor& e) noexcept; + + /// Move constructor. + ASIO_DECL any_completion_executor( + any_completion_executor&& e) noexcept; + + /// Construct to point to the same target as another any_executor. +#if defined(GENERATING_DOCUMENTATION) + template <class... OtherSupportableProperties> + any_completion_executor( + execution::any_executor<OtherSupportableProperties...> e); +#else // defined(GENERATING_DOCUMENTATION) + template <typename OtherAnyExecutor> + any_completion_executor(OtherAnyExecutor e, + constraint_t< + conditional< + !is_same<OtherAnyExecutor, any_completion_executor>::value + && is_base_of<execution::detail::any_executor_base, + OtherAnyExecutor>::value, + typename execution::detail::supportable_properties< + 0, supportable_properties_type>::template + is_valid_target<OtherAnyExecutor>, + false_type + >::type::value + > = 0) + : base_type(static_cast<OtherAnyExecutor&&>(e)) + { + } +#endif // defined(GENERATING_DOCUMENTATION) + + /// Construct to point to the same target as another any_executor. +#if defined(GENERATING_DOCUMENTATION) + template <class... OtherSupportableProperties> + any_completion_executor(std::nothrow_t, + execution::any_executor<OtherSupportableProperties...> e); +#else // defined(GENERATING_DOCUMENTATION) + template <typename OtherAnyExecutor> + any_completion_executor(std::nothrow_t, OtherAnyExecutor e, + constraint_t< + conditional< + !is_same<OtherAnyExecutor, any_completion_executor>::value + && is_base_of<execution::detail::any_executor_base, + OtherAnyExecutor>::value, + typename execution::detail::supportable_properties< + 0, supportable_properties_type>::template + is_valid_target<OtherAnyExecutor>, + false_type + >::type::value + > = 0) noexcept + : base_type(std::nothrow, static_cast<OtherAnyExecutor&&>(e)) + { + } +#endif // defined(GENERATING_DOCUMENTATION) + + /// Construct to point to the same target as another any_executor. + ASIO_DECL any_completion_executor(std::nothrow_t, + const any_completion_executor& e) noexcept; + + /// Construct to point to the same target as another any_executor. + ASIO_DECL any_completion_executor(std::nothrow_t, + any_completion_executor&& e) noexcept; + + /// Construct a polymorphic wrapper for the specified executor. +#if defined(GENERATING_DOCUMENTATION) + template <ASIO_EXECUTION_EXECUTOR Executor> + any_completion_executor(Executor e); +#else // defined(GENERATING_DOCUMENTATION) + template <ASIO_EXECUTION_EXECUTOR Executor> + any_completion_executor(Executor e, + constraint_t< + conditional< + !is_same<Executor, any_completion_executor>::value + && !is_base_of<execution::detail::any_executor_base, + Executor>::value, + execution::detail::is_valid_target_executor< + Executor, supportable_properties_type>, + false_type + >::type::value + > = 0) + : base_type(static_cast<Executor&&>(e)) + { + } +#endif // defined(GENERATING_DOCUMENTATION) + + /// Construct a polymorphic wrapper for the specified executor. +#if defined(GENERATING_DOCUMENTATION) + template <ASIO_EXECUTION_EXECUTOR Executor> + any_completion_executor(std::nothrow_t, Executor e); +#else // defined(GENERATING_DOCUMENTATION) + template <ASIO_EXECUTION_EXECUTOR Executor> + any_completion_executor(std::nothrow_t, Executor e, + constraint_t< + conditional< + !is_same<Executor, any_completion_executor>::value + && !is_base_of<execution::detail::any_executor_base, + Executor>::value, + execution::detail::is_valid_target_executor< + Executor, supportable_properties_type>, + false_type + >::type::value + > = 0) noexcept + : base_type(std::nothrow, static_cast<Executor&&>(e)) + { + } +#endif // defined(GENERATING_DOCUMENTATION) + + /// Assignment operator. + ASIO_DECL any_completion_executor& operator=( + const any_completion_executor& e) noexcept; + + /// Move assignment operator. + ASIO_DECL any_completion_executor& operator=( + any_completion_executor&& e) noexcept; + + /// Assignment operator that sets the polymorphic wrapper to the empty state. + ASIO_DECL any_completion_executor& operator=(nullptr_t); + + /// Destructor. + ASIO_DECL ~any_completion_executor(); + + /// Swap targets with another polymorphic wrapper. + ASIO_DECL void swap(any_completion_executor& other) noexcept; + + /// Obtain a polymorphic wrapper with the specified property. + /** + * Do not call this function directly. It is intended for use with the + * asio::require and asio::prefer customisation points. + * + * For example: + * @code any_completion_executor ex = ...; + * auto ex2 = asio::require(ex, execution::relationship.fork); @endcode + */ + template <typename Property> + any_completion_executor require(const Property& p, + constraint_t< + traits::require_member<const base_type&, const Property&>::is_valid + > = 0) const + { + return static_cast<const base_type&>(*this).require(p); + } + + /// Obtain a polymorphic wrapper with the specified property. + /** + * Do not call this function directly. It is intended for use with the + * asio::prefer customisation point. + * + * For example: + * @code any_completion_executor ex = ...; + * auto ex2 = asio::prefer(ex, execution::relationship.fork); @endcode + */ + template <typename Property> + any_completion_executor prefer(const Property& p, + constraint_t< + traits::prefer_member<const base_type&, const Property&>::is_valid + > = 0) const + { + return static_cast<const base_type&>(*this).prefer(p); + } +}; + +#if !defined(GENERATING_DOCUMENTATION) + +template <> +ASIO_DECL any_completion_executor any_completion_executor::prefer( + const execution::outstanding_work_t::tracked_t&, int) const; + +template <> +ASIO_DECL any_completion_executor any_completion_executor::prefer( + const execution::outstanding_work_t::untracked_t&, int) const; + +template <> +ASIO_DECL any_completion_executor any_completion_executor::prefer( + const execution::relationship_t::fork_t&, int) const; + +template <> +ASIO_DECL any_completion_executor any_completion_executor::prefer( + const execution::relationship_t::continuation_t&, int) const; + +namespace traits { + +#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) + +template <> +struct equality_comparable<any_completion_executor> +{ + static const bool is_valid = true; + static const bool is_noexcept = true; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) + +template <typename F> +struct execute_member<any_completion_executor, F> +{ + static const bool is_valid = true; + static const bool is_noexcept = false; + typedef void result_type; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) + +template <typename Prop> +struct query_member<any_completion_executor, Prop> : + query_member<any_completion_executor::base_type, Prop> +{ +}; + +#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) + +template <typename Prop> +struct require_member<any_completion_executor, Prop> : + require_member<any_completion_executor::base_type, Prop> +{ + typedef any_completion_executor result_type; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) + +template <typename Prop> +struct prefer_member<any_completion_executor, Prop> : + prefer_member<any_completion_executor::base_type, Prop> +{ + typedef any_completion_executor result_type; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) + +} // namespace traits + +#endif // !defined(GENERATING_DOCUMENTATION) + +#endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#if defined(ASIO_HEADER_ONLY) \ + && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) +# include "asio/impl/any_completion_executor.ipp" +#endif // defined(ASIO_HEADER_ONLY) + // && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) + +#endif // ASIO_ANY_COMPLETION_EXECUTOR_HPP diff --git a/3rdparty/asio/include/asio/any_completion_handler.hpp b/3rdparty/asio/include/asio/any_completion_handler.hpp new file mode 100644 index 00000000000..45b3e75fec7 --- /dev/null +++ b/3rdparty/asio/include/asio/any_completion_handler.hpp @@ -0,0 +1,822 @@ +// +// any_completion_handler.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_ANY_COMPLETION_HANDLER_HPP +#define ASIO_ANY_COMPLETION_HANDLER_HPP + +#include "asio/detail/config.hpp" +#include <cstring> +#include <functional> +#include <memory> +#include <utility> +#include "asio/any_completion_executor.hpp" +#include "asio/any_io_executor.hpp" +#include "asio/associated_allocator.hpp" +#include "asio/associated_cancellation_slot.hpp" +#include "asio/associated_executor.hpp" +#include "asio/associated_immediate_executor.hpp" +#include "asio/cancellation_state.hpp" +#include "asio/recycling_allocator.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class any_completion_handler_impl_base +{ +public: + template <typename S> + explicit any_completion_handler_impl_base(S&& slot) + : cancel_state_(static_cast<S&&>(slot), enable_total_cancellation()) + { + } + + cancellation_slot get_cancellation_slot() const noexcept + { + return cancel_state_.slot(); + } + +private: + cancellation_state cancel_state_; +}; + +template <typename Handler> +class any_completion_handler_impl : + public any_completion_handler_impl_base +{ +public: + template <typename S, typename H> + any_completion_handler_impl(S&& slot, H&& h) + : any_completion_handler_impl_base(static_cast<S&&>(slot)), + handler_(static_cast<H&&>(h)) + { + } + + struct uninit_deleter + { + typename std::allocator_traits< + associated_allocator_t<Handler, + asio::recycling_allocator<void>>>::template + rebind_alloc<any_completion_handler_impl> alloc; + + void operator()(any_completion_handler_impl* ptr) + { + std::allocator_traits<decltype(alloc)>::deallocate(alloc, ptr, 1); + } + }; + + struct deleter + { + typename std::allocator_traits< + associated_allocator_t<Handler, + asio::recycling_allocator<void>>>::template + rebind_alloc<any_completion_handler_impl> alloc; + + void operator()(any_completion_handler_impl* ptr) + { + std::allocator_traits<decltype(alloc)>::destroy(alloc, ptr); + std::allocator_traits<decltype(alloc)>::deallocate(alloc, ptr, 1); + } + }; + + template <typename S, typename H> + static any_completion_handler_impl* create(S&& slot, H&& h) + { + uninit_deleter d{ + (get_associated_allocator)(h, + asio::recycling_allocator<void>())}; + + std::unique_ptr<any_completion_handler_impl, uninit_deleter> uninit_ptr( + std::allocator_traits<decltype(d.alloc)>::allocate(d.alloc, 1), d); + + any_completion_handler_impl* ptr = + new (uninit_ptr.get()) any_completion_handler_impl( + static_cast<S&&>(slot), static_cast<H&&>(h)); + + uninit_ptr.release(); + return ptr; + } + + void destroy() + { + deleter d{ + (get_associated_allocator)(handler_, + asio::recycling_allocator<void>())}; + + d(this); + } + + any_completion_executor executor( + const any_completion_executor& candidate) const noexcept + { + return any_completion_executor(std::nothrow, + (get_associated_executor)(handler_, candidate)); + } + + any_completion_executor immediate_executor( + const any_io_executor& candidate) const noexcept + { + return any_completion_executor(std::nothrow, + (get_associated_immediate_executor)(handler_, candidate)); + } + + void* allocate(std::size_t size, std::size_t align) const + { + typename std::allocator_traits< + associated_allocator_t<Handler, + asio::recycling_allocator<void>>>::template + rebind_alloc<unsigned char> alloc( + (get_associated_allocator)(handler_, + asio::recycling_allocator<void>())); + + std::size_t space = size + align - 1; + unsigned char* base = + std::allocator_traits<decltype(alloc)>::allocate( + alloc, space + sizeof(std::ptrdiff_t)); + + void* p = base; + if (detail::align(align, size, p, space)) + { + std::ptrdiff_t off = static_cast<unsigned char*>(p) - base; + std::memcpy(static_cast<unsigned char*>(p) + size, &off, sizeof(off)); + return p; + } + + std::bad_alloc ex; + asio::detail::throw_exception(ex); + return nullptr; + } + + void deallocate(void* p, std::size_t size, std::size_t align) const + { + if (p) + { + typename std::allocator_traits< + associated_allocator_t<Handler, + asio::recycling_allocator<void>>>::template + rebind_alloc<unsigned char> alloc( + (get_associated_allocator)(handler_, + asio::recycling_allocator<void>())); + + std::ptrdiff_t off; + std::memcpy(&off, static_cast<unsigned char*>(p) + size, sizeof(off)); + unsigned char* base = static_cast<unsigned char*>(p) - off; + + std::allocator_traits<decltype(alloc)>::deallocate( + alloc, base, size + align -1 + sizeof(std::ptrdiff_t)); + } + } + + template <typename... Args> + void call(Args&&... args) + { + deleter d{ + (get_associated_allocator)(handler_, + asio::recycling_allocator<void>())}; + + std::unique_ptr<any_completion_handler_impl, deleter> ptr(this, d); + Handler handler(static_cast<Handler&&>(handler_)); + ptr.reset(); + + static_cast<Handler&&>(handler)( + static_cast<Args&&>(args)...); + } + +private: + Handler handler_; +}; + +template <typename Signature> +class any_completion_handler_call_fn; + +template <typename R, typename... Args> +class any_completion_handler_call_fn<R(Args...)> +{ +public: + using type = void(*)(any_completion_handler_impl_base*, Args...); + + constexpr any_completion_handler_call_fn(type fn) + : call_fn_(fn) + { + } + + void call(any_completion_handler_impl_base* impl, Args... args) const + { + call_fn_(impl, static_cast<Args&&>(args)...); + } + + template <typename Handler> + static void impl(any_completion_handler_impl_base* impl, Args... args) + { + static_cast<any_completion_handler_impl<Handler>*>(impl)->call( + static_cast<Args&&>(args)...); + } + +private: + type call_fn_; +}; + +template <typename... Signatures> +class any_completion_handler_call_fns; + +template <typename Signature> +class any_completion_handler_call_fns<Signature> : + public any_completion_handler_call_fn<Signature> +{ +public: + using any_completion_handler_call_fn< + Signature>::any_completion_handler_call_fn; + using any_completion_handler_call_fn<Signature>::call; +}; + +template <typename Signature, typename... Signatures> +class any_completion_handler_call_fns<Signature, Signatures...> : + public any_completion_handler_call_fn<Signature>, + public any_completion_handler_call_fns<Signatures...> +{ +public: + template <typename CallFn, typename... CallFns> + constexpr any_completion_handler_call_fns(CallFn fn, CallFns... fns) + : any_completion_handler_call_fn<Signature>(fn), + any_completion_handler_call_fns<Signatures...>(fns...) + { + } + + using any_completion_handler_call_fn<Signature>::call; + using any_completion_handler_call_fns<Signatures...>::call; +}; + +class any_completion_handler_destroy_fn +{ +public: + using type = void(*)(any_completion_handler_impl_base*); + + constexpr any_completion_handler_destroy_fn(type fn) + : destroy_fn_(fn) + { + } + + void destroy(any_completion_handler_impl_base* impl) const + { + destroy_fn_(impl); + } + + template <typename Handler> + static void impl(any_completion_handler_impl_base* impl) + { + static_cast<any_completion_handler_impl<Handler>*>(impl)->destroy(); + } + +private: + type destroy_fn_; +}; + +class any_completion_handler_executor_fn +{ +public: + using type = any_completion_executor(*)( + any_completion_handler_impl_base*, const any_completion_executor&); + + constexpr any_completion_handler_executor_fn(type fn) + : executor_fn_(fn) + { + } + + any_completion_executor executor(any_completion_handler_impl_base* impl, + const any_completion_executor& candidate) const + { + return executor_fn_(impl, candidate); + } + + template <typename Handler> + static any_completion_executor impl(any_completion_handler_impl_base* impl, + const any_completion_executor& candidate) + { + return static_cast<any_completion_handler_impl<Handler>*>(impl)->executor( + candidate); + } + +private: + type executor_fn_; +}; + +class any_completion_handler_immediate_executor_fn +{ +public: + using type = any_completion_executor(*)( + any_completion_handler_impl_base*, const any_io_executor&); + + constexpr any_completion_handler_immediate_executor_fn(type fn) + : immediate_executor_fn_(fn) + { + } + + any_completion_executor immediate_executor( + any_completion_handler_impl_base* impl, + const any_io_executor& candidate) const + { + return immediate_executor_fn_(impl, candidate); + } + + template <typename Handler> + static any_completion_executor impl(any_completion_handler_impl_base* impl, + const any_io_executor& candidate) + { + return static_cast<any_completion_handler_impl<Handler>*>( + impl)->immediate_executor(candidate); + } + +private: + type immediate_executor_fn_; +}; + +class any_completion_handler_allocate_fn +{ +public: + using type = void*(*)(any_completion_handler_impl_base*, + std::size_t, std::size_t); + + constexpr any_completion_handler_allocate_fn(type fn) + : allocate_fn_(fn) + { + } + + void* allocate(any_completion_handler_impl_base* impl, + std::size_t size, std::size_t align) const + { + return allocate_fn_(impl, size, align); + } + + template <typename Handler> + static void* impl(any_completion_handler_impl_base* impl, + std::size_t size, std::size_t align) + { + return static_cast<any_completion_handler_impl<Handler>*>(impl)->allocate( + size, align); + } + +private: + type allocate_fn_; +}; + +class any_completion_handler_deallocate_fn +{ +public: + using type = void(*)(any_completion_handler_impl_base*, + void*, std::size_t, std::size_t); + + constexpr any_completion_handler_deallocate_fn(type fn) + : deallocate_fn_(fn) + { + } + + void deallocate(any_completion_handler_impl_base* impl, + void* p, std::size_t size, std::size_t align) const + { + deallocate_fn_(impl, p, size, align); + } + + template <typename Handler> + static void impl(any_completion_handler_impl_base* impl, + void* p, std::size_t size, std::size_t align) + { + static_cast<any_completion_handler_impl<Handler>*>(impl)->deallocate( + p, size, align); + } + +private: + type deallocate_fn_; +}; + +template <typename... Signatures> +class any_completion_handler_fn_table + : private any_completion_handler_destroy_fn, + private any_completion_handler_executor_fn, + private any_completion_handler_immediate_executor_fn, + private any_completion_handler_allocate_fn, + private any_completion_handler_deallocate_fn, + private any_completion_handler_call_fns<Signatures...> +{ +public: + template <typename... CallFns> + constexpr any_completion_handler_fn_table( + any_completion_handler_destroy_fn::type destroy_fn, + any_completion_handler_executor_fn::type executor_fn, + any_completion_handler_immediate_executor_fn::type immediate_executor_fn, + any_completion_handler_allocate_fn::type allocate_fn, + any_completion_handler_deallocate_fn::type deallocate_fn, + CallFns... call_fns) + : any_completion_handler_destroy_fn(destroy_fn), + any_completion_handler_executor_fn(executor_fn), + any_completion_handler_immediate_executor_fn(immediate_executor_fn), + any_completion_handler_allocate_fn(allocate_fn), + any_completion_handler_deallocate_fn(deallocate_fn), + any_completion_handler_call_fns<Signatures...>(call_fns...) + { + } + + using any_completion_handler_destroy_fn::destroy; + using any_completion_handler_executor_fn::executor; + using any_completion_handler_immediate_executor_fn::immediate_executor; + using any_completion_handler_allocate_fn::allocate; + using any_completion_handler_deallocate_fn::deallocate; + using any_completion_handler_call_fns<Signatures...>::call; +}; + +template <typename Handler, typename... Signatures> +struct any_completion_handler_fn_table_instance +{ + static constexpr any_completion_handler_fn_table<Signatures...> + value = any_completion_handler_fn_table<Signatures...>( + &any_completion_handler_destroy_fn::impl<Handler>, + &any_completion_handler_executor_fn::impl<Handler>, + &any_completion_handler_immediate_executor_fn::impl<Handler>, + &any_completion_handler_allocate_fn::impl<Handler>, + &any_completion_handler_deallocate_fn::impl<Handler>, + &any_completion_handler_call_fn<Signatures>::template impl<Handler>...); +}; + +template <typename Handler, typename... Signatures> +constexpr any_completion_handler_fn_table<Signatures...> +any_completion_handler_fn_table_instance<Handler, Signatures...>::value; + +} // namespace detail + +template <typename... Signatures> +class any_completion_handler; + +/// An allocator type that forwards memory allocation operations through an +/// instance of @c any_completion_handler. +template <typename T, typename... Signatures> +class any_completion_handler_allocator +{ +private: + template <typename...> + friend class any_completion_handler; + + template <typename, typename...> + friend class any_completion_handler_allocator; + + const detail::any_completion_handler_fn_table<Signatures...>* fn_table_; + detail::any_completion_handler_impl_base* impl_; + + constexpr any_completion_handler_allocator(int, + const any_completion_handler<Signatures...>& h) noexcept + : fn_table_(h.fn_table_), + impl_(h.impl_) + { + } + +public: + /// The type of objects that may be allocated by the allocator. + typedef T value_type; + + /// Rebinds an allocator to another value type. + template <typename U> + struct rebind + { + /// Specifies the type of the rebound allocator. + typedef any_completion_handler_allocator<U, Signatures...> other; + }; + + /// Construct from another @c any_completion_handler_allocator. + template <typename U> + constexpr any_completion_handler_allocator( + const any_completion_handler_allocator<U, Signatures...>& a) + noexcept + : fn_table_(a.fn_table_), + impl_(a.impl_) + { + } + + /// Equality operator. + constexpr bool operator==( + const any_completion_handler_allocator& other) const noexcept + { + return fn_table_ == other.fn_table_ && impl_ == other.impl_; + } + + /// Inequality operator. + constexpr bool operator!=( + const any_completion_handler_allocator& other) const noexcept + { + return fn_table_ != other.fn_table_ || impl_ != other.impl_; + } + + /// Allocate space for @c n objects of the allocator's value type. + T* allocate(std::size_t n) const + { + if (fn_table_) + { + return static_cast<T*>( + fn_table_->allocate( + impl_, sizeof(T) * n, alignof(T))); + } + std::bad_alloc ex; + asio::detail::throw_exception(ex); + return nullptr; + } + + /// Deallocate space for @c n objects of the allocator's value type. + void deallocate(T* p, std::size_t n) const + { + fn_table_->deallocate(impl_, p, sizeof(T) * n, alignof(T)); + } +}; + +/// A protoco-allocator type that may be rebound to obtain an allocator that +/// forwards memory allocation operations through an instance of +/// @c any_completion_handler. +template <typename... Signatures> +class any_completion_handler_allocator<void, Signatures...> +{ +private: + template <typename...> + friend class any_completion_handler; + + template <typename, typename...> + friend class any_completion_handler_allocator; + + const detail::any_completion_handler_fn_table<Signatures...>* fn_table_; + detail::any_completion_handler_impl_base* impl_; + + constexpr any_completion_handler_allocator(int, + const any_completion_handler<Signatures...>& h) noexcept + : fn_table_(h.fn_table_), + impl_(h.impl_) + { + } + +public: + /// @c void as no objects can be allocated through a proto-allocator. + typedef void value_type; + + /// Rebinds an allocator to another value type. + template <typename U> + struct rebind + { + /// Specifies the type of the rebound allocator. + typedef any_completion_handler_allocator<U, Signatures...> other; + }; + + /// Construct from another @c any_completion_handler_allocator. + template <typename U> + constexpr any_completion_handler_allocator( + const any_completion_handler_allocator<U, Signatures...>& a) + noexcept + : fn_table_(a.fn_table_), + impl_(a.impl_) + { + } + + /// Equality operator. + constexpr bool operator==( + const any_completion_handler_allocator& other) const noexcept + { + return fn_table_ == other.fn_table_ && impl_ == other.impl_; + } + + /// Inequality operator. + constexpr bool operator!=( + const any_completion_handler_allocator& other) const noexcept + { + return fn_table_ != other.fn_table_ || impl_ != other.impl_; + } +}; + +/// Polymorphic wrapper for completion handlers. +/** + * The @c any_completion_handler class template is a polymorphic wrapper for + * completion handlers that propagates the associated executor, associated + * allocator, and associated cancellation slot through a type-erasing interface. + * + * When using @c any_completion_handler, specify one or more completion + * signatures as template parameters. These will dictate the arguments that may + * be passed to the handler through the polymorphic interface. + * + * Typical uses for @c any_completion_handler include: + * + * @li Separate compilation of asynchronous operation implementations. + * + * @li Enabling interoperability between asynchronous operations and virtual + * functions. + */ +template <typename... Signatures> +class any_completion_handler +{ +#if !defined(GENERATING_DOCUMENTATION) +private: + template <typename, typename...> + friend class any_completion_handler_allocator; + + template <typename, typename> + friend struct associated_executor; + + template <typename, typename> + friend struct associated_immediate_executor; + + const detail::any_completion_handler_fn_table<Signatures...>* fn_table_; + detail::any_completion_handler_impl_base* impl_; +#endif // !defined(GENERATING_DOCUMENTATION) + +public: + /// The associated allocator type. + using allocator_type = any_completion_handler_allocator<void, Signatures...>; + + /// The associated cancellation slot type. + using cancellation_slot_type = cancellation_slot; + + /// Construct an @c any_completion_handler in an empty state, without a target + /// object. + constexpr any_completion_handler() + : fn_table_(nullptr), + impl_(nullptr) + { + } + + /// Construct an @c any_completion_handler in an empty state, without a target + /// object. + constexpr any_completion_handler(nullptr_t) + : fn_table_(nullptr), + impl_(nullptr) + { + } + + /// Construct an @c any_completion_handler to contain the specified target. + template <typename H, typename Handler = decay_t<H>> + any_completion_handler(H&& h, + constraint_t< + !is_same<decay_t<H>, any_completion_handler>::value + > = 0) + : fn_table_( + &detail::any_completion_handler_fn_table_instance< + Handler, Signatures...>::value), + impl_(detail::any_completion_handler_impl<Handler>::create( + (get_associated_cancellation_slot)(h), static_cast<H&&>(h))) + { + } + + /// Move-construct an @c any_completion_handler from another. + /** + * After the operation, the moved-from object @c other has no target. + */ + any_completion_handler(any_completion_handler&& other) noexcept + : fn_table_(other.fn_table_), + impl_(other.impl_) + { + other.fn_table_ = nullptr; + other.impl_ = nullptr; + } + + /// Move-assign an @c any_completion_handler from another. + /** + * After the operation, the moved-from object @c other has no target. + */ + any_completion_handler& operator=( + any_completion_handler&& other) noexcept + { + any_completion_handler( + static_cast<any_completion_handler&&>(other)).swap(*this); + return *this; + } + + /// Assignment operator that sets the polymorphic wrapper to the empty state. + any_completion_handler& operator=(nullptr_t) noexcept + { + any_completion_handler().swap(*this); + return *this; + } + + /// Destructor. + ~any_completion_handler() + { + if (impl_) + fn_table_->destroy(impl_); + } + + /// Test if the polymorphic wrapper is empty. + constexpr explicit operator bool() const noexcept + { + return impl_ != nullptr; + } + + /// Test if the polymorphic wrapper is non-empty. + constexpr bool operator!() const noexcept + { + return impl_ == nullptr; + } + + /// Swap the content of an @c any_completion_handler with another. + void swap(any_completion_handler& other) noexcept + { + std::swap(fn_table_, other.fn_table_); + std::swap(impl_, other.impl_); + } + + /// Get the associated allocator. + allocator_type get_allocator() const noexcept + { + return allocator_type(0, *this); + } + + /// Get the associated cancellation slot. + cancellation_slot_type get_cancellation_slot() const noexcept + { + return impl_ ? impl_->get_cancellation_slot() : cancellation_slot_type(); + } + + /// Function call operator. + /** + * Invokes target completion handler with the supplied arguments. + * + * This function may only be called once, as the target handler is moved from. + * The polymorphic wrapper is left in an empty state. + * + * Throws @c std::bad_function_call if the polymorphic wrapper is empty. + */ + template <typename... Args> + auto operator()(Args&&... args) + -> decltype(fn_table_->call(impl_, static_cast<Args&&>(args)...)) + { + if (detail::any_completion_handler_impl_base* impl = impl_) + { + impl_ = nullptr; + return fn_table_->call(impl, static_cast<Args&&>(args)...); + } + std::bad_function_call ex; + asio::detail::throw_exception(ex); + } + + /// Equality operator. + friend constexpr bool operator==( + const any_completion_handler& a, nullptr_t) noexcept + { + return a.impl_ == nullptr; + } + + /// Equality operator. + friend constexpr bool operator==( + nullptr_t, const any_completion_handler& b) noexcept + { + return nullptr == b.impl_; + } + + /// Inequality operator. + friend constexpr bool operator!=( + const any_completion_handler& a, nullptr_t) noexcept + { + return a.impl_ != nullptr; + } + + /// Inequality operator. + friend constexpr bool operator!=( + nullptr_t, const any_completion_handler& b) noexcept + { + return nullptr != b.impl_; + } +}; + +template <typename... Signatures, typename Candidate> +struct associated_executor<any_completion_handler<Signatures...>, Candidate> +{ + using type = any_completion_executor; + + static type get(const any_completion_handler<Signatures...>& handler, + const Candidate& candidate = Candidate()) noexcept + { + any_completion_executor any_candidate(std::nothrow, candidate); + return handler.fn_table_ + ? handler.fn_table_->executor(handler.impl_, any_candidate) + : any_candidate; + } +}; + +template <typename... Signatures, typename Candidate> +struct associated_immediate_executor< + any_completion_handler<Signatures...>, Candidate> +{ + using type = any_completion_executor; + + static type get(const any_completion_handler<Signatures...>& handler, + const Candidate& candidate = Candidate()) noexcept + { + any_io_executor any_candidate(std::nothrow, candidate); + return handler.fn_table_ + ? handler.fn_table_->immediate_executor(handler.impl_, any_candidate) + : any_candidate; + } +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_ANY_COMPLETION_HANDLER_HPP diff --git a/3rdparty/asio/include/asio/any_io_executor.hpp b/3rdparty/asio/include/asio/any_io_executor.hpp index 5f2c13f014c..d35acf44ae3 100644 --- a/3rdparty/asio/include/asio/any_io_executor.hpp +++ b/3rdparty/asio/include/asio/any_io_executor.hpp @@ -2,7 +2,7 @@ // any_io_executor.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -87,30 +87,16 @@ public: #endif // !defined(GENERATING_DOCUMENTATION) /// Default constructor. - any_io_executor() ASIO_NOEXCEPT - : base_type() - { - } + ASIO_DECL any_io_executor() noexcept; /// Construct in an empty state. Equivalent effects to default constructor. - any_io_executor(nullptr_t) ASIO_NOEXCEPT - : base_type(nullptr_t()) - { - } + ASIO_DECL any_io_executor(nullptr_t) noexcept; /// Copy constructor. - any_io_executor(const any_io_executor& e) ASIO_NOEXCEPT - : base_type(static_cast<const base_type&>(e)) - { - } + ASIO_DECL any_io_executor(const any_io_executor& e) noexcept; -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. - any_io_executor(any_io_executor&& e) ASIO_NOEXCEPT - : base_type(static_cast<base_type&&>(e)) - { - } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + ASIO_DECL any_io_executor(any_io_executor&& e) noexcept; /// Construct to point to the same target as another any_executor. #if defined(GENERATING_DOCUMENTATION) @@ -119,8 +105,32 @@ public: #else // defined(GENERATING_DOCUMENTATION) template <typename OtherAnyExecutor> any_io_executor(OtherAnyExecutor e, - typename constraint< - conditional< + constraint_t< + conditional_t< + !is_same<OtherAnyExecutor, any_io_executor>::value + && is_base_of<execution::detail::any_executor_base, + OtherAnyExecutor>::value, + typename execution::detail::supportable_properties< + 0, supportable_properties_type>::template + is_valid_target<OtherAnyExecutor>, + false_type + >::value + > = 0) + : base_type(static_cast<OtherAnyExecutor&&>(e)) + { + } +#endif // defined(GENERATING_DOCUMENTATION) + + /// Construct to point to the same target as another any_executor. +#if defined(GENERATING_DOCUMENTATION) + template <class... OtherSupportableProperties> + any_io_executor(std::nothrow_t, + execution::any_executor<OtherSupportableProperties...> e); +#else // defined(GENERATING_DOCUMENTATION) + template <typename OtherAnyExecutor> + any_io_executor(std::nothrow_t, OtherAnyExecutor e, + constraint_t< + conditional_t< !is_same<OtherAnyExecutor, any_io_executor>::value && is_base_of<execution::detail::any_executor_base, OtherAnyExecutor>::value, @@ -128,13 +138,20 @@ public: 0, supportable_properties_type>::template is_valid_target<OtherAnyExecutor>, false_type - >::type::value - >::type = 0) - : base_type(ASIO_MOVE_CAST(OtherAnyExecutor)(e)) + >::value + > = 0) noexcept + : base_type(std::nothrow, static_cast<OtherAnyExecutor&&>(e)) { } #endif // defined(GENERATING_DOCUMENTATION) + /// Construct to point to the same target as another any_executor. + ASIO_DECL any_io_executor(std::nothrow_t, + const any_io_executor& e) noexcept; + + /// Construct to point to the same target as another any_executor. + ASIO_DECL any_io_executor(std::nothrow_t, any_io_executor&& e) noexcept; + /// Construct a polymorphic wrapper for the specified executor. #if defined(GENERATING_DOCUMENTATION) template <ASIO_EXECUTION_EXECUTOR Executor> @@ -142,54 +159,58 @@ public: #else // defined(GENERATING_DOCUMENTATION) template <ASIO_EXECUTION_EXECUTOR Executor> any_io_executor(Executor e, - typename constraint< - conditional< + constraint_t< + conditional_t< !is_same<Executor, any_io_executor>::value && !is_base_of<execution::detail::any_executor_base, Executor>::value, execution::detail::is_valid_target_executor< Executor, supportable_properties_type>, false_type - >::type::value - >::type = 0) - : base_type(ASIO_MOVE_CAST(Executor)(e)) + >::value + > = 0) + : base_type(static_cast<Executor&&>(e)) { } #endif // defined(GENERATING_DOCUMENTATION) - /// Assignment operator. - any_io_executor& operator=(const any_io_executor& e) ASIO_NOEXCEPT + /// Construct a polymorphic wrapper for the specified executor. +#if defined(GENERATING_DOCUMENTATION) + template <ASIO_EXECUTION_EXECUTOR Executor> + any_io_executor(std::nothrow_t, Executor e); +#else // defined(GENERATING_DOCUMENTATION) + template <ASIO_EXECUTION_EXECUTOR Executor> + any_io_executor(std::nothrow_t, Executor e, + constraint_t< + conditional_t< + !is_same<Executor, any_io_executor>::value + && !is_base_of<execution::detail::any_executor_base, + Executor>::value, + execution::detail::is_valid_target_executor< + Executor, supportable_properties_type>, + false_type + >::value + > = 0) noexcept + : base_type(std::nothrow, static_cast<Executor&&>(e)) { - base_type::operator=(static_cast<const base_type&>(e)); - return *this; } +#endif // defined(GENERATING_DOCUMENTATION) + + /// Assignment operator. + ASIO_DECL any_io_executor& operator=( + const any_io_executor& e) noexcept; -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move assignment operator. - any_io_executor& operator=(any_io_executor&& e) ASIO_NOEXCEPT - { - base_type::operator=(static_cast<base_type&&>(e)); - return *this; - } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + ASIO_DECL any_io_executor& operator=(any_io_executor&& e) noexcept; /// Assignment operator that sets the polymorphic wrapper to the empty state. - any_io_executor& operator=(nullptr_t) - { - base_type::operator=(nullptr_t()); - return *this; - } + ASIO_DECL any_io_executor& operator=(nullptr_t); /// Destructor. - ~any_io_executor() - { - } + ASIO_DECL ~any_io_executor(); /// Swap targets with another polymorphic wrapper. - void swap(any_io_executor& other) ASIO_NOEXCEPT - { - static_cast<base_type&>(*this).swap(static_cast<base_type&>(other)); - } + ASIO_DECL void swap(any_io_executor& other) noexcept; /// Obtain a polymorphic wrapper with the specified property. /** @@ -202,9 +223,9 @@ public: */ template <typename Property> any_io_executor require(const Property& p, - typename constraint< + constraint_t< traits::require_member<const base_type&, const Property&>::is_valid - >::type = 0) const + > = 0) const { return static_cast<const base_type&>(*this).require(p); } @@ -220,9 +241,9 @@ public: */ template <typename Property> any_io_executor prefer(const Property& p, - typename constraint< + constraint_t< traits::prefer_member<const base_type&, const Property&>::is_valid - >::type = 0) const + > = 0) const { return static_cast<const base_type&>(*this).prefer(p); } @@ -230,6 +251,30 @@ public: #if !defined(GENERATING_DOCUMENTATION) +template <> +ASIO_DECL any_io_executor any_io_executor::require( + const execution::blocking_t::never_t&, int) const; + +template <> +ASIO_DECL any_io_executor any_io_executor::prefer( + const execution::blocking_t::possibly_t&, int) const; + +template <> +ASIO_DECL any_io_executor any_io_executor::prefer( + const execution::outstanding_work_t::tracked_t&, int) const; + +template <> +ASIO_DECL any_io_executor any_io_executor::prefer( + const execution::outstanding_work_t::untracked_t&, int) const; + +template <> +ASIO_DECL any_io_executor any_io_executor::prefer( + const execution::relationship_t::fork_t&, int) const; + +template <> +ASIO_DECL any_io_executor any_io_executor::prefer( + const execution::relationship_t::continuation_t&, int) const; + namespace traits { #if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) @@ -297,4 +342,10 @@ struct prefer_member<any_io_executor, Prop> : #include "asio/detail/pop_options.hpp" +#if defined(ASIO_HEADER_ONLY) \ + && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) +# include "asio/impl/any_io_executor.ipp" +#endif // defined(ASIO_HEADER_ONLY) + // && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) + #endif // ASIO_ANY_IO_EXECUTOR_HPP diff --git a/3rdparty/asio/include/asio/append.hpp b/3rdparty/asio/include/asio/append.hpp new file mode 100644 index 00000000000..04608924280 --- /dev/null +++ b/3rdparty/asio/include/asio/append.hpp @@ -0,0 +1,65 @@ +// +// append.hpp +// ~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_APPEND_HPP +#define ASIO_APPEND_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <tuple> +#include "asio/detail/type_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Completion token type used to specify that the completion handler +/// arguments should be passed additional values after the results of the +/// operation. +template <typename CompletionToken, typename... Values> +class append_t +{ +public: + /// Constructor. + template <typename T, typename... V> + constexpr explicit append_t(T&& completion_token, V&&... values) + : token_(static_cast<T&&>(completion_token)), + values_(static_cast<V&&>(values)...) + { + } + +//private: + CompletionToken token_; + std::tuple<Values...> values_; +}; + +/// Completion token type used to specify that the completion handler +/// arguments should be passed additional values after the results of the +/// operation. +template <typename CompletionToken, typename... Values> +ASIO_NODISCARD inline constexpr +append_t<decay_t<CompletionToken>, decay_t<Values>...> +append(CompletionToken&& completion_token, Values&&... values) +{ + return append_t<decay_t<CompletionToken>, decay_t<Values>...>( + static_cast<CompletionToken&&>(completion_token), + static_cast<Values&&>(values)...); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/impl/append.hpp" + +#endif // ASIO_APPEND_HPP diff --git a/3rdparty/asio/include/asio/as_tuple.hpp b/3rdparty/asio/include/asio/as_tuple.hpp new file mode 100644 index 00000000000..60008bda5c2 --- /dev/null +++ b/3rdparty/asio/include/asio/as_tuple.hpp @@ -0,0 +1,126 @@ +// +// as_tuple.hpp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_AS_TUPLE_HPP +#define ASIO_AS_TUPLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/type_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// A @ref completion_token adapter used to specify that the completion handler +/// arguments should be combined into a single tuple argument. +/** + * The as_tuple_t class is used to indicate that any arguments to the + * completion handler should be combined and passed as a single tuple argument. + * The arguments are first moved into a @c std::tuple and that tuple is then + * passed to the completion handler. + */ +template <typename CompletionToken> +class as_tuple_t +{ +public: + /// Tag type used to prevent the "default" constructor from being used for + /// conversions. + struct default_constructor_tag {}; + + /// Default constructor. + /** + * This constructor is only valid if the underlying completion token is + * default constructible and move constructible. The underlying completion + * token is itself defaulted as an argument to allow it to capture a source + * location. + */ + constexpr as_tuple_t( + default_constructor_tag = default_constructor_tag(), + CompletionToken token = CompletionToken()) + : token_(static_cast<CompletionToken&&>(token)) + { + } + + /// Constructor. + template <typename T> + constexpr explicit as_tuple_t( + T&& completion_token) + : token_(static_cast<T&&>(completion_token)) + { + } + + /// Adapts an executor to add the @c as_tuple_t completion token as the + /// default. + template <typename InnerExecutor> + struct executor_with_default : InnerExecutor + { + /// Specify @c as_tuple_t as the default completion token type. + typedef as_tuple_t default_completion_token_type; + + /// Construct the adapted executor from the inner executor type. + template <typename InnerExecutor1> + executor_with_default(const InnerExecutor1& ex, + constraint_t< + conditional_t< + !is_same<InnerExecutor1, executor_with_default>::value, + is_convertible<InnerExecutor1, InnerExecutor>, + false_type + >::value + > = 0) noexcept + : InnerExecutor(ex) + { + } + }; + + /// Type alias to adapt an I/O object to use @c as_tuple_t as its + /// default completion token type. + template <typename T> + using as_default_on_t = typename T::template rebind_executor< + executor_with_default<typename T::executor_type>>::other; + + /// Function helper to adapt an I/O object to use @c as_tuple_t as its + /// default completion token type. + template <typename T> + static typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> + >::other + as_default_on(T&& object) + { + return typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> + >::other(static_cast<T&&>(object)); + } + +//private: + CompletionToken token_; +}; + +/// Adapt a @ref completion_token to specify that the completion handler +/// arguments should be combined into a single tuple argument. +template <typename CompletionToken> +ASIO_NODISCARD inline +constexpr as_tuple_t<decay_t<CompletionToken>> +as_tuple(CompletionToken&& completion_token) +{ + return as_tuple_t<decay_t<CompletionToken>>( + static_cast<CompletionToken&&>(completion_token)); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/impl/as_tuple.hpp" + +#endif // ASIO_AS_TUPLE_HPP diff --git a/3rdparty/asio/include/asio/associated_allocator.hpp b/3rdparty/asio/include/asio/associated_allocator.hpp index 3f945834a95..f21ea250efb 100644 --- a/3rdparty/asio/include/asio/associated_allocator.hpp +++ b/3rdparty/asio/include/asio/associated_allocator.hpp @@ -2,7 +2,7 @@ // associated_allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -36,43 +36,54 @@ struct has_allocator_type : false_type }; template <typename T> -struct has_allocator_type<T, - typename void_type<typename T::executor_type>::type> - : true_type +struct has_allocator_type<T, void_t<typename T::allocator_type>> : true_type { }; -template <typename T, typename E, typename = void, typename = void> +template <typename T, typename A, typename = void, typename = void> struct associated_allocator_impl { - typedef E type; + typedef void asio_associated_allocator_is_unspecialised; - static type get(const T&, const E& e) ASIO_NOEXCEPT + typedef A type; + + static type get(const T&) noexcept + { + return type(); + } + + static const type& get(const T&, const A& a) noexcept { - return e; + return a; } }; -template <typename T, typename E> -struct associated_allocator_impl<T, E, - typename void_type<typename T::allocator_type>::type> +template <typename T, typename A> +struct associated_allocator_impl<T, A, void_t<typename T::allocator_type>> { typedef typename T::allocator_type type; - static type get(const T& t, const E&) ASIO_NOEXCEPT + static auto get(const T& t) noexcept + -> decltype(t.get_allocator()) + { + return t.get_allocator(); + } + + static auto get(const T& t, const A&) noexcept + -> decltype(t.get_allocator()) { return t.get_allocator(); } }; -template <typename T, typename E> -struct associated_allocator_impl<T, E, - typename enable_if< +template <typename T, typename A> +struct associated_allocator_impl<T, A, + enable_if_t< !has_allocator_type<T>::value - >::type, - typename void_type< - typename associator<associated_allocator, T, E>::type - >::type> : associator<associated_allocator, T, E> + >, + void_t< + typename associator<associated_allocator, T, A>::type + >> : associator<associated_allocator, T, A> { }; @@ -92,29 +103,32 @@ struct associated_allocator_impl<T, E, * Allocator requirements. * * @li Provide a noexcept static member function named @c get, callable as @c - * get(t) and with return type @c type. + * get(t) and with return type @c type or a (possibly const) reference to @c + * type. * * @li Provide a noexcept static member function named @c get, callable as @c - * get(t,a) and with return type @c type. + * get(t,a) and with return type @c type or a (possibly const) reference to @c + * type. */ -template <typename T, typename Allocator = std::allocator<void> > +template <typename T, typename Allocator = std::allocator<void>> struct associated_allocator +#if !defined(GENERATING_DOCUMENTATION) + : detail::associated_allocator_impl<T, Allocator> +#endif // !defined(GENERATING_DOCUMENTATION) { +#if defined(GENERATING_DOCUMENTATION) /// If @c T has a nested type @c allocator_type, <tt>T::allocator_type</tt>. /// Otherwise @c Allocator. -#if defined(GENERATING_DOCUMENTATION) typedef see_below type; -#else // defined(GENERATING_DOCUMENTATION) - typedef typename detail::associated_allocator_impl<T, Allocator>::type type; -#endif // defined(GENERATING_DOCUMENTATION) + + /// If @c T has a nested type @c allocator_type, returns + /// <tt>t.get_allocator()</tt>. Otherwise returns @c type(). + static decltype(auto) get(const T& t) noexcept; /// If @c T has a nested type @c allocator_type, returns /// <tt>t.get_allocator()</tt>. Otherwise returns @c a. - static type get(const T& t, - const Allocator& a = Allocator()) ASIO_NOEXCEPT - { - return detail::associated_allocator_impl<T, Allocator>::get(t, a); - } + static decltype(auto) get(const T& t, const Allocator& a) noexcept; +#endif // defined(GENERATING_DOCUMENTATION) }; /// Helper function to obtain an object's associated allocator. @@ -122,8 +136,8 @@ struct 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) ASIO_NOEXCEPT +ASIO_NODISCARD inline typename associated_allocator<T>::type +get_associated_allocator(const T& t) noexcept { return associated_allocator<T>::get(t); } @@ -133,26 +147,45 @@ get_associated_allocator(const T& t) ASIO_NOEXCEPT * @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) ASIO_NOEXCEPT +ASIO_NODISCARD inline auto get_associated_allocator( + const T& t, const Allocator& a) noexcept + -> decltype(associated_allocator<T, Allocator>::get(t, a)) { return associated_allocator<T, Allocator>::get(t, a); } -#if defined(ASIO_HAS_ALIAS_TEMPLATES) - -template <typename T, typename Allocator = std::allocator<void> > +template <typename T, typename Allocator = std::allocator<void>> using associated_allocator_t = typename associated_allocator<T, Allocator>::type; -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) +namespace detail { + +template <typename T, typename A, typename = void> +struct associated_allocator_forwarding_base +{ +}; -#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \ - || defined(GENERATING_DOCUMENTATION) +template <typename T, typename A> +struct associated_allocator_forwarding_base<T, A, + enable_if_t< + is_same< + typename associated_allocator<T, + A>::asio_associated_allocator_is_unspecialised, + void + >::value + >> +{ + typedef void asio_associated_allocator_is_unspecialised; +}; + +} // namespace detail /// Specialisation of associated_allocator for @c std::reference_wrapper. template <typename T, typename Allocator> struct associated_allocator<reference_wrapper<T>, Allocator> +#if !defined(GENERATING_DOCUMENTATION) + : detail::associated_allocator_forwarding_base<T, Allocator> +#endif // !defined(GENERATING_DOCUMENTATION) { /// Forwards @c type to the associator specialisation for the unwrapped type /// @c T. @@ -160,16 +193,20 @@ struct associated_allocator<reference_wrapper<T>, Allocator> /// Forwards the request to get the allocator to the associator specialisation /// for the unwrapped type @c T. - static type get(reference_wrapper<T> t, - const Allocator& a = Allocator()) ASIO_NOEXCEPT + static type get(reference_wrapper<T> t) noexcept + { + return associated_allocator<T, Allocator>::get(t.get()); + } + + /// Forwards the request to get the allocator to the associator specialisation + /// for the unwrapped type @c T. + static auto get(reference_wrapper<T> t, const Allocator& a) noexcept + -> decltype(associated_allocator<T, Allocator>::get(t.get(), a)) { return associated_allocator<T, Allocator>::get(t.get(), a); } }; -#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER) - // || defined(GENERATING_DOCUMENTATION) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/associated_cancellation_slot.hpp b/3rdparty/asio/include/asio/associated_cancellation_slot.hpp index 6a809e71104..518bd881eaf 100644 --- a/3rdparty/asio/include/asio/associated_cancellation_slot.hpp +++ b/3rdparty/asio/include/asio/associated_cancellation_slot.hpp @@ -2,7 +2,7 @@ // associated_cancellation_slot.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include "asio/associator.hpp" #include "asio/cancellation_signal.hpp" +#include "asio/detail/functional.hpp" #include "asio/detail/type_traits.hpp" #include "asio/detail/push_options.hpp" @@ -35,9 +36,8 @@ struct has_cancellation_slot_type : false_type }; template <typename T> -struct has_cancellation_slot_type<T, - typename void_type<typename T::cancellation_slot_type>::type> - : true_type +struct has_cancellation_slot_type<T, void_t<typename T::cancellation_slot_type>> + : true_type { }; @@ -48,7 +48,12 @@ struct associated_cancellation_slot_impl typedef S type; - static type get(const T&, const S& s = S()) ASIO_NOEXCEPT + static type get(const T&) noexcept + { + return type(); + } + + static const type& get(const T&, const S& s) noexcept { return s; } @@ -56,11 +61,18 @@ struct associated_cancellation_slot_impl template <typename T, typename S> struct associated_cancellation_slot_impl<T, S, - typename void_type<typename T::cancellation_slot_type>::type> + void_t<typename T::cancellation_slot_type>> { typedef typename T::cancellation_slot_type type; - static type get(const T& t, const S& = S()) ASIO_NOEXCEPT + static auto get(const T& t) noexcept + -> decltype(t.get_cancellation_slot()) + { + return t.get_cancellation_slot(); + } + + static auto get(const T& t, const S&) noexcept + -> decltype(t.get_cancellation_slot()) { return t.get_cancellation_slot(); } @@ -68,12 +80,12 @@ struct associated_cancellation_slot_impl<T, S, template <typename T, typename S> struct associated_cancellation_slot_impl<T, S, - typename enable_if< + enable_if_t< !has_cancellation_slot_type<T>::value - >::type, - typename void_type< + >, + void_t< typename associator<associated_cancellation_slot, T, S>::type - >::type> : associator<associated_cancellation_slot, T, S> + >> : associator<associated_cancellation_slot, T, S> { }; @@ -93,10 +105,12 @@ struct associated_cancellation_slot_impl<T, S, * CancellationSlot requirements. * * @li Provide a noexcept static member function named @c get, callable as @c - * get(t) and with return type @c type. + * get(t) and with return type @c type or a (possibly const) reference to @c + * type. * * @li Provide a noexcept static member function named @c get, callable as @c - * get(t,s) and with return type @c type. + * get(t,s) and with return type @c type or a (possibly const) reference to @c + * type. */ template <typename T, typename CancellationSlot = cancellation_slot> struct associated_cancellation_slot @@ -111,9 +125,13 @@ struct associated_cancellation_slot typedef see_below type; /// If @c T has a nested type @c cancellation_slot_type, returns + /// <tt>t.get_cancellation_slot()</tt>. Otherwise returns @c type(). + static decltype(auto) get(const T& t) noexcept; + + /// If @c T has a nested type @c cancellation_slot_type, returns /// <tt>t.get_cancellation_slot()</tt>. Otherwise returns @c s. - static type get(const T& t, - const CancellationSlot& s = CancellationSlot()) ASIO_NOEXCEPT; + static decltype(auto) get(const T& t, + const CancellationSlot& s) noexcept; #endif // defined(GENERATING_DOCUMENTATION) }; @@ -122,8 +140,8 @@ struct associated_cancellation_slot * @returns <tt>associated_cancellation_slot<T>::get(t)</tt> */ template <typename T> -inline typename associated_cancellation_slot<T>::type -get_associated_cancellation_slot(const T& t) ASIO_NOEXCEPT +ASIO_NODISCARD inline typename associated_cancellation_slot<T>::type +get_associated_cancellation_slot(const T& t) noexcept { return associated_cancellation_slot<T>::get(t); } @@ -134,21 +152,17 @@ get_associated_cancellation_slot(const T& t) ASIO_NOEXCEPT * CancellationSlot>::get(t, st)</tt> */ template <typename T, typename CancellationSlot> -inline typename associated_cancellation_slot<T, CancellationSlot>::type -get_associated_cancellation_slot(const T& t, - const CancellationSlot& st) ASIO_NOEXCEPT +ASIO_NODISCARD inline auto get_associated_cancellation_slot( + const T& t, const CancellationSlot& st) noexcept + -> decltype(associated_cancellation_slot<T, CancellationSlot>::get(t, st)) { return associated_cancellation_slot<T, CancellationSlot>::get(t, st); } -#if defined(ASIO_HAS_ALIAS_TEMPLATES) - template <typename T, typename CancellationSlot = cancellation_slot> using associated_cancellation_slot_t = typename associated_cancellation_slot<T, CancellationSlot>::type; -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - namespace detail { template <typename T, typename S, typename = void> @@ -158,18 +172,48 @@ struct associated_cancellation_slot_forwarding_base template <typename T, typename S> struct associated_cancellation_slot_forwarding_base<T, S, - typename enable_if< + enable_if_t< is_same< typename associated_cancellation_slot<T, S>::asio_associated_cancellation_slot_is_unspecialised, void >::value - >::type> + >> { typedef void asio_associated_cancellation_slot_is_unspecialised; }; } // namespace detail + +/// Specialisation of associated_cancellation_slot for @c +/// std::reference_wrapper. +template <typename T, typename CancellationSlot> +struct associated_cancellation_slot<reference_wrapper<T>, CancellationSlot> +#if !defined(GENERATING_DOCUMENTATION) + : detail::associated_cancellation_slot_forwarding_base<T, CancellationSlot> +#endif // !defined(GENERATING_DOCUMENTATION) +{ + /// Forwards @c type to the associator specialisation for the unwrapped type + /// @c T. + typedef typename associated_cancellation_slot<T, CancellationSlot>::type type; + + /// Forwards the request to get the cancellation slot to the associator + /// specialisation for the unwrapped type @c T. + static type get(reference_wrapper<T> t) noexcept + { + return associated_cancellation_slot<T, CancellationSlot>::get(t.get()); + } + + /// Forwards the request to get the cancellation slot to the associator + /// specialisation for the unwrapped type @c T. + static auto get(reference_wrapper<T> t, const CancellationSlot& s) noexcept + -> decltype( + associated_cancellation_slot<T, CancellationSlot>::get(t.get(), s)) + { + return associated_cancellation_slot<T, CancellationSlot>::get(t.get(), s); + } +}; + } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/associated_executor.hpp b/3rdparty/asio/include/asio/associated_executor.hpp index 1e62e37a12e..4ca7ba149e9 100644 --- a/3rdparty/asio/include/asio/associated_executor.hpp +++ b/3rdparty/asio/include/asio/associated_executor.hpp @@ -2,7 +2,7 @@ // associated_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -38,8 +38,7 @@ struct has_executor_type : false_type }; template <typename T> -struct has_executor_type<T, - typename void_type<typename T::executor_type>::type> +struct has_executor_type<T, void_t<typename T::executor_type>> : true_type { }; @@ -51,19 +50,30 @@ struct associated_executor_impl typedef E type; - static type get(const T&, const E& e = E()) ASIO_NOEXCEPT + static type get(const T&) noexcept + { + return type(); + } + + static const type& get(const T&, const E& e) noexcept { return e; } }; template <typename T, typename E> -struct associated_executor_impl<T, E, - typename void_type<typename T::executor_type>::type> +struct associated_executor_impl<T, E, void_t<typename T::executor_type>> { typedef typename T::executor_type type; - static type get(const T& t, const E& = E()) ASIO_NOEXCEPT + static auto get(const T& t) noexcept + -> decltype(t.get_executor()) + { + return t.get_executor(); + } + + static auto get(const T& t, const E&) noexcept + -> decltype(t.get_executor()) { return t.get_executor(); } @@ -71,12 +81,12 @@ struct associated_executor_impl<T, E, template <typename T, typename E> struct associated_executor_impl<T, E, - typename enable_if< + enable_if_t< !has_executor_type<T>::value - >::type, - typename void_type< + >, + void_t< typename associator<associated_executor, T, E>::type - >::type> : associator<associated_executor, T, E> + >> : associator<associated_executor, T, E> { }; @@ -96,10 +106,12 @@ struct associated_executor_impl<T, E, * Executor requirements. * * @li Provide a noexcept static member function named @c get, callable as @c - * get(t) and with return type @c type. + * get(t) and with return type @c type or a (possibly const) reference to @c + * type. * * @li Provide a noexcept static member function named @c get, callable as @c - * get(t,e) and with return type @c type. + * get(t,e) and with return type @c type or a (possibly const) reference to @c + * type. */ template <typename T, typename Executor = system_executor> struct associated_executor @@ -113,9 +125,12 @@ struct associated_executor typedef see_below type; /// If @c T has a nested type @c executor_type, returns + /// <tt>t.get_executor()</tt>. Otherwise returns @c type(). + static decltype(auto) get(const T& t) noexcept; + + /// If @c T has a nested type @c executor_type, returns /// <tt>t.get_executor()</tt>. Otherwise returns @c ex. - static type get(const T& t, - const Executor& ex = Executor()) ASIO_NOEXCEPT; + static decltype(auto) get(const T& t, const Executor& ex) noexcept; #endif // defined(GENERATING_DOCUMENTATION) }; @@ -124,8 +139,8 @@ struct 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) ASIO_NOEXCEPT +ASIO_NODISCARD inline typename associated_executor<T>::type +get_associated_executor(const T& t) noexcept { return associated_executor<T>::get(t); } @@ -135,11 +150,12 @@ get_associated_executor(const T& t) ASIO_NOEXCEPT * @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 constraint< +ASIO_NODISCARD inline auto get_associated_executor( + const T& t, const Executor& ex, + constraint_t< is_executor<Executor>::value || execution::is_executor<Executor>::value - >::type = 0) ASIO_NOEXCEPT + > = 0) noexcept + -> decltype(associated_executor<T, Executor>::get(t, ex)) { return associated_executor<T, Executor>::get(t, ex); } @@ -150,23 +166,19 @@ get_associated_executor(const T& t, const Executor& ex, * ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt> */ template <typename T, typename ExecutionContext> -inline typename associated_executor<T, - typename ExecutionContext::executor_type>::type +ASIO_NODISCARD inline typename associated_executor<T, + typename ExecutionContext::executor_type>::type get_associated_executor(const T& t, ExecutionContext& ctx, - typename constraint<is_convertible<ExecutionContext&, - execution_context&>::value>::type = 0) ASIO_NOEXCEPT + constraint_t<is_convertible<ExecutionContext&, + execution_context&>::value> = 0) noexcept { return associated_executor<T, typename ExecutionContext::executor_type>::get(t, ctx.get_executor()); } -#if defined(ASIO_HAS_ALIAS_TEMPLATES) - template <typename T, typename Executor = system_executor> using associated_executor_t = typename associated_executor<T, Executor>::type; -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - namespace detail { template <typename T, typename E, typename = void> @@ -176,22 +188,19 @@ struct associated_executor_forwarding_base template <typename T, typename E> struct associated_executor_forwarding_base<T, E, - typename enable_if< + enable_if_t< is_same< typename associated_executor<T, E>::asio_associated_executor_is_unspecialised, void >::value - >::type> + >> { typedef void asio_associated_executor_is_unspecialised; }; } // namespace detail -#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \ - || defined(GENERATING_DOCUMENTATION) - /// Specialisation of associated_executor for @c std::reference_wrapper. template <typename T, typename Executor> struct associated_executor<reference_wrapper<T>, Executor> @@ -205,16 +214,20 @@ struct associated_executor<reference_wrapper<T>, Executor> /// Forwards the request to get the executor to the associator specialisation /// for the unwrapped type @c T. - static type get(reference_wrapper<T> t, - const Executor& ex = Executor()) ASIO_NOEXCEPT + static type get(reference_wrapper<T> t) noexcept + { + return associated_executor<T, Executor>::get(t.get()); + } + + /// Forwards the request to get the executor to the associator specialisation + /// for the unwrapped type @c T. + static auto get(reference_wrapper<T> t, const Executor& ex) noexcept + -> decltype(associated_executor<T, Executor>::get(t.get(), ex)) { return associated_executor<T, Executor>::get(t.get(), ex); } }; -#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER) - // || defined(GENERATING_DOCUMENTATION) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/associated_immediate_executor.hpp b/3rdparty/asio/include/asio/associated_immediate_executor.hpp new file mode 100644 index 00000000000..aa6e0fcfee7 --- /dev/null +++ b/3rdparty/asio/include/asio/associated_immediate_executor.hpp @@ -0,0 +1,280 @@ +// +// associated_immediate_executor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_ASSOCIATED_IMMEDIATE_EXECUTOR_HPP +#define ASIO_ASSOCIATED_IMMEDIATE_EXECUTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/associator.hpp" +#include "asio/detail/functional.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/execution/blocking.hpp" +#include "asio/execution/executor.hpp" +#include "asio/execution_context.hpp" +#include "asio/is_executor.hpp" +#include "asio/require.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +template <typename T, typename Executor> +struct associated_immediate_executor; + +namespace detail { + +template <typename T, typename = void> +struct has_immediate_executor_type : false_type +{ +}; + +template <typename T> +struct has_immediate_executor_type<T, + void_t<typename T::immediate_executor_type>> + : true_type +{ +}; + +template <typename E, typename = void, typename = void> +struct default_immediate_executor +{ + typedef require_result_t<E, execution::blocking_t::never_t> type; + + static type get(const E& e) noexcept + { + return asio::require(e, execution::blocking.never); + } +}; + +template <typename E> +struct default_immediate_executor<E, + enable_if_t< + !execution::is_executor<E>::value + >, + enable_if_t< + is_executor<E>::value + >> +{ + class type : public E + { + public: + template <typename Executor1> + explicit type(const Executor1& e, + constraint_t< + conditional_t< + !is_same<Executor1, type>::value, + is_convertible<Executor1, E>, + false_type + >::value + > = 0) noexcept + : E(e) + { + } + + type(const type& other) noexcept + : E(static_cast<const E&>(other)) + { + } + + type(type&& other) noexcept + : E(static_cast<E&&>(other)) + { + } + + template <typename Function, typename Allocator> + void dispatch(Function&& f, const Allocator& a) const + { + this->post(static_cast<Function&&>(f), a); + } + + friend bool operator==(const type& a, const type& b) noexcept + { + return static_cast<const E&>(a) == static_cast<const E&>(b); + } + + friend bool operator!=(const type& a, const type& b) noexcept + { + return static_cast<const E&>(a) != static_cast<const E&>(b); + } + }; + + static type get(const E& e) noexcept + { + return type(e); + } +}; + +template <typename T, typename E, typename = void, typename = void> +struct associated_immediate_executor_impl +{ + typedef void asio_associated_immediate_executor_is_unspecialised; + + typedef typename default_immediate_executor<E>::type type; + + static auto get(const T&, const E& e) noexcept + -> decltype(default_immediate_executor<E>::get(e)) + { + return default_immediate_executor<E>::get(e); + } +}; + +template <typename T, typename E> +struct associated_immediate_executor_impl<T, E, + void_t<typename T::immediate_executor_type>> +{ + typedef typename T::immediate_executor_type type; + + static auto get(const T& t, const E&) noexcept + -> decltype(t.get_immediate_executor()) + { + return t.get_immediate_executor(); + } +}; + +template <typename T, typename E> +struct associated_immediate_executor_impl<T, E, + enable_if_t< + !has_immediate_executor_type<T>::value + >, + void_t< + typename associator<associated_immediate_executor, T, E>::type + >> : associator<associated_immediate_executor, T, E> +{ +}; + +} // namespace detail + +/// Traits type used to obtain the immediate executor associated with an object. +/** + * A program may specialise this traits type if the @c T template parameter in + * the specialisation is a user-defined type. The template parameter @c + * Executor shall be a type meeting the Executor requirements. + * + * Specialisations shall meet the following requirements, where @c t is a const + * reference to an object of type @c T, and @c e is an object of type @c + * Executor. + * + * @li Provide a nested typedef @c type that identifies a type meeting the + * Executor requirements. + * + * @li Provide a noexcept static member function named @c get, callable as @c + * get(t) and with return type @c type or a (possibly const) reference to @c + * type. + * + * @li Provide a noexcept static member function named @c get, callable as @c + * get(t,e) and with return type @c type or a (possibly const) reference to @c + * type. + */ +template <typename T, typename Executor> +struct associated_immediate_executor +#if !defined(GENERATING_DOCUMENTATION) + : detail::associated_immediate_executor_impl<T, Executor> +#endif // !defined(GENERATING_DOCUMENTATION) +{ +#if defined(GENERATING_DOCUMENTATION) + /// If @c T has a nested type @c immediate_executor_type, + // <tt>T::immediate_executor_type</tt>. Otherwise @c Executor. + typedef see_below type; + + /// If @c T has a nested type @c immediate_executor_type, returns + /// <tt>t.get_immediate_executor()</tt>. Otherwise returns + /// <tt>asio::require(ex, asio::execution::blocking.never)</tt>. + static decltype(auto) get(const T& t, const Executor& ex) noexcept; +#endif // defined(GENERATING_DOCUMENTATION) +}; + +/// Helper function to obtain an object's associated executor. +/** + * @returns <tt>associated_immediate_executor<T, Executor>::get(t, ex)</tt> + */ +template <typename T, typename Executor> +ASIO_NODISCARD inline auto get_associated_immediate_executor( + const T& t, const Executor& ex, + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + > = 0) noexcept + -> decltype(associated_immediate_executor<T, Executor>::get(t, ex)) +{ + return associated_immediate_executor<T, Executor>::get(t, ex); +} + +/// Helper function to obtain an object's associated executor. +/** + * @returns <tt>associated_immediate_executor<T, typename + * ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt> + */ +template <typename T, typename ExecutionContext> +ASIO_NODISCARD inline typename associated_immediate_executor<T, + typename ExecutionContext::executor_type>::type +get_associated_immediate_executor(const T& t, ExecutionContext& ctx, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) noexcept +{ + return associated_immediate_executor<T, + typename ExecutionContext::executor_type>::get(t, ctx.get_executor()); +} + +template <typename T, typename Executor> +using associated_immediate_executor_t = + typename associated_immediate_executor<T, Executor>::type; + +namespace detail { + +template <typename T, typename E, typename = void> +struct associated_immediate_executor_forwarding_base +{ +}; + +template <typename T, typename E> +struct associated_immediate_executor_forwarding_base<T, E, + enable_if_t< + is_same< + typename associated_immediate_executor<T, + E>::asio_associated_immediate_executor_is_unspecialised, + void + >::value + >> +{ + typedef void asio_associated_immediate_executor_is_unspecialised; +}; + +} // namespace detail + +/// Specialisation of associated_immediate_executor for +/// @c std::reference_wrapper. +template <typename T, typename Executor> +struct associated_immediate_executor<reference_wrapper<T>, Executor> +#if !defined(GENERATING_DOCUMENTATION) + : detail::associated_immediate_executor_forwarding_base<T, Executor> +#endif // !defined(GENERATING_DOCUMENTATION) +{ + /// Forwards @c type to the associator specialisation for the unwrapped type + /// @c T. + typedef typename associated_immediate_executor<T, Executor>::type type; + + /// Forwards the request to get the executor to the associator specialisation + /// for the unwrapped type @c T. + static auto get(reference_wrapper<T> t, const Executor& ex) noexcept + -> decltype(associated_immediate_executor<T, Executor>::get(t.get(), ex)) + { + return associated_immediate_executor<T, Executor>::get(t.get(), ex); + } +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_ASSOCIATED_IMMEDIATE_EXECUTOR_HPP diff --git a/3rdparty/asio/include/asio/associator.hpp b/3rdparty/asio/include/asio/associator.hpp index 0f93b120623..7952fcc51ba 100644 --- a/3rdparty/asio/include/asio/associator.hpp +++ b/3rdparty/asio/include/asio/associator.hpp @@ -2,7 +2,7 @@ // associator.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/async_result.hpp b/3rdparty/asio/include/asio/async_result.hpp index 1750e19e3a4..cdae9ede687 100644 --- a/3rdparty/asio/include/asio/async_result.hpp +++ b/3rdparty/asio/include/asio/async_result.hpp @@ -2,7 +2,7 @@ // async_result.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,15 +17,12 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" #include "asio/detail/push_options.hpp" namespace asio { -#if defined(ASIO_HAS_CONCEPTS) \ - && defined(ASIO_HAS_VARIADIC_TEMPLATES) \ - && defined(ASIO_HAS_DECLTYPE) +#if defined(ASIO_HAS_CONCEPTS) namespace detail { @@ -39,8 +36,6 @@ struct is_completion_signature<R(Args...)> : true_type { }; -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - template <typename R, typename... Args> struct is_completion_signature<R(Args...) &> : true_type { @@ -69,7 +64,6 @@ struct is_completion_signature<R(Args...) && noexcept> : true_type }; # endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) template <typename... T> struct are_completion_signatures : false_type @@ -103,21 +97,19 @@ struct is_completion_handler_for : false_type template <typename T, typename R, typename... Args> struct is_completion_handler_for<T, R(Args...)> - : integral_constant<bool, (callable_with<T, Args...>)> + : integral_constant<bool, (callable_with<decay_t<T>, Args...>)> { }; -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - template <typename T, typename R, typename... Args> struct is_completion_handler_for<T, R(Args...) &> - : integral_constant<bool, (callable_with<T&, Args...>)> + : integral_constant<bool, (callable_with<decay_t<T>&, Args...>)> { }; template <typename T, typename R, typename... Args> struct is_completion_handler_for<T, R(Args...) &&> - : integral_constant<bool, (callable_with<T&&, Args...>)> + : integral_constant<bool, (callable_with<decay_t<T>&&, Args...>)> { }; @@ -125,24 +117,23 @@ struct is_completion_handler_for<T, R(Args...) &&> template <typename T, typename R, typename... Args> struct is_completion_handler_for<T, R(Args...) noexcept> - : integral_constant<bool, (callable_with<T, Args...>)> + : integral_constant<bool, (callable_with<decay_t<T>, Args...>)> { }; template <typename T, typename R, typename... Args> struct is_completion_handler_for<T, R(Args...) & noexcept> - : integral_constant<bool, (callable_with<T&, Args...>)> + : integral_constant<bool, (callable_with<decay_t<T>&, Args...>)> { }; template <typename T, typename R, typename... Args> struct is_completion_handler_for<T, R(Args...) && noexcept> - : integral_constant<bool, (callable_with<T&&, Args...>)> + : integral_constant<bool, (callable_with<decay_t<T>&&, Args...>)> { }; # endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) template <typename T, typename Signature0, typename... SignatureN> struct is_completion_handler_for<T, Signature0, SignatureN...> @@ -174,8 +165,6 @@ ASIO_CONCEPT completion_handler_for = ::asio::completion_handler_for<sig0, sig1, sig2> #else // defined(ASIO_HAS_CONCEPTS) - // && defined(ASIO_HAS_VARIADIC_TEMPLATES) - // && defined(ASIO_HAS_DECLTYPE) #define ASIO_COMPLETION_SIGNATURE typename #define ASIO_COMPLETION_HANDLER_FOR(sig) typename @@ -183,271 +172,130 @@ ASIO_CONCEPT completion_handler_for = #define ASIO_COMPLETION_HANDLER_FOR3(sig0, sig1, sig2) typename #endif // defined(ASIO_HAS_CONCEPTS) - // && defined(ASIO_HAS_VARIADIC_TEMPLATES) - // && defined(ASIO_HAS_DECLTYPE) namespace detail { template <typename T> -struct is_simple_completion_signature : false_type +struct is_lvalue_completion_signature : false_type { }; -template <typename T> -struct simple_completion_signature; +template <typename R, typename... Args> +struct is_lvalue_completion_signature<R(Args...) &> : true_type +{ +}; -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) +# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template <typename R, typename... Args> -struct is_simple_completion_signature<R(Args...)> : true_type +struct is_lvalue_completion_signature<R(Args...) & noexcept> : true_type { }; +# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) + template <typename... Signatures> -struct are_simple_completion_signatures : false_type +struct are_any_lvalue_completion_signatures : false_type { }; template <typename Sig0> -struct are_simple_completion_signatures<Sig0> - : is_simple_completion_signature<Sig0> +struct are_any_lvalue_completion_signatures<Sig0> + : is_lvalue_completion_signature<Sig0> { }; template <typename Sig0, typename... SigN> -struct are_simple_completion_signatures<Sig0, SigN...> +struct are_any_lvalue_completion_signatures<Sig0, SigN...> : integral_constant<bool, ( - is_simple_completion_signature<Sig0>::value - && are_simple_completion_signatures<SigN...>::value)> + is_lvalue_completion_signature<Sig0>::value + || are_any_lvalue_completion_signatures<SigN...>::value)> { }; -template <typename R, typename... Args> -struct simple_completion_signature<R(Args...)> -{ - typedef R type(Args...); -}; - -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -template <typename R, typename... Args> -struct simple_completion_signature<R(Args...) &> +template <typename T> +struct is_rvalue_completion_signature : false_type { - typedef R type(Args...); }; template <typename R, typename... Args> -struct simple_completion_signature<R(Args...) &&> +struct is_rvalue_completion_signature<R(Args...) &&> : true_type { - typedef R type(Args...); }; # if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template <typename R, typename... Args> -struct simple_completion_signature<R(Args...) noexcept> -{ - typedef R type(Args...); -}; - -template <typename R, typename... Args> -struct simple_completion_signature<R(Args...) & noexcept> +struct is_rvalue_completion_signature<R(Args...) && noexcept> : true_type { - typedef R type(Args...); -}; - -template <typename R, typename... Args> -struct simple_completion_signature<R(Args...) && noexcept> -{ - typedef R type(Args...); }; # endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename R> -struct is_simple_completion_signature<R()> : true_type -{ -}; - -#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct is_simple_completion_signature<R(ASIO_VARIADIC_TARGS(n))> \ - : true_type \ - { \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF) -#undef ASIO_PRIVATE_SIMPLE_SIG_DEF - -template <typename Sig0 = void, typename Sig1 = void, - typename Sig2 = void, typename = void> -struct are_simple_completion_signatures : false_type +template <typename... Signatures> +struct are_any_rvalue_completion_signatures : false_type { }; template <typename Sig0> -struct are_simple_completion_signatures<Sig0> - : is_simple_completion_signature<Sig0> +struct are_any_rvalue_completion_signatures<Sig0> + : is_rvalue_completion_signature<Sig0> { }; -template <typename Sig0, typename Sig1> -struct are_simple_completion_signatures<Sig0, Sig1> - : integral_constant<bool, - (is_simple_completion_signature<Sig0>::value - && is_simple_completion_signature<Sig1>::value)> +template <typename Sig0, typename... SigN> +struct are_any_rvalue_completion_signatures<Sig0, SigN...> + : integral_constant<bool, ( + is_rvalue_completion_signature<Sig0>::value + || are_any_rvalue_completion_signatures<SigN...>::value)> { }; -template <typename Sig0, typename Sig1, typename Sig2> -struct are_simple_completion_signatures<Sig0, Sig1, Sig2> - : integral_constant<bool, - (is_simple_completion_signature<Sig0>::value - && is_simple_completion_signature<Sig1>::value - && is_simple_completion_signature<Sig2>::value)> -{ -}; +template <typename T> +struct simple_completion_signature; -template <typename R> -struct simple_completion_signature<R()> +template <typename R, typename... Args> +struct simple_completion_signature<R(Args...)> { - typedef R type(); + typedef R type(Args...); }; -#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct simple_completion_signature<R(ASIO_VARIADIC_TARGS(n))> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)); \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF) -#undef ASIO_PRIVATE_SIMPLE_SIG_DEF - -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -template <typename R> -struct simple_completion_signature<R() &> +template <typename R, typename... Args> +struct simple_completion_signature<R(Args...) &> { - typedef R type(); + typedef R type(Args...); }; -template <typename R> -struct simple_completion_signature<R() &&> +template <typename R, typename... Args> +struct simple_completion_signature<R(Args...) &&> { - typedef R type(); + typedef R type(Args...); }; -#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct simple_completion_signature< \ - R(ASIO_VARIADIC_TARGS(n)) &> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)); \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct simple_completion_signature< \ - R(ASIO_VARIADIC_TARGS(n)) &&> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)); \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF) -#undef ASIO_PRIVATE_SIMPLE_SIG_DEF - # if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) -template <typename R> -struct simple_completion_signature<R() noexcept> +template <typename R, typename... Args> +struct simple_completion_signature<R(Args...) noexcept> { - typedef R type(); + typedef R type(Args...); }; -template <typename R> -struct simple_completion_signature<R() & noexcept> +template <typename R, typename... Args> +struct simple_completion_signature<R(Args...) & noexcept> { - typedef R type(); + typedef R type(Args...); }; -template <typename R> -struct simple_completion_signature<R() && noexcept> +template <typename R, typename... Args> +struct simple_completion_signature<R(Args...) && noexcept> { - typedef R type(); + typedef R type(Args...); }; -#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct simple_completion_signature< \ - R(ASIO_VARIADIC_TARGS(n)) noexcept> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)); \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct simple_completion_signature< \ - R(ASIO_VARIADIC_TARGS(n)) & noexcept> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)); \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct simple_completion_signature< \ - R(ASIO_VARIADIC_TARGS(n)) && noexcept> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)); \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF) -#undef ASIO_PRIVATE_SIMPLE_SIG_DEF - # endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \ - || defined(GENERATING_DOCUMENTATION) - -# define ASIO_COMPLETION_SIGNATURES_TPARAMS \ - ASIO_COMPLETION_SIGNATURE... Signatures -# define ASIO_COMPLETION_SIGNATURES_TSPECPARAMS \ - ASIO_COMPLETION_SIGNATURE... Signatures - -# define ASIO_COMPLETION_SIGNATURES_TARGS Signatures... - -# define ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS \ - typename asio::detail::simple_completion_signature< \ - Signatures>::type... - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - -# define ASIO_COMPLETION_SIGNATURES_TPARAMS \ - typename Sig0 = void, \ - typename Sig1 = void, \ - typename Sig2 = void - -# define ASIO_COMPLETION_SIGNATURES_TSPECPARAMS \ - typename Sig0, \ - typename Sig1, \ - typename Sig2 - -# define ASIO_COMPLETION_SIGNATURES_TARGS Sig0, Sig1, Sig2 - -# define ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS \ - typename ::asio::detail::simple_completion_signature<Sig0>::type, \ - typename ::asio::detail::simple_completion_signature<Sig1>::type, \ - typename ::asio::detail::simple_completion_signature<Sig2>::type - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - -template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS> +template <typename CompletionToken, + ASIO_COMPLETION_SIGNATURE... Signatures> class completion_handler_async_result { public: @@ -462,56 +310,22 @@ public: { } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Initiation, ASIO_COMPLETION_HANDLER_FOR(Signatures...) RawCompletionToken, typename... Args> - static return_type initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token, - ASIO_MOVE_ARG(Args)... args) + static return_type initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) { - ASIO_MOVE_CAST(Initiation)(initiation)( - ASIO_MOVE_CAST(RawCompletionToken)(token), - ASIO_MOVE_CAST(Args)(args)...); + static_cast<Initiation&&>(initiation)( + static_cast<RawCompletionToken&&>(token), + static_cast<Args&&>(args)...); } -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Initiation, typename RawCompletionToken> - static return_type initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token) - { - ASIO_MOVE_CAST(Initiation)(initiation)( - ASIO_MOVE_CAST(RawCompletionToken)(token)); - } - -#define ASIO_PRIVATE_INITIATE_DEF(n) \ - template <typename Initiation, \ - typename RawCompletionToken, \ - ASIO_VARIADIC_TPARAMS(n)> \ - static return_type initiate( \ - ASIO_MOVE_ARG(Initiation) initiation, \ - ASIO_MOVE_ARG(RawCompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - ASIO_MOVE_CAST(Initiation)(initiation)( \ - ASIO_MOVE_CAST(RawCompletionToken)(token), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF) -#undef ASIO_PRIVATE_INITIATE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - private: completion_handler_async_result( - const completion_handler_async_result&) ASIO_DELETED; + const completion_handler_async_result&) = delete; completion_handler_async_result& operator=( - const completion_handler_async_result&) ASIO_DELETED; + const completion_handler_async_result&) = delete; }; } // namespace detail @@ -536,7 +350,8 @@ private: * The primary template assumes that the CompletionToken is the completion * handler. */ -template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS> +template <typename CompletionToken, + ASIO_COMPLETION_SIGNATURE... Signatures> class async_result { public: @@ -561,70 +376,46 @@ public: /// obtain the value to be returned from the initiating function. template <typename Initiation, typename RawCompletionToken, typename... Args> static return_type initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token, - ASIO_MOVE_ARG(Args)... args); + Initiation&& initiation, + RawCompletionToken&& token, + Args&&... args); private: - async_result(const async_result&) ASIO_DELETED; - async_result& operator=(const async_result&) ASIO_DELETED; + async_result(const async_result&) = delete; + async_result& operator=(const async_result&) = delete; }; #else // defined(GENERATING_DOCUMENTATION) -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS> +template <typename CompletionToken, + ASIO_COMPLETION_SIGNATURE... Signatures> class async_result : - public conditional< - detail::are_simple_completion_signatures< - ASIO_COMPLETION_SIGNATURES_TARGS>::value, - detail::completion_handler_async_result< - CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS>, + public conditional_t< + detail::are_any_lvalue_completion_signatures<Signatures...>::value + || !detail::are_any_rvalue_completion_signatures<Signatures...>::value, + detail::completion_handler_async_result<CompletionToken, Signatures...>, async_result<CompletionToken, - ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS> - >::type + typename detail::simple_completion_signature<Signatures>::type...> + > { public: - typedef typename conditional< - detail::are_simple_completion_signatures< - ASIO_COMPLETION_SIGNATURES_TARGS>::value, - detail::completion_handler_async_result< - CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS>, + typedef conditional_t< + detail::are_any_lvalue_completion_signatures<Signatures...>::value + || !detail::are_any_rvalue_completion_signatures<Signatures...>::value, + detail::completion_handler_async_result<CompletionToken, Signatures...>, async_result<CompletionToken, - ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS> - >::type base_type; + typename detail::simple_completion_signature<Signatures>::type...> + > base_type; using base_type::base_type; private: - async_result(const async_result&) ASIO_DELETED; - async_result& operator=(const async_result&) ASIO_DELETED; -}; - -#else // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS> -class async_result : - public detail::completion_handler_async_result< - CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS> -{ -public: - explicit async_result(CompletionToken& h) - : detail::completion_handler_async_result< - CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS>(h) - { - } - -private: - async_result(const async_result&) ASIO_DELETED; - async_result& operator=(const async_result&) ASIO_DELETED; + async_result(const async_result&) = delete; + async_result& operator=(const async_result&) = delete; }; -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -template <ASIO_COMPLETION_SIGNATURES_TSPECPARAMS> -class async_result<void, ASIO_COMPLETION_SIGNATURES_TARGS> +template <ASIO_COMPLETION_SIGNATURE... Signatures> +class async_result<void, Signatures...> { // Empty. }; @@ -634,65 +425,39 @@ class async_result<void, ASIO_COMPLETION_SIGNATURES_TARGS> /// Helper template to deduce the handler type from a CompletionToken, capture /// a local copy of the handler, and then create an async_result for the /// handler. -template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS> +template <typename CompletionToken, + ASIO_COMPLETION_SIGNATURE... Signatures> struct async_completion { /// The real handler type to be used for the asynchronous operation. typedef typename asio::async_result< - typename decay<CompletionToken>::type, - ASIO_COMPLETION_SIGNATURES_TARGS>::completion_handler_type - completion_handler_type; + decay_t<CompletionToken>, Signatures...>::completion_handler_type + completion_handler_type; -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Constructor. /** * The constructor creates the concrete completion handler and makes the link * between the handler and the asynchronous result. */ explicit async_completion(CompletionToken& token) - : completion_handler(static_cast<typename conditional< + : completion_handler(static_cast<conditional_t< is_same<CompletionToken, completion_handler_type>::value, - completion_handler_type&, CompletionToken&&>::type>(token)), - result(completion_handler) - { - } -#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - explicit async_completion(typename decay<CompletionToken>::type& token) - : completion_handler(token), + completion_handler_type&, CompletionToken&&>>(token)), result(completion_handler) { } - explicit async_completion(const typename decay<CompletionToken>::type& token) - : completion_handler(token), - result(completion_handler) - { - } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// A copy of, or reference to, a real handler object. -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - typename conditional< + conditional_t< is_same<CompletionToken, completion_handler_type>::value, - completion_handler_type&, completion_handler_type>::type completion_handler; -#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - completion_handler_type completion_handler; -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + completion_handler_type&, completion_handler_type> completion_handler; /// The result of the asynchronous operation's initiating function. - async_result<typename decay<CompletionToken>::type, - ASIO_COMPLETION_SIGNATURES_TARGS> result; + async_result<decay_t<CompletionToken>, Signatures...> result; }; namespace detail { -template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS> -struct async_result_helper - : async_result<typename decay<CompletionToken>::type, - ASIO_COMPLETION_SIGNATURES_TARGS> -{ -}; - struct async_result_memfns_base { void initiate(); @@ -718,11 +483,11 @@ char async_result_initiate_memfn_helper( void (async_result_memfns_base::*)(), &async_result_memfns_derived<T>::initiate>*); -template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS> +template <typename CompletionToken, + ASIO_COMPLETION_SIGNATURE... Signatures> struct async_result_has_initiate_memfn : integral_constant<bool, sizeof(async_result_initiate_memfn_helper< - async_result<typename decay<CompletionToken>::type, - ASIO_COMPLETION_SIGNATURES_TARGS> + async_result<decay_t<CompletionToken>, Signatures...> >(0)) != 1> { }; @@ -736,25 +501,6 @@ struct async_result_has_initiate_memfn void_or_deduced # define ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \ void_or_deduced -#elif defined(_MSC_VER) && (_MSC_VER < 1500) -# define ASIO_INITFN_RESULT_TYPE(ct, sig) \ - typename ::asio::detail::async_result_helper< \ - ct, sig>::return_type -# define ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \ - typename ::asio::detail::async_result_helper< \ - ct, sig0, sig1>::return_type -# define ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \ - typename ::asio::detail::async_result_helper< \ - ct, sig0, sig1, sig2>::return_type -#define ASIO_HANDLER_TYPE(ct, sig) \ - typename ::asio::detail::async_result_helper< \ - ct, sig>::completion_handler_type -#define ASIO_HANDLER_TYPE2(ct, sig0, sig1) \ - typename ::asio::detail::async_result_helper< \ - ct, sig0, sig1>::completion_handler_type -#define ASIO_HANDLER_TYPE3(ct, sig0, sig1, sig2) \ - typename ::asio::detail::async_result_helper< \ - ct, sig0, sig1, sig2>::completion_handler_type #else # define ASIO_INITFN_RESULT_TYPE(ct, sig) \ typename ::asio::async_result< \ @@ -802,26 +548,45 @@ struct async_result_has_initiate_memfn #endif #if defined(GENERATING_DOCUMENTATION) +# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \ + auto +# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \ + auto +# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \ + auto +# define ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) +#elif defined(ASIO_HAS_RETURN_TYPE_DEDUCTION) +# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \ + auto +# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \ + auto +# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \ + auto +# define ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) +#else +# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \ + auto +# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \ + auto +# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \ + auto +# define ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) -> decltype expr +#endif + +#if defined(GENERATING_DOCUMENTATION) # define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \ void_or_deduced # define ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \ void_or_deduced # define ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \ void_or_deduced -#elif defined(ASIO_HAS_DECLTYPE) +#else # define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \ decltype expr # define ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \ decltype expr # define ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \ decltype expr -#else -# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \ - ASIO_INITFN_RESULT_TYPE(ct, sig) -# define ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \ - ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) -# define ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \ - ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) #endif #if defined(GENERATING_DOCUMENTATION) @@ -830,326 +595,57 @@ template <typename CompletionToken, completion_signature... Signatures, typename Initiation, typename... Args> void_or_deduced async_initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken), - ASIO_MOVE_ARG(Args)... args); + Initiation&& initiation, + type_identity_t<CompletionToken>& token, + Args&&... args); -#elif defined(ASIO_HAS_VARIADIC_TEMPLATES) +#else // defined(GENERATING_DOCUMENTATION) template <typename CompletionToken, ASIO_COMPLETION_SIGNATURE... Signatures, typename Initiation, typename... Args> -inline typename constraint< +inline auto async_initiate(Initiation&& initiation, + type_identity_t<CompletionToken>& token, Args&&... args) + -> constraint_t< detail::async_result_has_initiate_memfn< CompletionToken, Signatures...>::value, - ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signatures..., - (async_result<typename decay<CompletionToken>::type, - Signatures...>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(), - declval<ASIO_MOVE_ARG(CompletionToken)>(), - declval<ASIO_MOVE_ARG(Args)>()...)))>::type -async_initiate(ASIO_MOVE_ARG(Initiation) initiation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, - ASIO_MOVE_ARG(Args)... args) -{ - return async_result<typename decay<CompletionToken>::type, - Signatures...>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), - ASIO_MOVE_CAST(CompletionToken)(token), - ASIO_MOVE_CAST(Args)(args)...); + decltype( + async_result<decay_t<CompletionToken>, Signatures...>::initiate( + static_cast<Initiation&&>(initiation), + static_cast<CompletionToken&&>(token), + static_cast<Args&&>(args)...))> +{ + return async_result<decay_t<CompletionToken>, Signatures...>::initiate( + static_cast<Initiation&&>(initiation), + static_cast<CompletionToken&&>(token), + static_cast<Args&&>(args)...); } template <typename CompletionToken, ASIO_COMPLETION_SIGNATURE... Signatures, typename Initiation, typename... Args> -inline typename constraint< +inline constraint_t< !detail::async_result_has_initiate_memfn< CompletionToken, Signatures...>::value, - ASIO_INITFN_RESULT_TYPE(CompletionToken, Signatures...)>::type -async_initiate(ASIO_MOVE_ARG(Initiation) initiation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, - ASIO_MOVE_ARG(Args)... args) + typename async_result<decay_t<CompletionToken>, Signatures...>::return_type> +async_initiate(Initiation&& initiation, + type_identity_t<CompletionToken>& token, Args&&... args) { async_completion<CompletionToken, Signatures...> completion(token); - ASIO_MOVE_CAST(Initiation)(initiation)( - ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, - Signatures...))(completion.completion_handler), - ASIO_MOVE_CAST(Args)(args)...); + static_cast<Initiation&&>(initiation)( + static_cast< + typename async_result<decay_t<CompletionToken>, + Signatures...>::completion_handler_type&&>( + completion.completion_handler), + static_cast<Args&&>(args)...); return completion.result.get(); } -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename CompletionToken, - ASIO_COMPLETION_SIGNATURE Sig0, - typename Initiation> -inline typename constraint< - detail::async_result_has_initiate_memfn< - CompletionToken, Sig0>::value, - ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Sig0, - (async_result<typename decay<CompletionToken>::type, - Sig0>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(), - declval<ASIO_MOVE_ARG(CompletionToken)>())))>::type -async_initiate(ASIO_MOVE_ARG(Initiation) initiation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) -{ - return async_result<typename decay<CompletionToken>::type, - Sig0>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), - ASIO_MOVE_CAST(CompletionToken)(token)); -} - -template <typename CompletionToken, - ASIO_COMPLETION_SIGNATURE Sig0, - ASIO_COMPLETION_SIGNATURE Sig1, - typename Initiation> -inline typename constraint< - detail::async_result_has_initiate_memfn< - CompletionToken, Sig0, Sig1>::value, - ASIO_INITFN_DEDUCED_RESULT_TYPE2(CompletionToken, Sig0, Sig1, - (async_result<typename decay<CompletionToken>::type, - Sig0, Sig1>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(), - declval<ASIO_MOVE_ARG(CompletionToken)>())))>::type -async_initiate(ASIO_MOVE_ARG(Initiation) initiation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) -{ - return async_result<typename decay<CompletionToken>::type, - Sig0, Sig1>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), - ASIO_MOVE_CAST(CompletionToken)(token)); -} - -template <typename CompletionToken, - ASIO_COMPLETION_SIGNATURE Sig0, - ASIO_COMPLETION_SIGNATURE Sig1, - ASIO_COMPLETION_SIGNATURE Sig2, - typename Initiation> -inline typename constraint< - detail::async_result_has_initiate_memfn< - CompletionToken, Sig0, Sig1, Sig2>::value, - ASIO_INITFN_DEDUCED_RESULT_TYPE3(CompletionToken, Sig0, Sig1, Sig2, - (async_result<typename decay<CompletionToken>::type, - Sig0, Sig1, Sig2>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(), - declval<ASIO_MOVE_ARG(CompletionToken)>())))>::type -async_initiate(ASIO_MOVE_ARG(Initiation) initiation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) -{ - return async_result<typename decay<CompletionToken>::type, - Sig0, Sig1, Sig2>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), - ASIO_MOVE_CAST(CompletionToken)(token)); -} - -template <typename CompletionToken, - ASIO_COMPLETION_SIGNATURE Sig0, - typename Initiation> -inline typename constraint< - !detail::async_result_has_initiate_memfn< - CompletionToken, Sig0>::value, - ASIO_INITFN_RESULT_TYPE(CompletionToken, Sig0)>::type -async_initiate(ASIO_MOVE_ARG(Initiation) initiation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) -{ - async_completion<CompletionToken, Sig0> completion(token); - - ASIO_MOVE_CAST(Initiation)(initiation)( - ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, - Sig0))(completion.completion_handler)); - - return completion.result.get(); -} - -template <typename CompletionToken, - ASIO_COMPLETION_SIGNATURE Sig0, - ASIO_COMPLETION_SIGNATURE Sig1, - typename Initiation> -inline typename constraint< - !detail::async_result_has_initiate_memfn< - CompletionToken, Sig0, Sig1>::value, - ASIO_INITFN_RESULT_TYPE2(CompletionToken, Sig0, Sig1)>::type -async_initiate(ASIO_MOVE_ARG(Initiation) initiation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) -{ - async_completion<CompletionToken, Sig0, Sig1> completion(token); - - ASIO_MOVE_CAST(Initiation)(initiation)( - ASIO_MOVE_CAST(ASIO_HANDLER_TYPE2(CompletionToken, - Sig0, Sig1))(completion.completion_handler)); - - return completion.result.get(); -} - -template <typename CompletionToken, - ASIO_COMPLETION_SIGNATURE Sig0, - ASIO_COMPLETION_SIGNATURE Sig1, - ASIO_COMPLETION_SIGNATURE Sig2, - typename Initiation> -inline typename constraint< - !detail::async_result_has_initiate_memfn< - CompletionToken, Sig0, Sig1, Sig2>::value, - ASIO_INITFN_RESULT_TYPE3(CompletionToken, Sig0, Sig1, Sig2)>::type -async_initiate(ASIO_MOVE_ARG(Initiation) initiation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) -{ - async_completion<CompletionToken, Sig0, Sig1, Sig2> completion(token); - - ASIO_MOVE_CAST(Initiation)(initiation)( - ASIO_MOVE_CAST(ASIO_HANDLER_TYPE3(CompletionToken, - Sig0, Sig1, Sig2))(completion.completion_handler)); - - return completion.result.get(); -} +#endif // defined(GENERATING_DOCUMENTATION) -#define ASIO_PRIVATE_INITIATE_DEF(n) \ - template <typename CompletionToken, \ - ASIO_COMPLETION_SIGNATURE Sig0, \ - typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \ - inline typename constraint< \ - detail::async_result_has_initiate_memfn< \ - CompletionToken, Sig0>::value, \ - ASIO_INITFN_DEDUCED_RESULT_TYPE( \ - CompletionToken, Sig0, \ - (async_result<typename decay<CompletionToken>::type, \ - Sig0>::initiate( \ - declval<ASIO_MOVE_ARG(Initiation)>(), \ - declval<ASIO_MOVE_ARG(CompletionToken)>(), \ - ASIO_VARIADIC_MOVE_DECLVAL(n))))>::type \ - async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \ - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - return async_result<typename decay<CompletionToken>::type, \ - Sig0>::initiate( \ - ASIO_MOVE_CAST(Initiation)(initiation), \ - ASIO_MOVE_CAST(CompletionToken)(token), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <typename CompletionToken, \ - ASIO_COMPLETION_SIGNATURE Sig0, \ - ASIO_COMPLETION_SIGNATURE Sig1, \ - typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \ - inline typename constraint< \ - detail::async_result_has_initiate_memfn< \ - CompletionToken, Sig0, Sig1>::value, \ - ASIO_INITFN_DEDUCED_RESULT_TYPE2( \ - CompletionToken, Sig0, Sig1, \ - (async_result<typename decay<CompletionToken>::type, \ - Sig0, Sig1>::initiate( \ - declval<ASIO_MOVE_ARG(Initiation)>(), \ - declval<ASIO_MOVE_ARG(CompletionToken)>(), \ - ASIO_VARIADIC_MOVE_DECLVAL(n))))>::type \ - async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \ - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - return async_result<typename decay<CompletionToken>::type, \ - Sig0, Sig1>::initiate( \ - ASIO_MOVE_CAST(Initiation)(initiation), \ - ASIO_MOVE_CAST(CompletionToken)(token), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <typename CompletionToken, \ - ASIO_COMPLETION_SIGNATURE Sig0, \ - ASIO_COMPLETION_SIGNATURE Sig1, \ - ASIO_COMPLETION_SIGNATURE Sig2, \ - typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \ - inline typename constraint< \ - detail::async_result_has_initiate_memfn< \ - CompletionToken, Sig0, Sig1, Sig2>::value, \ - ASIO_INITFN_DEDUCED_RESULT_TYPE3( \ - CompletionToken, Sig0, Sig1, Sig2, \ - (async_result<typename decay<CompletionToken>::type, \ - Sig0, Sig1, Sig2>::initiate( \ - declval<ASIO_MOVE_ARG(Initiation)>(), \ - declval<ASIO_MOVE_ARG(CompletionToken)>(), \ - ASIO_VARIADIC_MOVE_DECLVAL(n))))>::type \ - async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \ - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - return async_result<typename decay<CompletionToken>::type, \ - Sig0, Sig1, Sig2>::initiate( \ - ASIO_MOVE_CAST(Initiation)(initiation), \ - ASIO_MOVE_CAST(CompletionToken)(token), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <typename CompletionToken, \ - ASIO_COMPLETION_SIGNATURE Sig0, \ - typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \ - inline typename constraint< \ - !detail::async_result_has_initiate_memfn< \ - CompletionToken, Sig0>::value, \ - ASIO_INITFN_RESULT_TYPE(CompletionToken, Sig0)>::type \ - async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \ - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - async_completion<CompletionToken, \ - Sig0> completion(token); \ - \ - ASIO_MOVE_CAST(Initiation)(initiation)( \ - ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, \ - Sig0))(completion.completion_handler), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - \ - return completion.result.get(); \ - } \ - \ - template <typename CompletionToken, \ - ASIO_COMPLETION_SIGNATURE Sig0, \ - ASIO_COMPLETION_SIGNATURE Sig1, \ - typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \ - inline typename constraint< \ - !detail::async_result_has_initiate_memfn< \ - CompletionToken, Sig0, Sig1>::value, \ - ASIO_INITFN_RESULT_TYPE2(CompletionToken, Sig0, Sig1)>::type \ - async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \ - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - async_completion<CompletionToken, \ - Sig0, Sig1> completion(token); \ - \ - ASIO_MOVE_CAST(Initiation)(initiation)( \ - ASIO_MOVE_CAST(ASIO_HANDLER_TYPE2(CompletionToken, \ - Sig0, Sig1))(completion.completion_handler), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - \ - return completion.result.get(); \ - } \ - \ - template <typename CompletionToken, \ - ASIO_COMPLETION_SIGNATURE Sig0, \ - ASIO_COMPLETION_SIGNATURE Sig1, \ - ASIO_COMPLETION_SIGNATURE Sig2, \ - typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \ - inline typename constraint< \ - !detail::async_result_has_initiate_memfn< \ - CompletionToken, Sig0, Sig1, Sig2>::value, \ - ASIO_INITFN_RESULT_TYPE3(CompletionToken, Sig0, Sig1, Sig2)>::type \ - async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \ - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - async_completion<CompletionToken, \ - Sig0, Sig1, Sig2> completion(token); \ - \ - ASIO_MOVE_CAST(Initiation)(initiation)( \ - ASIO_MOVE_CAST(ASIO_HANDLER_TYPE3(CompletionToken, \ - Sig0, Sig1, Sig2))(completion.completion_handler), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - \ - return completion.result.get(); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF) -#undef ASIO_PRIVATE_INITIATE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#if defined(ASIO_HAS_CONCEPTS) \ - && defined(ASIO_HAS_VARIADIC_TEMPLATES) \ - && defined(ASIO_HAS_DECLTYPE) +#if defined(ASIO_HAS_CONCEPTS) namespace detail { @@ -1182,16 +678,209 @@ ASIO_CONCEPT completion_token_for = ::asio::completion_token_for<sig0, sig1, sig2> #else // defined(ASIO_HAS_CONCEPTS) - // && defined(ASIO_HAS_VARIADIC_TEMPLATES) - // && defined(ASIO_HAS_DECLTYPE) #define ASIO_COMPLETION_TOKEN_FOR(sig) typename #define ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) typename #define ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) typename #endif // defined(ASIO_HAS_CONCEPTS) - // && defined(ASIO_HAS_VARIADIC_TEMPLATES) - // && defined(ASIO_HAS_DECLTYPE) + +namespace detail { + +struct async_operation_probe {}; +struct async_operation_probe_result {}; + +template <typename Call, typename = void> +struct is_async_operation_call : false_type +{ +}; + +template <typename Call> +struct is_async_operation_call<Call, + void_t< + enable_if_t< + is_same< + result_of_t<Call>, + async_operation_probe_result + >::value + > + > + > : true_type +{ +}; + +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename... Signatures> +class async_result<detail::async_operation_probe, Signatures...> +{ +public: + typedef detail::async_operation_probe_result return_type; + + template <typename Initiation, typename... InitArgs> + static return_type initiate(Initiation&&, + detail::async_operation_probe, InitArgs&&...) + { + return return_type(); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +#if defined(GENERATING_DOCUMENTATION) + +/// The is_async_operation trait detects whether a type @c T and arguments +/// @c Args... may be used to initiate an asynchronous operation. +/** + * Class template @c is_async_operation is a trait is derived from @c true_type + * if the expression <tt>T(Args..., token)</tt> initiates an asynchronous + * operation, where @c token is an unspecified completion token type. Otherwise, + * @c is_async_operation is derived from @c false_type. + */ +template <typename T, typename... Args> +struct is_async_operation : integral_constant<bool, automatically_determined> +{ +}; + +#else // defined(GENERATING_DOCUMENTATION) + +template <typename T, typename... Args> +struct is_async_operation : + detail::is_async_operation_call< + T(Args..., detail::async_operation_probe)> +{ +}; + +#endif // defined(GENERATING_DOCUMENTATION) + +#if defined(ASIO_HAS_CONCEPTS) + +template <typename T, typename... Args> +ASIO_CONCEPT async_operation = is_async_operation<T, Args...>::value; + +#define ASIO_ASYNC_OPERATION(t) \ + ::asio::async_operation<t> +#define ASIO_ASYNC_OPERATION1(t, a0) \ + ::asio::async_operation<t, a0> +#define ASIO_ASYNC_OPERATION2(t, a0, a1) \ + ::asio::async_operation<t, a0, a1> +#define ASIO_ASYNC_OPERATION3(t, a0, a1, a2) \ + ::asio::async_operation<t, a0, a1, a2> + +#else // defined(ASIO_HAS_CONCEPTS) + +#define ASIO_ASYNC_OPERATION(t) typename +#define ASIO_ASYNC_OPERATION1(t, a0) typename +#define ASIO_ASYNC_OPERATION2(t, a0, a1) typename +#define ASIO_ASYNC_OPERATION3(t, a0, a1, a2) typename + +#endif // defined(ASIO_HAS_CONCEPTS) + +namespace detail { + +struct completion_signature_probe {}; + +template <typename... T> +struct completion_signature_probe_result +{ + template <template <typename...> class Op> + struct apply + { + typedef Op<T...> type; + }; +}; + +template <typename T> +struct completion_signature_probe_result<T> +{ + typedef T type; + + template <template <typename...> class Op> + struct apply + { + typedef Op<T> type; + }; +}; + +template <> +struct completion_signature_probe_result<void> +{ + template <template <typename...> class Op> + struct apply + { + typedef Op<> type; + }; +}; + +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename... Signatures> +class async_result<detail::completion_signature_probe, Signatures...> +{ +public: + typedef detail::completion_signature_probe_result<Signatures...> return_type; + + template <typename Initiation, typename... InitArgs> + static return_type initiate(Initiation&&, + detail::completion_signature_probe, InitArgs&&...) + { + return return_type(); + } +}; + +template <typename Signature> +class async_result<detail::completion_signature_probe, Signature> +{ +public: + typedef detail::completion_signature_probe_result<Signature> return_type; + + template <typename Initiation, typename... InitArgs> + static return_type initiate(Initiation&&, + detail::completion_signature_probe, InitArgs&&...) + { + return return_type(); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +#if defined(GENERATING_DOCUMENTATION) + +/// The completion_signature_of trait determines the completion signature +/// of an asynchronous operation. +/** + * Class template @c completion_signature_of is a trait with a member type + * alias @c type that denotes the completion signature of the asynchronous + * operation initiated by the expression <tt>T(Args..., token)</tt> operation, + * where @c token is an unspecified completion token type. If the asynchronous + * operation does not have exactly one completion signature, the instantion of + * the trait is well-formed but the member type alias @c type is omitted. If + * the expression <tt>T(Args..., token)</tt> is not an asynchronous operation + * then use of the trait is ill-formed. + */ +template <typename T, typename... Args> +struct completion_signature_of +{ + typedef automatically_determined type; +}; + +#else // defined(GENERATING_DOCUMENTATION) + +template <typename T, typename... Args> +struct completion_signature_of : + result_of_t<T(Args..., detail::completion_signature_probe)> +{ +}; + +#endif // defined(GENERATING_DOCUMENTATION) + +template <typename T, typename... Args> +using completion_signature_of_t = + typename completion_signature_of<T, Args...>::type; namespace detail { @@ -1203,7 +892,8 @@ struct default_completion_token_impl template <typename T> struct default_completion_token_impl<T, - typename void_type<typename T::default_completion_token_type>::type> + void_t<typename T::default_completion_token_type> + > { typedef typename T::default_completion_token_type type; }; @@ -1237,27 +927,14 @@ struct default_completion_token }; #endif -#if defined(ASIO_HAS_ALIAS_TEMPLATES) - template <typename T> using default_completion_token_t = typename default_completion_token<T>::type; -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - -#if defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) - #define ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(e) \ = typename ::asio::default_completion_token<e>::type #define ASIO_DEFAULT_COMPLETION_TOKEN(e) \ = typename ::asio::default_completion_token<e>::type() -#else // defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) - -#define ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(e) -#define ASIO_DEFAULT_COMPLETION_TOKEN(e) - -#endif // defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/awaitable.hpp b/3rdparty/asio/include/asio/awaitable.hpp index b9e8d51df5c..7e4ee7a2f22 100644 --- a/3rdparty/asio/include/asio/awaitable.hpp +++ b/3rdparty/asio/include/asio/awaitable.hpp @@ -2,7 +2,7 @@ // awaitable.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -25,6 +25,7 @@ # include <experimental/coroutine> #endif // defined(ASIO_HAS_STD_COROUTINE) +#include <utility> #include "asio/any_io_executor.hpp" #include "asio/detail/push_options.hpp" @@ -75,6 +76,14 @@ public: frame_->destroy(); } + /// Move assignment. + awaitable& operator=(awaitable&& other) noexcept + { + if (this != &other) + frame_ = std::exchange(other.frame_, nullptr); + return *this; + } + /// Checks if the awaitable refers to a future result. bool valid() const noexcept { diff --git a/3rdparty/asio/include/asio/basic_datagram_socket.hpp b/3rdparty/asio/include/asio/basic_datagram_socket.hpp index a09dfcdbee8..3d72a38475a 100644 --- a/3rdparty/asio/include/asio/basic_datagram_socket.hpp +++ b/3rdparty/asio/include/asio/basic_datagram_socket.hpp @@ -2,7 +2,7 @@ // basic_datagram_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -46,17 +46,23 @@ class basic_datagram_socket; * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. * - * Synchronous @c send, @c send_to, @c receive, @c receive_from, and @c connect - * operations are thread safe with respect to each other, if the underlying - * operating system calls are also thread safe. This means that it is permitted - * to perform concurrent calls to these synchronous operations on a single - * socket object. Other synchronous operations, such as @c open or @c close, are - * not thread safe. + * Synchronous @c send, @c send_to, @c receive, @c receive_from, @c connect, + * and @c shutdown operations are thread safe with respect to each other, if + * the underlying operating system calls are also thread safe. This means that + * it is permitted to perform concurrent calls to these synchronous operations + * on a single socket object. Other synchronous operations, such as @c open or + * @c close, are not thread safe. */ template <typename Protocol, typename Executor> class basic_datagram_socket : public basic_socket<Protocol, Executor> { +private: + class initiate_async_send; + class initiate_async_send_to; + class initiate_async_receive; + class initiate_async_receive_from; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -107,9 +113,9 @@ public: */ template <typename ExecutionContext> explicit basic_datagram_socket(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context) { } @@ -145,10 +151,10 @@ public: template <typename ExecutionContext> basic_datagram_socket(ExecutionContext& context, const protocol_type& protocol, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : basic_socket<Protocol, Executor>(context, protocol) { } @@ -192,9 +198,9 @@ public: template <typename ExecutionContext> basic_datagram_socket(ExecutionContext& context, const endpoint_type& endpoint, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context, endpoint) { } @@ -237,14 +243,13 @@ public: template <typename ExecutionContext> basic_datagram_socket(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_socket, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context, protocol, native_socket) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a basic_datagram_socket from another. /** * This constructor moves a datagram socket from one object to another. @@ -256,7 +261,7 @@ public: * constructed using the @c basic_datagram_socket(const executor_type&) * constructor. */ - basic_datagram_socket(basic_datagram_socket&& other) ASIO_NOEXCEPT + basic_datagram_socket(basic_datagram_socket&& other) noexcept : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -293,10 +298,10 @@ public: */ template <typename Protocol1, typename Executor1> basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other, - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -315,16 +320,15 @@ public: * constructor. */ template <typename Protocol1, typename Executor1> - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_datagram_socket& - >::type operator=(basic_datagram_socket<Protocol1, Executor1>&& other) + > operator=(basic_datagram_socket<Protocol1, Executor1>&& other) { basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destroys the socket. /** @@ -423,25 +427,31 @@ public: /// Start an asynchronous send on a connected socket. /** * This function is used to asynchronously send data on the datagram socket. - * The function call always returns immediately. + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. + * remain valid until the completion handler is called. * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the send completes. Potential + * completion tokens include @ref use_future, @ref use_awaitable, @ref + * yield_context, or a function object with the correct completion signature. + * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. + * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected datagram * socket. @@ -467,44 +477,51 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_send(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_send(const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send>(), token, + buffers, socket_base::message_flags(0))) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send(this), handler, + initiate_async_send(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous send on a connected socket. /** * This function is used to asynchronously send data on the datagram socket. - * The function call always returns immediately. + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. + * remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the send completes. Potential + * completion tokens include @ref use_future, @ref use_awaitable, @ref + * yield_context, or a function object with the correct completion signature. + * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. + * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected datagram * socket. @@ -521,18 +538,18 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_send(const ConstBufferSequence& buffers, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send>(), token, buffers, flags)) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send(this), handler, buffers, flags); + initiate_async_send(this), token, buffers, flags); } /// Send a datagram to the specified endpoint. @@ -626,28 +643,34 @@ public: /// Start an asynchronous send. /** * This function is used to asynchronously send a datagram to the specified - * remote endpoint. The function call always returns immediately. + * remote endpoint. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param buffers One or more data buffers to be sent to the remote endpoint. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param destination The remote endpoint to which the data will be sent. * Copies will be made of the endpoint as required. * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the send completes. Potential + * completion tokens include @ref use_future, @ref use_awaitable, @ref + * yield_context, or a function object with the correct completion signature. + * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. + * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To send a single data buffer use the @ref buffer function as follows: * @code @@ -672,48 +695,55 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_send_to(const ConstBufferSequence& buffers, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send_to>(), token, buffers, + destination, socket_base::message_flags(0))) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send_to(this), handler, buffers, + initiate_async_send_to(this), token, buffers, destination, socket_base::message_flags(0)); } /// Start an asynchronous send. /** * This function is used to asynchronously send a datagram to the specified - * remote endpoint. The function call always returns immediately. + * remote endpoint. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param buffers One or more data buffers to be sent to the remote endpoint. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. * * @param destination The remote endpoint to which the data will be sent. * Copies will be made of the endpoint as required. * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the send completes. Potential + * completion tokens include @ref use_future, @ref use_awaitable, @ref + * yield_context, or a function object with the correct completion signature. + * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. + * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * On POSIX or Windows operating systems, this asynchronous operation supports * cancellation for the following asio::cancellation_type values: @@ -726,18 +756,20 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_send_to(const ConstBufferSequence& buffers, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send_to>(), token, + buffers, destination, flags)) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send_to(this), handler, buffers, destination, flags); + initiate_async_send_to(this), token, + buffers, destination, flags); } /// Receive some data on a connected socket. @@ -832,25 +864,31 @@ public: /// Start an asynchronous receive on a connected socket. /** * This function is used to asynchronously receive data from the datagram - * socket. The function call always returns immediately. + * socket. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected * datagram socket. @@ -877,44 +915,51 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_receive(const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive>(), token, + buffers, socket_base::message_flags(0))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive(this), handler, + initiate_async_receive(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive on a connected socket. /** * This function is used to asynchronously receive data from the datagram - * socket. The function call always returns immediately. + * socket. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param flags Flags specifying how the receive call is to be made. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected * datagram socket. @@ -931,18 +976,18 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive(const MutableBufferSequence& buffers, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive>(), token, buffers, flags)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive(this), handler, buffers, flags); + initiate_async_receive(this), token, buffers, flags); } /// Receive a datagram with the endpoint of the sender. @@ -1036,31 +1081,37 @@ public: /// Start an asynchronous receive. /** - * This function is used to asynchronously receive a datagram. The function - * call always returns immediately. + * This function is used to asynchronously receive a datagram. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param sender_endpoint An endpoint object that receives the endpoint of * the remote sender of the datagram. Ownership of the sender_endpoint object * is retained by the caller, which must guarantee that it is valid until the - * handler is called. + * completion handler is called. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To receive into a single data buffer use the @ref buffer function as * follows: @@ -1082,50 +1133,57 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive_from(const MutableBufferSequence& buffers, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive_from>(), token, buffers, + &sender_endpoint, socket_base::message_flags(0))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive_from(this), handler, buffers, + initiate_async_receive_from(this), token, buffers, &sender_endpoint, socket_base::message_flags(0)); } /// Start an asynchronous receive. /** - * This function is used to asynchronously receive a datagram. The function - * call always returns immediately. + * This function is used to asynchronously receive a datagram. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param sender_endpoint An endpoint object that receives the endpoint of * the remote sender of the datagram. Ownership of the sender_endpoint object * is retained by the caller, which must guarantee that it is valid until the - * handler is called. + * completion handler is called. * * @param flags Flags specifying how the receive call is to be made. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * On POSIX or Windows operating systems, this asynchronous operation supports * cancellation for the following asio::cancellation_type values: @@ -1138,26 +1196,27 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive_from(const MutableBufferSequence& buffers, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, socket_base::message_flags flags, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive_from>(), token, + buffers, &sender_endpoint, flags)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive_from(this), handler, + initiate_async_receive_from(this), token, buffers, &sender_endpoint, flags); } private: // Disallow copying and assignment. - basic_datagram_socket(const basic_datagram_socket&) ASIO_DELETED; + basic_datagram_socket(const basic_datagram_socket&) = delete; basic_datagram_socket& operator=( - const basic_datagram_socket&) ASIO_DELETED; + const basic_datagram_socket&) = delete; class initiate_async_send { @@ -1169,13 +1228,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, const ConstBufferSequence& buffers, socket_base::message_flags flags) const { @@ -1203,13 +1262,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags) const { @@ -1237,13 +1296,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, const MutableBufferSequence& buffers, socket_base::message_flags flags) const { @@ -1271,13 +1330,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, const MutableBufferSequence& buffers, endpoint_type* sender_endpoint, socket_base::message_flags flags) const { diff --git a/3rdparty/asio/include/asio/basic_deadline_timer.hpp b/3rdparty/asio/include/asio/basic_deadline_timer.hpp index 4d647f888ce..9343591bf8b 100644 --- a/3rdparty/asio/include/asio/basic_deadline_timer.hpp +++ b/3rdparty/asio/include/asio/basic_deadline_timer.hpp @@ -2,7 +2,7 @@ // basic_deadline_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -128,6 +128,9 @@ template <typename Time, typename Executor = any_io_executor> class basic_deadline_timer { +private: + class initiate_async_wait; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -175,9 +178,9 @@ public: */ template <typename ExecutionContext> explicit basic_deadline_timer(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { } @@ -213,9 +216,9 @@ public: */ template <typename ExecutionContext> basic_deadline_timer(ExecutionContext& context, const time_type& expiry_time, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -257,9 +260,9 @@ public: template <typename ExecutionContext> basic_deadline_timer(ExecutionContext& context, const duration_type& expiry_time, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -268,7 +271,6 @@ public: asio::detail::throw_error(ec, "expires_from_now"); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a basic_deadline_timer from another. /** * This constructor moves a timer from one object to another. @@ -302,7 +304,6 @@ public: impl_ = std::move(other.impl_); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destroys the timer. /** @@ -314,7 +315,7 @@ public: } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + const executor_type& get_executor() noexcept { return impl_.get_executor(); } @@ -607,30 +608,36 @@ public: /// Start an asynchronous wait on the timer. /** * This function may be used to initiate an asynchronous wait against the - * timer. It always returns immediately. + * timer. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * - * For each call to async_wait(), the supplied handler will be called exactly - * once. The handler will be called when: + * For each call to async_wait(), the completion handler will be called + * exactly once. The completion handler will be called when: * * @li The timer has expired. * * @li The timer was cancelled, in which case the handler is passed the error * code asio::error::operation_aborted. * - * @param handler The handler to be called when the timer expires. Copies - * will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the timer expires. Potential + * completion tokens include @ref use_future, @ref use_awaitable, @ref + * yield_context, or a function object with the correct completion signature. + * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code) @endcode + * * @par Per-Operation Cancellation - * On POSIX or Windows operating systems, this asynchronous operation supports - * cancellation for the following asio::cancellation_type values: + * This asynchronous operation supports cancellation for the following + * asio::cancellation_type values: * * @li @c cancellation_type::terminal * @@ -640,22 +647,22 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) - WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler, - void (asio::error_code)) - async_wait( - ASIO_MOVE_ARG(WaitHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WaitToken = default_completion_token_t<executor_type>> + auto async_wait( + WaitToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WaitToken, void (asio::error_code)>( + declval<initiate_async_wait>(), token)) { - return async_initiate<WaitHandler, void (asio::error_code)>( - initiate_async_wait(this), handler); + return async_initiate<WaitToken, void (asio::error_code)>( + initiate_async_wait(this), token); } private: // Disallow copying and assignment. - basic_deadline_timer(const basic_deadline_timer&) ASIO_DELETED; + basic_deadline_timer(const basic_deadline_timer&) = delete; basic_deadline_timer& operator=( - const basic_deadline_timer&) ASIO_DELETED; + const basic_deadline_timer&) = delete; class initiate_async_wait { @@ -667,13 +674,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WaitHandler> - void operator()(ASIO_MOVE_ARG(WaitHandler) handler) const + void operator()(WaitHandler&& handler) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a WaitHandler. diff --git a/3rdparty/asio/include/asio/basic_file.hpp b/3rdparty/asio/include/asio/basic_file.hpp new file mode 100644 index 00000000000..dbdb6d843d0 --- /dev/null +++ b/3rdparty/asio/include/asio/basic_file.hpp @@ -0,0 +1,824 @@ +// +// basic_file.hpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_FILE_HPP +#define ASIO_BASIC_FILE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_FILE) \ + || defined(GENERATING_DOCUMENTATION) + +#include <string> +#include <utility> +#include "asio/any_io_executor.hpp" +#include "asio/async_result.hpp" +#include "asio/detail/cstdint.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/error.hpp" +#include "asio/execution_context.hpp" +#include "asio/post.hpp" +#include "asio/file_base.hpp" +#if defined(ASIO_HAS_IOCP) +# include "asio/detail/win_iocp_file_service.hpp" +#elif defined(ASIO_HAS_IO_URING) +# include "asio/detail/io_uring_file_service.hpp" +#endif + +#include "asio/detail/push_options.hpp" + +namespace asio { + +#if !defined(ASIO_BASIC_FILE_FWD_DECL) +#define ASIO_BASIC_FILE_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename Executor = any_io_executor> +class basic_file; + +#endif // !defined(ASIO_BASIC_FILE_FWD_DECL) + +/// Provides file functionality. +/** + * The basic_file class template provides functionality that is common to both + * stream-oriented and random-access files. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename Executor> +class basic_file + : public file_base +{ +public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the file type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The file type when rebound to the specified executor. + typedef basic_file<Executor1> other; + }; + + /// The native representation of a file. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#elif defined(ASIO_HAS_IOCP) + typedef detail::win_iocp_file_service::native_handle_type native_handle_type; +#elif defined(ASIO_HAS_IO_URING) + typedef detail::io_uring_file_service::native_handle_type native_handle_type; +#endif + + /// Construct a basic_file without opening it. + /** + * This constructor initialises a file without opening it. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + */ + explicit basic_file(const executor_type& ex) + : impl_(0, ex) + { + } + + /// Construct a basic_file without opening it. + /** + * This constructor initialises a file without opening it. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + */ + template <typename ExecutionContext> + explicit basic_file(ExecutionContext& context, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(0, 0, context) + { + } + + /// Construct and open a basic_file. + /** + * This constructor initialises a file and opens it. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + */ + explicit basic_file(const executor_type& ex, + const char* path, file_base::flags open_flags) + : impl_(0, ex) + { + asio::error_code ec; + impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Construct a basic_file without opening it. + /** + * This constructor initialises a file and opens it. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + */ + template <typename ExecutionContext> + explicit basic_file(ExecutionContext& context, + const char* path, file_base::flags open_flags, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(0, 0, context) + { + asio::error_code ec; + impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Construct and open a basic_file. + /** + * This constructor initialises a file and opens it. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + */ + explicit basic_file(const executor_type& ex, + const std::string& path, file_base::flags open_flags) + : impl_(0, ex) + { + asio::error_code ec; + impl_.get_service().open(impl_.get_implementation(), + path.c_str(), open_flags, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Construct a basic_file without opening it. + /** + * This constructor initialises a file and opens it. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + */ + template <typename ExecutionContext> + explicit basic_file(ExecutionContext& context, + const std::string& path, file_base::flags open_flags, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(0, 0, context) + { + asio::error_code ec; + impl_.get_service().open(impl_.get_implementation(), + path.c_str(), open_flags, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Construct a basic_file on an existing native file handle. + /** + * This constructor initialises a file object to hold an existing native file. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + * + * @param native_file A native file handle. + * + * @throws asio::system_error Thrown on failure. + */ + basic_file(const executor_type& ex, const native_handle_type& native_file) + : impl_(0, ex) + { + asio::error_code ec; + impl_.get_service().assign( + impl_.get_implementation(), native_file, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Construct a basic_file on an existing native file. + /** + * This constructor initialises a file object to hold an existing native file. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + * + * @param native_file A native file. + * + * @throws asio::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_file(ExecutionContext& context, const native_handle_type& native_file, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(0, 0, context) + { + asio::error_code ec; + impl_.get_service().assign( + impl_.get_implementation(), native_file, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Move-construct a basic_file from another. + /** + * This constructor moves a file from one object to another. + * + * @param other The other basic_file object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_file(const executor_type&) constructor. + */ + basic_file(basic_file&& other) noexcept + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_file from another. + /** + * This assignment operator moves a file from one object to another. + * + * @param other The other basic_file object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_file(const executor_type&) constructor. + */ + basic_file& operator=(basic_file&& other) + { + impl_ = std::move(other.impl_); + return *this; + } + + // All files have access to each other's implementations. + template <typename Executor1> + friend class basic_file; + + /// Move-construct a basic_file from a file of another executor type. + /** + * This constructor moves a file from one object to another. + * + * @param other The other basic_file object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_file(const executor_type&) constructor. + */ + template <typename Executor1> + basic_file(basic_file<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_file from a file of another executor type. + /** + * This assignment operator moves a file from one object to another. + * + * @param other The other basic_file object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_file(const executor_type&) constructor. + */ + template <typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_file& + > operator=(basic_file<Executor1>&& other) + { + basic_file tmp(std::move(other)); + impl_ = std::move(tmp.impl_); + return *this; + } + + /// Get the executor associated with the object. + const executor_type& get_executor() noexcept + { + return impl_.get_executor(); + } + + /// Open the file using the specified path. + /** + * This function opens the file so that it will use the specified path. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::stream_file file(my_context); + * file.open("/path/to/my/file", asio::stream_file::read_only); + * @endcode + */ + void open(const char* path, file_base::flags open_flags) + { + asio::error_code ec; + impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Open the file using the specified path. + /** + * This function opens the file so that it will use the specified path. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * asio::stream_file file(my_context); + * asio::error_code ec; + * file.open("/path/to/my/file", asio::stream_file::read_only, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + ASIO_SYNC_OP_VOID open(const char* path, + file_base::flags open_flags, asio::error_code& ec) + { + impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Open the file using the specified path. + /** + * This function opens the file so that it will use the specified path. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @throws asio::system_error Thrown on failure. + * + * @par Example + * @code + * asio::stream_file file(my_context); + * file.open("/path/to/my/file", asio::stream_file::read_only); + * @endcode + */ + void open(const std::string& path, file_base::flags open_flags) + { + asio::error_code ec; + impl_.get_service().open(impl_.get_implementation(), + path.c_str(), open_flags, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Open the file using the specified path. + /** + * This function opens the file so that it will use the specified path. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @param ec Set to indicate what error occurred, if any. + * + * @par Example + * @code + * asio::stream_file file(my_context); + * asio::error_code ec; + * file.open("/path/to/my/file", asio::stream_file::read_only, ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + ASIO_SYNC_OP_VOID open(const std::string& path, + file_base::flags open_flags, asio::error_code& ec) + { + impl_.get_service().open(impl_.get_implementation(), + path.c_str(), open_flags, ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Assign an existing native file to the file. + /* + * This function opens the file to hold an existing native file. + * + * @param native_file A native file. + * + * @throws asio::system_error Thrown on failure. + */ + void assign(const native_handle_type& native_file) + { + asio::error_code ec; + impl_.get_service().assign( + impl_.get_implementation(), native_file, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Assign an existing native file to the file. + /* + * This function opens the file to hold an existing native file. + * + * @param native_file A native file. + * + * @param ec Set to indicate what error occurred, if any. + */ + ASIO_SYNC_OP_VOID assign(const native_handle_type& native_file, + asio::error_code& ec) + { + impl_.get_service().assign( + impl_.get_implementation(), native_file, ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Determine whether the file is open. + bool is_open() const + { + return impl_.get_service().is_open(impl_.get_implementation()); + } + + /// Close the file. + /** + * This function is used to close the file. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. Note that, even if + * the function indicates an error, the underlying descriptor is closed. + */ + void close() + { + asio::error_code ec; + impl_.get_service().close(impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "close"); + } + + /// Close the file. + /** + * This function is used to close the file. Any asynchronous read or write + * operations will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. Note that, even if + * the function indicates an error, the underlying descriptor is closed. + * + * @par Example + * @code + * asio::stream_file file(my_context); + * ... + * asio::error_code ec; + * file.close(ec); + * if (ec) + * { + * // An error occurred. + * } + * @endcode + */ + ASIO_SYNC_OP_VOID close(asio::error_code& ec) + { + impl_.get_service().close(impl_.get_implementation(), ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Release ownership of the underlying native file. + /** + * This function causes all outstanding asynchronous read and write + * operations to finish immediately, and the handlers for cancelled + * operations will be passed the asio::error::operation_aborted error. + * Ownership of the native file is then transferred to the caller. + * + * @throws asio::system_error Thrown on failure. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with asio::error::operation_not_supported on + * these platforms. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release() + { + asio::error_code ec; + native_handle_type s = impl_.get_service().release( + impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "release"); + return s; + } + + /// Release ownership of the underlying native file. + /** + * This function causes all outstanding asynchronous read and write + * operations to finish immediately, and the handlers for cancelled + * operations will be passed the asio::error::operation_aborted error. + * Ownership of the native file is then transferred to the caller. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with asio::error::operation_not_supported on + * these platforms. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release(asio::error_code& ec) + { + return impl_.get_service().release(impl_.get_implementation(), ec); + } + + /// Get the native file representation. + /** + * This function may be used to obtain the underlying representation of the + * file. This is intended to allow access to native file functionality + * that is not otherwise provided. + */ + native_handle_type native_handle() + { + return impl_.get_service().native_handle(impl_.get_implementation()); + } + + /// Cancel all asynchronous operations associated with the file. + /** + * This function causes all outstanding asynchronous read and write + * operations to finish immediately, and the handlers for cancelled + * operations will be passed the asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + * + * @note Calls to cancel() will always fail with + * asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using the close() function to + * simultaneously cancel the outstanding operations and close the file. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ + && !defined(ASIO_ENABLE_CANCELIO) + __declspec(deprecated("By default, this function always fails with " + "operation_not_supported when used on Windows XP, Windows Server 2003, " + "or earlier. Consult documentation for details.")) +#endif + void cancel() + { + asio::error_code ec; + impl_.get_service().cancel(impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the file. + /** + * This function causes all outstanding asynchronous read and write + * operations to finish immediately, and the handlers for cancelled + * operations will be passed the asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note Calls to cancel() will always fail with + * asio::error::operation_not_supported when run on Windows XP, Windows + * Server 2003, and earlier versions of Windows, unless + * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has + * two issues that should be considered before enabling its use: + * + * @li It will only cancel asynchronous operations that were initiated in the + * current thread. + * + * @li It can appear to complete without error, but the request to cancel the + * unfinished operations may be silently ignored by the operating system. + * Whether it works or not seems to depend on the drivers that are installed. + * + * For portable cancellation, consider using the close() function to + * simultaneously cancel the outstanding operations and close the file. + * + * When running on Windows Vista, Windows Server 2008, and later, the + * CancelIoEx function is always used. This function does not have the + * problems described above. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \ + && !defined(ASIO_ENABLE_CANCELIO) + __declspec(deprecated("By default, this function always fails with " + "operation_not_supported when used on Windows XP, Windows Server 2003, " + "or earlier. Consult documentation for details.")) +#endif + ASIO_SYNC_OP_VOID cancel(asio::error_code& ec) + { + impl_.get_service().cancel(impl_.get_implementation(), ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Get the size of the file. + /** + * This function determines the size of the file, in bytes. + * + * @throws asio::system_error Thrown on failure. + */ + uint64_t size() const + { + asio::error_code ec; + uint64_t s = impl_.get_service().size(impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "size"); + return s; + } + + /// Get the size of the file. + /** + * This function determines the size of the file, in bytes. + * + * @param ec Set to indicate what error occurred, if any. + */ + uint64_t size(asio::error_code& ec) const + { + return impl_.get_service().size(impl_.get_implementation(), ec); + } + + /// Alter the size of the file. + /** + * This function resizes the file to the specified size, in bytes. If the + * current file size exceeds @c n then any extra data is discarded. If the + * current size is less than @c n then the file is extended and filled with + * zeroes. + * + * @param n The new size for the file. + * + * @throws asio::system_error Thrown on failure. + */ + void resize(uint64_t n) + { + asio::error_code ec; + impl_.get_service().resize(impl_.get_implementation(), n, ec); + asio::detail::throw_error(ec, "resize"); + } + + /// Alter the size of the file. + /** + * This function resizes the file to the specified size, in bytes. If the + * current file size exceeds @c n then any extra data is discarded. If the + * current size is less than @c n then the file is extended and filled with + * zeroes. + * + * @param n The new size for the file. + * + * @param ec Set to indicate what error occurred, if any. + */ + ASIO_SYNC_OP_VOID resize(uint64_t n, asio::error_code& ec) + { + impl_.get_service().resize(impl_.get_implementation(), n, ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Synchronise the file to disk. + /** + * This function synchronises the file data and metadata to disk. Note that + * the semantics of this synchronisation vary between operation systems. + * + * @throws asio::system_error Thrown on failure. + */ + void sync_all() + { + asio::error_code ec; + impl_.get_service().sync_all(impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "sync_all"); + } + + /// Synchronise the file to disk. + /** + * This function synchronises the file data and metadata to disk. Note that + * the semantics of this synchronisation vary between operation systems. + * + * @param ec Set to indicate what error occurred, if any. + */ + ASIO_SYNC_OP_VOID sync_all(asio::error_code& ec) + { + impl_.get_service().sync_all(impl_.get_implementation(), ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Synchronise the file data to disk. + /** + * This function synchronises the file data to disk. Note that the semantics + * of this synchronisation vary between operation systems. + * + * @throws asio::system_error Thrown on failure. + */ + void sync_data() + { + asio::error_code ec; + impl_.get_service().sync_data(impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "sync_data"); + } + + /// Synchronise the file data to disk. + /** + * This function synchronises the file data to disk. Note that the semantics + * of this synchronisation vary between operation systems. + * + * @param ec Set to indicate what error occurred, if any. + */ + ASIO_SYNC_OP_VOID sync_data(asio::error_code& ec) + { + impl_.get_service().sync_data(impl_.get_implementation(), ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + +protected: + /// Protected destructor to prevent deletion through this type. + /** + * This function destroys the file, cancelling any outstanding asynchronous + * operations associated with the file as if by calling @c cancel. + */ + ~basic_file() + { + } + +#if defined(ASIO_HAS_IOCP) + detail::io_object_impl<detail::win_iocp_file_service, Executor> impl_; +#elif defined(ASIO_HAS_IO_URING) + detail::io_object_impl<detail::io_uring_file_service, Executor> impl_; +#endif + +private: + // Disallow copying and assignment. + basic_file(const basic_file&) = delete; + basic_file& operator=(const basic_file&) = delete; +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_FILE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_BASIC_FILE_HPP diff --git a/3rdparty/asio/include/asio/basic_io_object.hpp b/3rdparty/asio/include/asio/basic_io_object.hpp index 733557e3e10..7e502206ff8 100644 --- a/3rdparty/asio/include/asio/basic_io_object.hpp +++ b/3rdparty/asio/include/asio/basic_io_object.hpp @@ -2,7 +2,7 @@ // basic_io_object.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,7 +22,6 @@ namespace asio { -#if defined(ASIO_HAS_MOVE) namespace detail { // Type trait used to determine whether a service supports move. @@ -45,14 +44,13 @@ namespace detail static_cast<implementation_type*>(0))) == 1; }; } -#endif // defined(ASIO_HAS_MOVE) /// Base class for all I/O objects. /** * @note All I/O objects are non-copyable. However, when using C++0x, certain * I/O objects do support move construction and move assignment. */ -#if !defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) +#if defined(GENERATING_DOCUMENTATION) template <typename IoObjectService> #else template <typename IoObjectService, @@ -101,7 +99,7 @@ public: typedef asio::io_context::executor_type executor_type; /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + executor_type get_executor() noexcept { return service_.get_io_context().get_executor(); } @@ -190,7 +188,6 @@ private: implementation_type implementation_; }; -#if defined(ASIO_HAS_MOVE) // Specialisation for movable objects. template <typename IoObjectService> class basic_io_object<IoObjectService, true> @@ -213,7 +210,7 @@ public: typedef asio::io_context::executor_type executor_type; - executor_type get_executor() ASIO_NOEXCEPT + executor_type get_executor() noexcept { return service_->get_io_context().get_executor(); } @@ -281,7 +278,6 @@ private: IoObjectService* service_; implementation_type implementation_; }; -#endif // defined(ASIO_HAS_MOVE) } // namespace asio diff --git a/3rdparty/asio/include/asio/basic_random_access_file.hpp b/3rdparty/asio/include/asio/basic_random_access_file.hpp new file mode 100644 index 00000000000..fe88f420560 --- /dev/null +++ b/3rdparty/asio/include/asio/basic_random_access_file.hpp @@ -0,0 +1,689 @@ +// +// basic_random_access_file.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_RANDOM_ACCESS_FILE_HPP +#define ASIO_BASIC_RANDOM_ACCESS_FILE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_FILE) \ + || defined(GENERATING_DOCUMENTATION) + +#include <cstddef> +#include "asio/async_result.hpp" +#include "asio/basic_file.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +#if !defined(ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL) +#define ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename Executor = any_io_executor> +class basic_random_access_file; + +#endif // !defined(ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL) + +/// Provides random-access file functionality. +/** + * The basic_random_access_file class template provides asynchronous and + * blocking random-access file functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * Synchronous @c read_some_at and @c write_some_at operations are thread safe + * with respect to each other, if the underlying operating system calls are + * also thread safe. This means that it is permitted to perform concurrent + * calls to these synchronous operations on a single file object. Other + * synchronous operations, such as @c open or @c close, are not thread safe. + */ +template <typename Executor> +class basic_random_access_file + : public basic_file<Executor> +{ +private: + class initiate_async_write_some_at; + class initiate_async_read_some_at; + +public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the file type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The file type when rebound to the specified executor. + typedef basic_random_access_file<Executor1> other; + }; + + /// The native representation of a file. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#else + typedef typename basic_file<Executor>::native_handle_type native_handle_type; +#endif + + /// Construct a basic_random_access_file without opening it. + /** + * This constructor initialises a file without opening it. The file needs to + * be opened before data can be read from or or written to it. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + */ + explicit basic_random_access_file(const executor_type& ex) + : basic_file<Executor>(ex) + { + } + + /// Construct a basic_random_access_file without opening it. + /** + * This constructor initialises a file without opening it. The file needs to + * be opened before data can be read from or or written to it. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + */ + template <typename ExecutionContext> + explicit basic_random_access_file(ExecutionContext& context, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_file<Executor>(context) + { + } + + /// Construct and open a basic_random_access_file. + /** + * This constructor initialises and opens a file. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @throws asio::system_error Thrown on failure. + */ + basic_random_access_file(const executor_type& ex, + const char* path, file_base::flags open_flags) + : basic_file<Executor>(ex, path, open_flags) + { + } + + /// Construct and open a basic_random_access_file. + /** + * This constructor initialises and opens a file. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @throws asio::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_random_access_file(ExecutionContext& context, + const char* path, file_base::flags open_flags, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_file<Executor>(context, path, open_flags) + { + } + + /// Construct and open a basic_random_access_file. + /** + * This constructor initialises and opens a file. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @throws asio::system_error Thrown on failure. + */ + basic_random_access_file(const executor_type& ex, + const std::string& path, file_base::flags open_flags) + : basic_file<Executor>(ex, path, open_flags) + { + } + + /// Construct and open a basic_random_access_file. + /** + * This constructor initialises and opens a file. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @throws asio::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_random_access_file(ExecutionContext& context, + const std::string& path, file_base::flags open_flags, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_file<Executor>(context, path, open_flags) + { + } + + /// Construct a basic_random_access_file on an existing native file. + /** + * This constructor initialises a random-access file object to hold an + * existing native file. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + * + * @param native_file The new underlying file implementation. + * + * @throws asio::system_error Thrown on failure. + */ + basic_random_access_file(const executor_type& ex, + const native_handle_type& native_file) + : basic_file<Executor>(ex, native_file) + { + } + + /// Construct a basic_random_access_file on an existing native file. + /** + * This constructor initialises a random-access file object to hold an + * existing native file. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + * + * @param native_file The new underlying file implementation. + * + * @throws asio::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_random_access_file(ExecutionContext& context, + const native_handle_type& native_file, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_file<Executor>(context, native_file) + { + } + + /// Move-construct a basic_random_access_file from another. + /** + * This constructor moves a random-access file from one object to another. + * + * @param other The other basic_random_access_file object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_random_access_file(const executor_type&) + * constructor. + */ + basic_random_access_file(basic_random_access_file&& other) noexcept + : basic_file<Executor>(std::move(other)) + { + } + + /// Move-assign a basic_random_access_file from another. + /** + * This assignment operator moves a random-access file from one object to + * another. + * + * @param other The other basic_random_access_file object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_random_access_file(const executor_type&) + * constructor. + */ + basic_random_access_file& operator=(basic_random_access_file&& other) + { + basic_file<Executor>::operator=(std::move(other)); + return *this; + } + + /// Move-construct a basic_random_access_file from a file of another executor + /// type. + /** + * This constructor moves a random-access file from one object to another. + * + * @param other The other basic_random_access_file object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_random_access_file(const executor_type&) + * constructor. + */ + template <typename Executor1> + basic_random_access_file(basic_random_access_file<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_file<Executor>(std::move(other)) + { + } + + /// Move-assign a basic_random_access_file from a file of another executor + /// type. + /** + * This assignment operator moves a random-access file from one object to + * another. + * + * @param other The other basic_random_access_file object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_random_access_file(const executor_type&) + * constructor. + */ + template <typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_random_access_file& + > operator=(basic_random_access_file<Executor1>&& other) + { + basic_file<Executor>::operator=(std::move(other)); + return *this; + } + + /// Destroys the file. + /** + * This function destroys the file, cancelling any outstanding asynchronous + * operations associated with the file as if by calling @c cancel. + */ + ~basic_random_access_file() + { + } + + /// Write some data to the handle at the specified offset. + /** + * This function is used to write data to the random-access handle. The + * function call will block until one or more bytes of the data has been + * written successfully, or until an error occurs. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @returns The number of bytes written. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the end of the file was reached. + * + * @note The write_some_at operation may not write all of the data. Consider + * using the @ref write_at function if you need to ensure that all data is + * written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.write_some_at(42, asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t write_some_at(uint64_t offset, + const ConstBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->impl_.get_service().write_some_at( + this->impl_.get_implementation(), offset, buffers, ec); + asio::detail::throw_error(ec, "write_some_at"); + return s; + } + + /// Write some data to the handle at the specified offset. + /** + * This function is used to write data to the random-access handle. The + * function call will block until one or more bytes of the data has been + * written successfully, or until an error occurs. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not write all of the data to the + * file. Consider using the @ref write_at function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template <typename ConstBufferSequence> + std::size_t write_some_at(uint64_t offset, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return this->impl_.get_service().write_some_at( + this->impl_.get_implementation(), offset, buffers, ec); + } + + /// Start an asynchronous write at the specified offset. + /** + * This function is used to asynchronously write data to the random-access + * handle. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. + * + * @param offset The offset at which the data will be written. + * + * @param buffers One or more data buffers to be written to the handle. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the completion handler is called. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a + * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * + * @note The write operation may not write all of the data to the file. + * Consider using the @ref async_write_at function if you need to ensure that + * all data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_write_some_at(42, asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @par Per-Operation Cancellation + * This asynchronous operation supports cancellation for the following + * asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total + */ + template <typename ConstBufferSequence, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_write_some_at(uint64_t offset, const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_write_some_at>(), token, offset, buffers)) + { + return async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + initiate_async_write_some_at(this), token, offset, buffers); + } + + /// Read some data from the handle at the specified offset. + /** + * This function is used to read data from the random-access handle. The + * function call will block until one or more bytes of data has been read + * successfully, or until an error occurs. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the end of the file was reached. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read_at function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.read_some_at(42, asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t read_some_at(uint64_t offset, + const MutableBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->impl_.get_service().read_some_at( + this->impl_.get_implementation(), offset, buffers, ec); + asio::detail::throw_error(ec, "read_some_at"); + return s; + } + + /// Read some data from the handle at the specified offset. + /** + * This function is used to read data from the random-access handle. The + * function call will block until one or more bytes of data has been read + * successfully, or until an error occurs. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read_at function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template <typename MutableBufferSequence> + std::size_t read_some_at(uint64_t offset, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return this->impl_.get_service().read_some_at( + this->impl_.get_implementation(), offset, buffers, ec); + } + + /// Start an asynchronous read at the specified offset. + /** + * This function is used to asynchronously read data from the random-access + * handle. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. + * + * @param offset The offset at which the data will be read. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the completion handler is called. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a + * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read_at function if you need to ensure that + * the requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * handle.async_read_some_at(42, asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @par Per-Operation Cancellation + * This asynchronous operation supports cancellation for the following + * asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total + */ + template <typename MutableBufferSequence, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_read_some_at(uint64_t offset, const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_read_some_at>(), token, offset, buffers)) + { + return async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + initiate_async_read_some_at(this), token, offset, buffers); + } + +private: + // Disallow copying and assignment. + basic_random_access_file(const basic_random_access_file&) = delete; + basic_random_access_file& operator=( + const basic_random_access_file&) = delete; + + class initiate_async_write_some_at + { + public: + typedef Executor executor_type; + + explicit initiate_async_write_some_at(basic_random_access_file* self) + : self_(self) + { + } + + const executor_type& get_executor() const noexcept + { + return self_->get_executor(); + } + + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(WriteHandler&& handler, + uint64_t offset, const ConstBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue<WriteHandler> handler2(handler); + self_->impl_.get_service().async_write_some_at( + self_->impl_.get_implementation(), offset, buffers, + handler2.value, self_->impl_.get_executor()); + } + + private: + basic_random_access_file* self_; + }; + + class initiate_async_read_some_at + { + public: + typedef Executor executor_type; + + explicit initiate_async_read_some_at(basic_random_access_file* self) + : self_(self) + { + } + + const executor_type& get_executor() const noexcept + { + return self_->get_executor(); + } + + template <typename ReadHandler, typename MutableBufferSequence> + void operator()(ReadHandler&& handler, + uint64_t offset, const MutableBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue<ReadHandler> handler2(handler); + self_->impl_.get_service().async_read_some_at( + self_->impl_.get_implementation(), offset, buffers, + handler2.value, self_->impl_.get_executor()); + } + + private: + basic_random_access_file* self_; + }; +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_FILE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_BASIC_RANDOM_ACCESS_FILE_HPP diff --git a/3rdparty/asio/include/asio/basic_raw_socket.hpp b/3rdparty/asio/include/asio/basic_raw_socket.hpp index d48885dfc45..112090900ce 100644 --- a/3rdparty/asio/include/asio/basic_raw_socket.hpp +++ b/3rdparty/asio/include/asio/basic_raw_socket.hpp @@ -2,7 +2,7 @@ // basic_raw_socket.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -46,17 +46,23 @@ class basic_raw_socket; * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. * - * Synchronous @c send, @c send_to, @c receive, @c receive_from, and @c connect - * operations are thread safe with respect to each other, if the underlying - * operating system calls are also thread safe. This means that it is permitted - * to perform concurrent calls to these synchronous operations on a single - * socket object. Other synchronous operations, such as @c open or @c close, are - * not thread safe. + * Synchronous @c send, @c send_to, @c receive, @c receive_from, @c connect, + * and @c shutdown operations are thread safe with respect to each other, if + * the underlying operating system calls are also thread safe. This means that + * it is permitted to perform concurrent calls to these synchronous operations + * on a single socket object. Other synchronous operations, such as @c open or + * @c close, are not thread safe. */ template <typename Protocol, typename Executor> class basic_raw_socket : public basic_socket<Protocol, Executor> { +private: + class initiate_async_send; + class initiate_async_send_to; + class initiate_async_receive; + class initiate_async_receive_from; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -107,9 +113,9 @@ public: */ template <typename ExecutionContext> explicit basic_raw_socket(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context) { } @@ -144,10 +150,10 @@ public: */ template <typename ExecutionContext> basic_raw_socket(ExecutionContext& context, const protocol_type& protocol, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : basic_socket<Protocol, Executor>(context, protocol) { } @@ -190,9 +196,9 @@ public: */ template <typename ExecutionContext> basic_raw_socket(ExecutionContext& context, const endpoint_type& endpoint, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context, endpoint) { } @@ -235,14 +241,13 @@ public: template <typename ExecutionContext> basic_raw_socket(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_socket, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context, protocol, native_socket) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a basic_raw_socket from another. /** * This constructor moves a raw socket from one object to another. @@ -254,7 +259,7 @@ public: * constructed using the @c basic_raw_socket(const executor_type&) * constructor. */ - basic_raw_socket(basic_raw_socket&& other) ASIO_NOEXCEPT + basic_raw_socket(basic_raw_socket&& other) noexcept : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -290,10 +295,10 @@ public: */ template <typename Protocol1, typename Executor1> basic_raw_socket(basic_raw_socket<Protocol1, Executor1>&& other, - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -310,16 +315,15 @@ public: * constructor. */ template <typename Protocol1, typename Executor1> - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_raw_socket& - >::type operator=(basic_raw_socket<Protocol1, Executor1>&& other) + > operator=(basic_raw_socket<Protocol1, Executor1>&& other) { basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destroys the socket. /** @@ -414,26 +418,32 @@ public: /// Start an asynchronous send on a connected socket. /** - * This function is used to send data on the raw socket. The function call - * will block until the data has been sent successfully or an error occurs. + * This function is used to asynchronously send data on the raw socket. It is + * an initiating function for an @ref asynchronous_operation, and always + * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. + * remain valid until the completion handler is called. * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the send completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. + * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected raw * socket. @@ -459,44 +469,51 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_send(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_send(const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send>(), token, + buffers, socket_base::message_flags(0))) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send(this), handler, + initiate_async_send(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous send on a connected socket. /** - * This function is used to send data on the raw socket. The function call - * will block until the data has been sent successfully or an error occurs. + * This function is used to asynchronously send data on the raw socket. It is + * an initiating function for an @ref asynchronous_operation, and always + * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. + * remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the send completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. + * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The async_send operation can only be used with a connected socket. * Use the async_send_to function to send data on an unconnected raw * socket. @@ -513,18 +530,18 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_send(const ConstBufferSequence& buffers, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send>(), token, buffers, flags)) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send(this), handler, buffers, flags); + initiate_async_send(this), token, buffers, flags); } /// Send raw data to the specified endpoint. @@ -618,28 +635,34 @@ public: /// Start an asynchronous send. /** * This function is used to asynchronously send raw data to the specified - * remote endpoint. The function call always returns immediately. + * remote endpoint. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param buffers One or more data buffers to be sent to the remote endpoint. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param destination The remote endpoint to which the data will be sent. * Copies will be made of the endpoint as required. * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the send completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. + * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To send a single data buffer use the @ref buffer function as follows: * @code @@ -664,48 +687,55 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_send_to(const ConstBufferSequence& buffers, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send_to>(), token, buffers, + destination, socket_base::message_flags(0))) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send_to(this), handler, buffers, + initiate_async_send_to(this), token, buffers, destination, socket_base::message_flags(0)); } /// Start an asynchronous send. /** * This function is used to asynchronously send raw data to the specified - * remote endpoint. The function call always returns immediately. + * remote endpoint. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param buffers One or more data buffers to be sent to the remote endpoint. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. * * @param destination The remote endpoint to which the data will be sent. * Copies will be made of the endpoint as required. * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the send completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. + * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * On POSIX or Windows operating systems, this asynchronous operation supports * cancellation for the following asio::cancellation_type values: @@ -718,18 +748,20 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_send_to(const ConstBufferSequence& buffers, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_send_to(const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send_to>(), token, + buffers, destination, flags)) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send_to(this), handler, buffers, destination, flags); + initiate_async_send_to(this), token, + buffers, destination, flags); } /// Receive some data on a connected socket. @@ -824,25 +856,31 @@ public: /// Start an asynchronous receive on a connected socket. /** * This function is used to asynchronously receive data from the raw - * socket. The function call always returns immediately. + * socket. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected * raw socket. @@ -869,44 +907,51 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_receive(const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive>(), token, + buffers, socket_base::message_flags(0))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive(this), handler, + initiate_async_receive(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive on a connected socket. /** * This function is used to asynchronously receive data from the raw - * socket. The function call always returns immediately. + * socket. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param flags Flags specifying how the receive call is to be made. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The async_receive operation can only be used with a connected socket. * Use the async_receive_from function to receive data on an unconnected * raw socket. @@ -923,18 +968,19 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive(const MutableBufferSequence& buffers, + std::size_t)) ReadToken + = default_completion_token_t<executor_type>> + auto async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive>(), token, buffers, flags)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive(this), handler, buffers, flags); + initiate_async_receive(this), token, buffers, flags); } /// Receive raw data with the endpoint of the sender. @@ -1028,31 +1074,37 @@ public: /// Start an asynchronous receive. /** - * This function is used to asynchronously receive raw data. The function - * call always returns immediately. + * This function is used to asynchronously receive raw data. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param sender_endpoint An endpoint object that receives the endpoint of * the remote sender of the data. Ownership of the sender_endpoint object * is retained by the caller, which must guarantee that it is valid until the - * handler is called. + * completion handler is called. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To receive into a single data buffer use the @ref buffer function as * follows: @@ -1074,50 +1126,58 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive_from(const MutableBufferSequence& buffers, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ReadToken&& token + = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive_from>(), token, buffers, + &sender_endpoint, socket_base::message_flags(0))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive_from(this), handler, buffers, + initiate_async_receive_from(this), token, buffers, &sender_endpoint, socket_base::message_flags(0)); } /// Start an asynchronous receive. /** - * This function is used to asynchronously receive raw data. The function - * call always returns immediately. + * This function is used to asynchronously receive raw data. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param sender_endpoint An endpoint object that receives the endpoint of * the remote sender of the data. Ownership of the sender_endpoint object * is retained by the caller, which must guarantee that it is valid until the - * handler is called. + * completion handler is called. * * @param flags Flags specifying how the receive call is to be made. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * On POSIX or Windows operating systems, this asynchronous operation supports * cancellation for the following asio::cancellation_type values: @@ -1130,25 +1190,27 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive_from(const MutableBufferSequence& buffers, + std::size_t)) ReadToken + = default_completion_token_t<executor_type>> + auto async_receive_from(const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, socket_base::message_flags flags, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive_from>(), token, + buffers, &sender_endpoint, flags)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive_from(this), handler, + initiate_async_receive_from(this), token, buffers, &sender_endpoint, flags); } private: // Disallow copying and assignment. - basic_raw_socket(const basic_raw_socket&) ASIO_DELETED; - basic_raw_socket& operator=(const basic_raw_socket&) ASIO_DELETED; + basic_raw_socket(const basic_raw_socket&) = delete; + basic_raw_socket& operator=(const basic_raw_socket&) = delete; class initiate_async_send { @@ -1160,13 +1222,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, const ConstBufferSequence& buffers, socket_base::message_flags flags) const { @@ -1194,13 +1256,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, const ConstBufferSequence& buffers, const endpoint_type& destination, socket_base::message_flags flags) const { @@ -1228,13 +1290,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, const MutableBufferSequence& buffers, socket_base::message_flags flags) const { @@ -1262,13 +1324,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, const MutableBufferSequence& buffers, endpoint_type* sender_endpoint, socket_base::message_flags flags) const { diff --git a/3rdparty/asio/include/asio/basic_readable_pipe.hpp b/3rdparty/asio/include/asio/basic_readable_pipe.hpp new file mode 100644 index 00000000000..9a5a0653f6b --- /dev/null +++ b/3rdparty/asio/include/asio/basic_readable_pipe.hpp @@ -0,0 +1,626 @@ +// +// basic_readable_pipe.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_READABLE_PIPE_HPP +#define ASIO_BASIC_READABLE_PIPE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PIPE) \ + || defined(GENERATING_DOCUMENTATION) + +#include <string> +#include <utility> +#include "asio/any_io_executor.hpp" +#include "asio/async_result.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/error.hpp" +#include "asio/execution_context.hpp" +#if defined(ASIO_HAS_IOCP) +# include "asio/detail/win_iocp_handle_service.hpp" +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/io_uring_descriptor_service.hpp" +#else +# include "asio/detail/reactive_descriptor_service.hpp" +#endif + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Provides pipe functionality. +/** + * The basic_readable_pipe class provides a wrapper over pipe + * functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename Executor = any_io_executor> +class basic_readable_pipe +{ +private: + class initiate_async_read_some; + +public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the pipe type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The pipe type when rebound to the specified executor. + typedef basic_readable_pipe<Executor1> other; + }; + + /// The native representation of a pipe. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#elif defined(ASIO_HAS_IOCP) + typedef detail::win_iocp_handle_service::native_handle_type + native_handle_type; +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) + typedef detail::io_uring_descriptor_service::native_handle_type + native_handle_type; +#else + typedef detail::reactive_descriptor_service::native_handle_type + native_handle_type; +#endif + + /// A basic_readable_pipe is always the lowest layer. + typedef basic_readable_pipe lowest_layer_type; + + /// Construct a basic_readable_pipe without opening it. + /** + * This constructor creates a pipe without opening it. + * + * @param ex The I/O executor that the pipe will use, by default, to dispatch + * handlers for any asynchronous operations performed on the pipe. + */ + explicit basic_readable_pipe(const executor_type& ex) + : impl_(0, ex) + { + } + + /// Construct a basic_readable_pipe without opening it. + /** + * This constructor creates a pipe without opening it. + * + * @param context An execution context which provides the I/O executor that + * the pipe will use, by default, to dispatch handlers for any asynchronous + * operations performed on the pipe. + */ + template <typename ExecutionContext> + explicit basic_readable_pipe(ExecutionContext& context, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(0, 0, context) + { + } + + /// Construct a basic_readable_pipe on an existing native pipe. + /** + * This constructor creates a pipe object to hold an existing native + * pipe. + * + * @param ex The I/O executor that the pipe will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * pipe. + * + * @param native_pipe A native pipe. + * + * @throws asio::system_error Thrown on failure. + */ + basic_readable_pipe(const executor_type& ex, + const native_handle_type& native_pipe) + : impl_(0, ex) + { + asio::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + native_pipe, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Construct a basic_readable_pipe on an existing native pipe. + /** + * This constructor creates a pipe object to hold an existing native + * pipe. + * + * @param context An execution context which provides the I/O executor that + * the pipe will use, by default, to dispatch handlers for any + * asynchronous operations performed on the pipe. + * + * @param native_pipe A native pipe. + * + * @throws asio::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_readable_pipe(ExecutionContext& context, + const native_handle_type& native_pipe, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) + : impl_(0, 0, context) + { + asio::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + native_pipe, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Move-construct a basic_readable_pipe from another. + /** + * This constructor moves a pipe from one object to another. + * + * @param other The other basic_readable_pipe object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_readable_pipe(const executor_type&) + * constructor. + */ + basic_readable_pipe(basic_readable_pipe&& other) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_readable_pipe from another. + /** + * This assignment operator moves a pipe from one object to another. + * + * @param other The other basic_readable_pipe object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_readable_pipe(const executor_type&) + * constructor. + */ + basic_readable_pipe& operator=(basic_readable_pipe&& other) + { + impl_ = std::move(other.impl_); + return *this; + } + + // All pipes have access to each other's implementations. + template <typename Executor1> + friend class basic_readable_pipe; + + /// Move-construct a basic_readable_pipe from a pipe of another executor type. + /** + * This constructor moves a pipe from one object to another. + * + * @param other The other basic_readable_pipe object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_readable_pipe(const executor_type&) + * constructor. + */ + template <typename Executor1> + basic_readable_pipe(basic_readable_pipe<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_readable_pipe from a pipe of another executor type. + /** + * This assignment operator moves a pipe from one object to another. + * + * @param other The other basic_readable_pipe object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_readable_pipe(const executor_type&) + * constructor. + */ + template <typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_readable_pipe& + > operator=(basic_readable_pipe<Executor1>&& other) + { + basic_readable_pipe tmp(std::move(other)); + impl_ = std::move(tmp.impl_); + return *this; + } + + /// Destroys the pipe. + /** + * This function destroys the pipe, cancelling any outstanding + * asynchronous wait operations associated with the pipe as if by + * calling @c cancel. + */ + ~basic_readable_pipe() + { + } + + /// Get the executor associated with the object. + const executor_type& get_executor() noexcept + { + return impl_.get_executor(); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_readable_pipe cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Get a const reference to the lowest layer. + /** + * This function returns a const reference to the lowest layer in a stack of + * layers. Since a basic_readable_pipe cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A const reference to the lowest layer in the stack of layers. + * Ownership is not transferred to the caller. + */ + const lowest_layer_type& lowest_layer() const + { + return *this; + } + + /// Assign an existing native pipe to the pipe. + /* + * This function opens the pipe to hold an existing native pipe. + * + * @param native_pipe A native pipe. + * + * @throws asio::system_error Thrown on failure. + */ + void assign(const native_handle_type& native_pipe) + { + asio::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Assign an existing native pipe to the pipe. + /* + * This function opens the pipe to hold an existing native pipe. + * + * @param native_pipe A native pipe. + * + * @param ec Set to indicate what error occurred, if any. + */ + ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe, + asio::error_code& ec) + { + impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Determine whether the pipe is open. + bool is_open() const + { + return impl_.get_service().is_open(impl_.get_implementation()); + } + + /// Close the pipe. + /** + * This function is used to close the pipe. Any asynchronous read operations + * will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + */ + void close() + { + asio::error_code ec; + impl_.get_service().close(impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "close"); + } + + /// Close the pipe. + /** + * This function is used to close the pipe. Any asynchronous read operations + * will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + ASIO_SYNC_OP_VOID close(asio::error_code& ec) + { + impl_.get_service().close(impl_.get_implementation(), ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Release ownership of the underlying native pipe. + /** + * This function causes all outstanding asynchronous read operations to + * finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. Ownership of the + * native pipe is then transferred to the caller. + * + * @throws asio::system_error Thrown on failure. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with asio::error::operation_not_supported on + * these platforms. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release() + { + asio::error_code ec; + native_handle_type s = impl_.get_service().release( + impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "release"); + return s; + } + + /// Release ownership of the underlying native pipe. + /** + * This function causes all outstanding asynchronous read operations to + * finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. Ownership of the + * native pipe is then transferred to the caller. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with asio::error::operation_not_supported on + * these platforms. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release(asio::error_code& ec) + { + return impl_.get_service().release(impl_.get_implementation(), ec); + } + + /// Get the native pipe representation. + /** + * This function may be used to obtain the underlying representation of the + * pipe. This is intended to allow access to native pipe + * functionality that is not otherwise provided. + */ + native_handle_type native_handle() + { + return impl_.get_service().native_handle(impl_.get_implementation()); + } + + /// Cancel all asynchronous operations associated with the pipe. + /** + * This function causes all outstanding asynchronous read operations to finish + * immediately, and the handlers for cancelled operations will be passed the + * asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + */ + void cancel() + { + asio::error_code ec; + impl_.get_service().cancel(impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the pipe. + /** + * This function causes all outstanding asynchronous read operations to finish + * immediately, and the handlers for cancelled operations will be passed the + * asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + ASIO_SYNC_OP_VOID cancel(asio::error_code& ec) + { + impl_.get_service().cancel(impl_.get_implementation(), ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Read some data from the pipe. + /** + * This function is used to read data from the pipe. The function call will + * block until one or more bytes of data has been read successfully, or until + * an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * basic_readable_pipe.read_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = impl_.get_service().read_some( + impl_.get_implementation(), buffers, ec); + asio::detail::throw_error(ec, "read_some"); + return s; + } + + /// Read some data from the pipe. + /** + * This function is used to read data from the pipe. The function call will + * block until one or more bytes of data has been read successfully, or until + * an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers, + asio::error_code& ec) + { + return impl_.get_service().read_some( + impl_.get_implementation(), buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the pipe. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the completion handler is called. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a + * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * basic_readable_pipe.async_read_some( + * asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_read_some(const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_read_some>(), token, buffers)) + { + return async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + initiate_async_read_some(this), token, buffers); + } + +private: + // Disallow copying and assignment. + basic_readable_pipe(const basic_readable_pipe&) = delete; + basic_readable_pipe& operator=(const basic_readable_pipe&) = delete; + + class initiate_async_read_some + { + public: + typedef Executor executor_type; + + explicit initiate_async_read_some(basic_readable_pipe* self) + : self_(self) + { + } + + const executor_type& get_executor() const noexcept + { + return self_->get_executor(); + } + + template <typename ReadHandler, typename MutableBufferSequence> + void operator()(ReadHandler&& handler, + const MutableBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue<ReadHandler> handler2(handler); + self_->impl_.get_service().async_read_some( + self_->impl_.get_implementation(), buffers, + handler2.value, self_->impl_.get_executor()); + } + + private: + basic_readable_pipe* self_; + }; + +#if defined(ASIO_HAS_IOCP) + detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_; +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) + detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_; +#else + detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_; +#endif +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_PIPE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_BASIC_READABLE_PIPE_HPP diff --git a/3rdparty/asio/include/asio/basic_seq_packet_socket.hpp b/3rdparty/asio/include/asio/basic_seq_packet_socket.hpp index a1f6d99831f..cf2a4b6ad71 100644 --- a/3rdparty/asio/include/asio/basic_seq_packet_socket.hpp +++ b/3rdparty/asio/include/asio/basic_seq_packet_socket.hpp @@ -2,7 +2,7 @@ // basic_seq_packet_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -44,16 +44,21 @@ class basic_seq_packet_socket; * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. * - * Synchronous @c send, @c receive, and @c connect operations are thread safe - * with respect to each other, if the underlying operating system calls are - * also thread safe. This means that it is permitted to perform concurrent - * calls to these synchronous operations on a single socket object. Other - * synchronous operations, such as @c open or @c close, are not thread safe. + * Synchronous @c send, @c receive, @c connect, and @c shutdown operations are + * thread safe with respect to each other, if the underlying operating system + * calls are also thread safe. This means that it is permitted to perform + * concurrent calls to these synchronous operations on a single socket object. + * Other synchronous operations, such as @c open or @c close, are not thread + * safe. */ template <typename Protocol, typename Executor> class basic_seq_packet_socket : public basic_socket<Protocol, Executor> { +private: + class initiate_async_send; + class initiate_async_receive_with_flags; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -106,9 +111,9 @@ public: */ template <typename ExecutionContext> explicit basic_seq_packet_socket(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context) { } @@ -149,10 +154,10 @@ public: template <typename ExecutionContext> basic_seq_packet_socket(ExecutionContext& context, const protocol_type& protocol, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : basic_socket<Protocol, Executor>(context, protocol) { } @@ -197,9 +202,9 @@ public: template <typename ExecutionContext> basic_seq_packet_socket(ExecutionContext& context, const endpoint_type& endpoint, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context, endpoint) { } @@ -242,14 +247,13 @@ public: template <typename ExecutionContext> basic_seq_packet_socket(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_socket, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context, protocol, native_socket) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a basic_seq_packet_socket from another. /** * This constructor moves a sequenced packet socket from one object to @@ -262,7 +266,7 @@ public: * constructed using the @c basic_seq_packet_socket(const executor_type&) * constructor. */ - basic_seq_packet_socket(basic_seq_packet_socket&& other) ASIO_NOEXCEPT + basic_seq_packet_socket(basic_seq_packet_socket&& other) noexcept : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -300,10 +304,10 @@ public: */ template <typename Protocol1, typename Executor1> basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other, - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -322,16 +326,15 @@ public: * constructor. */ template <typename Protocol1, typename Executor1> - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_seq_packet_socket& - >::type operator=(basic_seq_packet_socket<Protocol1, Executor1>&& other) + > operator=(basic_seq_packet_socket<Protocol1, Executor1>&& other) { basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destroys the socket. /** @@ -405,27 +408,33 @@ public: /// Start an asynchronous send. /** * This function is used to asynchronously send data on the sequenced packet - * socket. The function call always returns immediately. + * socket. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. + * remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the send completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. + * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To send a single data buffer use the @ref buffer function as follows: * @code @@ -447,18 +456,20 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_send(const ConstBufferSequence& buffers, + std::size_t)) WriteToken + = default_completion_token_t<executor_type>> + auto async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WriteToken&& token + = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send>(), token, buffers, flags)) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send(this), handler, buffers, flags); + initiate_async_send(this), token, buffers, flags); } /// Receive some data on the socket. @@ -583,31 +594,37 @@ public: /// Start an asynchronous receive. /** * This function is used to asynchronously receive data from the sequenced - * packet socket. The function call always returns immediately. + * packet socket. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param out_flags Once the asynchronous operation completes, contains flags * associated with the received data. For example, if the * socket_base::message_end_of_record bit is set then the received data marks * the end of a record. The caller must guarantee that the referenced - * variable remains valid until the handler is called. + * variable remains valid until the completion handler is called. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To receive into a single data buffer use the @ref buffer function as * follows: @@ -630,30 +647,32 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive(const MutableBufferSequence& buffers, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_receive(const MutableBufferSequence& buffers, socket_base::message_flags& out_flags, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive_with_flags>(), token, + buffers, socket_base::message_flags(0), &out_flags)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive_with_flags(this), handler, + initiate_async_receive_with_flags(this), token, buffers, socket_base::message_flags(0), &out_flags); } /// Start an asynchronous receive. /** * This function is used to asynchronously receive data from the sequenced - * data socket. The function call always returns immediately. + * data socket. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param in_flags Flags specifying how the receive call is to be made. * @@ -661,20 +680,25 @@ public: * associated with the received data. For example, if the * socket_base::message_end_of_record bit is set then the received data marks * the end of a record. The caller must guarantee that the referenced - * variable remains valid until the handler is called. + * variable remains valid until the completion handler is called. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To receive into a single data buffer use the @ref buffer function as * follows: @@ -699,27 +723,28 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive(const MutableBufferSequence& buffers, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_receive(const MutableBufferSequence& buffers, socket_base::message_flags in_flags, socket_base::message_flags& out_flags, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive_with_flags>(), + token, buffers, in_flags, &out_flags)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( initiate_async_receive_with_flags(this), - handler, buffers, in_flags, &out_flags); + token, buffers, in_flags, &out_flags); } private: // Disallow copying and assignment. - basic_seq_packet_socket(const basic_seq_packet_socket&) ASIO_DELETED; + basic_seq_packet_socket(const basic_seq_packet_socket&) = delete; basic_seq_packet_socket& operator=( - const basic_seq_packet_socket&) ASIO_DELETED; + const basic_seq_packet_socket&) = delete; class initiate_async_send { @@ -731,13 +756,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, const ConstBufferSequence& buffers, socket_base::message_flags flags) const { @@ -765,13 +790,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, const MutableBufferSequence& buffers, socket_base::message_flags in_flags, socket_base::message_flags* out_flags) const diff --git a/3rdparty/asio/include/asio/basic_serial_port.hpp b/3rdparty/asio/include/asio/basic_serial_port.hpp index 1c0c636976c..8fa66c0b0d7 100644 --- a/3rdparty/asio/include/asio/basic_serial_port.hpp +++ b/3rdparty/asio/include/asio/basic_serial_port.hpp @@ -2,7 +2,7 @@ // basic_serial_port.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -22,6 +22,7 @@ || defined(GENERATING_DOCUMENTATION) #include <string> +#include <utility> #include "asio/any_io_executor.hpp" #include "asio/async_result.hpp" #include "asio/detail/handler_type_requirements.hpp" @@ -35,13 +36,9 @@ #if defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_serial_port_service.hpp" #else -# include "asio/detail/reactive_serial_port_service.hpp" +# include "asio/detail/posix_serial_port_service.hpp" #endif -#if defined(ASIO_HAS_MOVE) -# include <utility> -#endif // defined(ASIO_HAS_MOVE) - #include "asio/detail/push_options.hpp" namespace asio { @@ -59,6 +56,10 @@ template <typename Executor = any_io_executor> class basic_serial_port : public serial_port_base { +private: + class initiate_async_write_some; + class initiate_async_read_some; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -78,7 +79,7 @@ public: typedef detail::win_iocp_serial_port_service::native_handle_type native_handle_type; #else - typedef detail::reactive_serial_port_service::native_handle_type + typedef detail::posix_serial_port_service::native_handle_type native_handle_type; #endif @@ -108,10 +109,10 @@ public: */ template <typename ExecutionContext> explicit basic_serial_port(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : impl_(0, 0, context) { } @@ -150,9 +151,9 @@ public: */ template <typename ExecutionContext> basic_serial_port(ExecutionContext& context, const char* device, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -194,9 +195,9 @@ public: */ template <typename ExecutionContext> basic_serial_port(ExecutionContext& context, const std::string& device, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -243,9 +244,9 @@ public: template <typename ExecutionContext> basic_serial_port(ExecutionContext& context, const native_handle_type& native_serial_port, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -254,7 +255,6 @@ public: asio::detail::throw_error(ec, "assign"); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a basic_serial_port from another. /** * This constructor moves a serial port from one object to another. @@ -287,7 +287,55 @@ public: impl_ = std::move(other.impl_); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + // All serial ports have access to each other's implementations. + template <typename Executor1> + friend class basic_serial_port; + + /// Move-construct a basic_serial_port from a serial port of another executor + /// type. + /** + * This constructor moves a serial port from one object to another. + * + * @param other The other basic_serial_port object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_serial_port(const executor_type&) + * constructor. + */ + template <typename Executor1> + basic_serial_port(basic_serial_port<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_serial_port from a serial port of another executor + /// type. + /** + * This assignment operator moves a serial port from one object to another. + * + * @param other The other basic_serial_port object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_serial_port(const executor_type&) + * constructor. + */ + template <typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_serial_port& + > operator=(basic_serial_port<Executor1>&& other) + { + basic_serial_port tmp(std::move(other)); + impl_ = std::move(tmp.impl_); + return *this; + } /// Destroys the serial port. /** @@ -300,7 +348,7 @@ public: } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + const executor_type& get_executor() noexcept { return impl_.get_executor(); } @@ -656,25 +704,31 @@ public: /// Start an asynchronous write. /** * This function is used to asynchronously write data to the serial port. - * The function call always returns immediately. + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. * * @param buffers One or more data buffers to be written to the serial port. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. + * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes. @@ -688,20 +742,30 @@ public: * See the @ref buffer documentation for information on writing multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector. + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_write_some(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return async_initiate<WriteHandler, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_write_some(const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_write_some>(), token, buffers)) + { + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_write_some(this), handler, buffers); + initiate_async_write_some(this), token, buffers); } /// Read some data from the serial port. @@ -770,25 +834,31 @@ public: /// Start an asynchronous read. /** * This function is used to asynchronously read data from the serial port. - * The function call always returns immediately. + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. * * @param buffers One or more buffers into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. + * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the * requested amount of data is read before the asynchronous operation @@ -803,26 +873,36 @@ public: * See the @ref buffer documentation for information on reading into multiple * buffers in one go, and how to use it with arrays, boost::array or * std::vector. + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_read_some(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return async_initiate<ReadHandler, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_read_some(const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_read_some>(), token, buffers)) + { + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_read_some(this), handler, buffers); + initiate_async_read_some(this), token, buffers); } private: // Disallow copying and assignment. - basic_serial_port(const basic_serial_port&) ASIO_DELETED; - basic_serial_port& operator=(const basic_serial_port&) ASIO_DELETED; + basic_serial_port(const basic_serial_port&) = delete; + basic_serial_port& operator=(const basic_serial_port&) = delete; class initiate_async_write_some { @@ -834,13 +914,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, const ConstBufferSequence& buffers) const { // If you get an error on the following line it means that your handler @@ -867,13 +947,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, const MutableBufferSequence& buffers) const { // If you get an error on the following line it means that your handler @@ -893,7 +973,7 @@ private: #if defined(ASIO_HAS_IOCP) detail::io_object_impl<detail::win_iocp_serial_port_service, Executor> impl_; #else - detail::io_object_impl<detail::reactive_serial_port_service, Executor> impl_; + detail::io_object_impl<detail::posix_serial_port_service, Executor> impl_; #endif }; diff --git a/3rdparty/asio/include/asio/basic_signal_set.hpp b/3rdparty/asio/include/asio/basic_signal_set.hpp index 25144346c23..bf74c39b3a8 100644 --- a/3rdparty/asio/include/asio/basic_signal_set.hpp +++ b/3rdparty/asio/include/asio/basic_signal_set.hpp @@ -2,7 +2,7 @@ // basic_signal_set.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -27,6 +27,7 @@ #include "asio/detail/type_traits.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" +#include "asio/signal_set_base.hpp" #include "asio/detail/push_options.hpp" @@ -93,8 +94,11 @@ namespace asio { * least one thread. */ template <typename Executor = any_io_executor> -class basic_signal_set +class basic_signal_set : public signal_set_base { +private: + class initiate_async_wait; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -130,10 +134,10 @@ public: */ template <typename ExecutionContext> explicit basic_signal_set(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : impl_(0, 0, context) { } @@ -176,10 +180,10 @@ public: */ template <typename ExecutionContext> basic_signal_set(ExecutionContext& context, int signal_number_1, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : impl_(0, 0, context) { asio::error_code ec; @@ -235,10 +239,10 @@ public: template <typename ExecutionContext> basic_signal_set(ExecutionContext& context, int signal_number_1, int signal_number_2, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : impl_(0, 0, context) { asio::error_code ec; @@ -304,10 +308,10 @@ public: template <typename ExecutionContext> basic_signal_set(ExecutionContext& context, int signal_number_1, int signal_number_2, int signal_number_3, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : impl_(0, 0, context) { asio::error_code ec; @@ -330,7 +334,7 @@ public: } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + const executor_type& get_executor() noexcept { return impl_.get_executor(); } @@ -367,6 +371,58 @@ public: ASIO_SYNC_OP_VOID_RETURN(ec); } + /// Add a signal to a signal_set with the specified flags. + /** + * This function adds the specified signal to the set. It has no effect if the + * signal is already in the set. + * + * Flags other than flags::dont_care require OS support for the @c sigaction + * call, and this function will fail with @c error::operation_not_supported if + * this is unavailable. + * + * The specified flags will conflict with a prior, active registration of the + * same signal, if either specified a flags value other than flags::dont_care. + * In this case, the @c add will fail with @c error::invalid_argument. + * + * @param signal_number The signal to be added to the set. + * + * @param f Flags to modify the behaviour of the specified signal. + * + * @throws asio::system_error Thrown on failure. + */ + void add(int signal_number, flags_t f) + { + asio::error_code ec; + impl_.get_service().add(impl_.get_implementation(), signal_number, f, ec); + asio::detail::throw_error(ec, "add"); + } + + /// Add a signal to a signal_set with the specified flags. + /** + * This function adds the specified signal to the set. It has no effect if the + * signal is already in the set. + * + * Flags other than flags::dont_care require OS support for the @c sigaction + * call, and this function will fail with @c error::operation_not_supported if + * this is unavailable. + * + * The specified flags will conflict with a prior, active registration of the + * same signal, if either specified a flags value other than flags::dont_care. + * In this case, the @c add will fail with @c error::invalid_argument. + * + * @param signal_number The signal to be added to the set. + * + * @param f Flags to modify the behaviour of the specified signal. + * + * @param ec Set to indicate what error occurred, if any. + */ + ASIO_SYNC_OP_VOID add(int signal_number, flags_t f, + asio::error_code& ec) + { + impl_.get_service().add(impl_.get_implementation(), signal_number, f, ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + /// Remove a signal from a signal_set. /** * This function removes the specified signal from the set. It has no effect @@ -494,45 +550,61 @@ public: /// Start an asynchronous operation to wait for a signal to be delivered. /** * This function may be used to initiate an asynchronous wait against the - * signal set. It always returns immediately. + * signal set. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * - * For each call to async_wait(), the supplied handler will be called exactly - * once. The handler will be called when: + * For each call to async_wait(), the completion handler will be called + * exactly once. The completion handler will be called when: * * @li One of the registered signals in the signal set occurs; or * * @li The signal set was cancelled, in which case the handler is passed the * error code asio::error::operation_aborted. * - * @param handler The handler to be called when the signal occurs. Copies - * will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the wait completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * int signal_number // Indicates which signal occurred. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code, int) @endcode + * + * @par Per-Operation Cancellation + * This asynchronous operation supports cancellation for the following + * asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, int)) - SignalHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(SignalHandler, - void (asio::error_code, int)) - async_wait( - ASIO_MOVE_ARG(SignalHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + SignalToken = default_completion_token_t<executor_type>> + auto async_wait( + SignalToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<SignalToken, void (asio::error_code, int)>( + declval<initiate_async_wait>(), token)) { - return async_initiate<SignalHandler, void (asio::error_code, int)>( - initiate_async_wait(this), handler); + return async_initiate<SignalToken, void (asio::error_code, int)>( + initiate_async_wait(this), token); } private: // Disallow copying and assignment. - basic_signal_set(const basic_signal_set&) ASIO_DELETED; - basic_signal_set& operator=(const basic_signal_set&) ASIO_DELETED; + basic_signal_set(const basic_signal_set&) = delete; + basic_signal_set& operator=(const basic_signal_set&) = delete; class initiate_async_wait { @@ -544,13 +616,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename SignalHandler> - void operator()(ASIO_MOVE_ARG(SignalHandler) handler) const + void operator()(SignalHandler&& handler) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a SignalHandler. diff --git a/3rdparty/asio/include/asio/basic_socket.hpp b/3rdparty/asio/include/asio/basic_socket.hpp index ba63cbbdeaf..88c4b03fe18 100644 --- a/3rdparty/asio/include/asio/basic_socket.hpp +++ b/3rdparty/asio/include/asio/basic_socket.hpp @@ -2,7 +2,7 @@ // basic_socket.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -15,6 +15,7 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +#include <utility> #include "asio/any_io_executor.hpp" #include "asio/detail/config.hpp" #include "asio/async_result.hpp" @@ -32,14 +33,12 @@ # include "asio/detail/null_socket_service.hpp" #elif defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_socket_service.hpp" +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/io_uring_socket_service.hpp" #else # include "asio/detail/reactive_socket_service.hpp" #endif -#if defined(ASIO_HAS_MOVE) -# include <utility> -#endif // defined(ASIO_HAS_MOVE) - #include "asio/detail/push_options.hpp" namespace asio { @@ -66,6 +65,10 @@ template <typename Protocol, typename Executor> class basic_socket : public socket_base { +private: + class initiate_async_connect; + class initiate_async_wait; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -87,6 +90,9 @@ public: #elif defined(ASIO_HAS_IOCP) typedef typename detail::win_iocp_socket_service< Protocol>::native_handle_type native_handle_type; +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) + typedef typename detail::io_uring_socket_service< + Protocol>::native_handle_type native_handle_type; #else typedef typename detail::reactive_socket_service< Protocol>::native_handle_type native_handle_type; @@ -125,9 +131,9 @@ public: */ template <typename ExecutionContext> explicit basic_socket(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { } @@ -165,10 +171,10 @@ public: */ template <typename ExecutionContext> basic_socket(ExecutionContext& context, const protocol_type& protocol, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : impl_(0, 0, context) { asio::error_code ec; @@ -220,9 +226,9 @@ public: */ template <typename ExecutionContext> basic_socket(ExecutionContext& context, const endpoint_type& endpoint, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -273,9 +279,9 @@ public: template <typename ExecutionContext> basic_socket(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_socket, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -284,7 +290,6 @@ public: asio::detail::throw_error(ec, "assign"); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a basic_socket from another. /** * This constructor moves a socket from one object to another. @@ -295,7 +300,7 @@ public: * @note Following the move, the moved-from object is in the same state as if * constructed using the @c basic_socket(const executor_type&) constructor. */ - basic_socket(basic_socket&& other) ASIO_NOEXCEPT + basic_socket(basic_socket&& other) noexcept : impl_(std::move(other.impl_)) { } @@ -332,10 +337,10 @@ public: */ template <typename Protocol1, typename Executor1> basic_socket(basic_socket<Protocol1, Executor1>&& other, - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value - >::type = 0) + > = 0) : impl_(std::move(other.impl_)) { } @@ -351,20 +356,19 @@ public: * constructed using the @c basic_socket(const executor_type&) constructor. */ template <typename Protocol1, typename Executor1> - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_socket& - >::type operator=(basic_socket<Protocol1, Executor1> && other) + > operator=(basic_socket<Protocol1, Executor1>&& other) { basic_socket tmp(std::move(other)); impl_ = std::move(tmp.impl_); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + const executor_type& get_executor() noexcept { return impl_.get_executor(); } @@ -902,7 +906,8 @@ public: /// Start an asynchronous connect. /** * This function is used to asynchronously connect a socket to the specified - * remote endpoint. The function call always returns immediately. + * remote endpoint. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * The socket is automatically opened if it is not already open. If the * connect fails, and the socket was automatically opened, the socket is @@ -911,17 +916,22 @@ public: * @param peer_endpoint The remote endpoint to which the socket will be * connected. Copies will be made of the endpoint object as required. * - * @param handler The handler to be called when the connection operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the connect completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error // Result of operation + * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code) @endcode + * * @par Example * @code * void connect_handler(const asio::error_code& error) @@ -952,12 +962,13 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) - ConnectHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ConnectHandler, - void (asio::error_code)) - async_connect(const endpoint_type& peer_endpoint, - ASIO_MOVE_ARG(ConnectHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ConnectToken = default_completion_token_t<executor_type>> + auto async_connect(const endpoint_type& peer_endpoint, + ConnectToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ConnectToken, void (asio::error_code)>( + declval<initiate_async_connect>(), token, + peer_endpoint, declval<asio::error_code&>())) { asio::error_code open_ec; if (!is_open()) @@ -966,8 +977,8 @@ public: impl_.get_service().open(impl_.get_implementation(), protocol, open_ec); } - return async_initiate<ConnectHandler, void (asio::error_code)>( - initiate_async_connect(this), handler, peer_endpoint, open_ec); + return async_initiate<ConnectToken, void (asio::error_code)>( + initiate_async_connect(this), token, peer_endpoint, open_ec); } /// Set an option on the socket. @@ -1751,21 +1762,28 @@ public: /// write, or to have pending error conditions. /** * This function is used to perform an asynchronous wait for a socket to enter - * a ready to read, write or error condition state. + * a ready to read, write or error condition state. It is an initiating + * function for an @ref asynchronous_operation, and always returns + * immediately. * * @param w Specifies the desired socket state. * - * @param handler The handler to be called when the wait operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the wait completes. Potential + * completion tokens include @ref use_future, @ref use_awaitable, @ref + * yield_context, or a function object with the correct completion signature. + * The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error // Result of operation + * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code) @endcode + * * @par Example * @code * void wait_handler(const asio::error_code& error) @@ -1795,15 +1813,15 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) - WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler, - void (asio::error_code)) - async_wait(wait_type w, - ASIO_MOVE_ARG(WaitHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WaitToken = default_completion_token_t<executor_type>> + auto async_wait(wait_type w, + WaitToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WaitToken, void (asio::error_code)>( + declval<initiate_async_wait>(), token, w)) { - return async_initiate<WaitHandler, void (asio::error_code)>( - initiate_async_wait(this), handler, w); + return async_initiate<WaitToken, void (asio::error_code)>( + initiate_async_wait(this), token, w); } protected: @@ -1822,6 +1840,9 @@ protected: #elif defined(ASIO_HAS_IOCP) detail::io_object_impl< detail::win_iocp_socket_service<Protocol>, Executor> impl_; +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) + detail::io_object_impl< + detail::io_uring_socket_service<Protocol>, Executor> impl_; #else detail::io_object_impl< detail::reactive_socket_service<Protocol>, Executor> impl_; @@ -1829,8 +1850,8 @@ protected: private: // Disallow copying and assignment. - basic_socket(const basic_socket&) ASIO_DELETED; - basic_socket& operator=(const basic_socket&) ASIO_DELETED; + basic_socket(const basic_socket&) = delete; + basic_socket& operator=(const basic_socket&) = delete; class initiate_async_connect { @@ -1842,13 +1863,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename ConnectHandler> - void operator()(ASIO_MOVE_ARG(ConnectHandler) handler, + void operator()(ConnectHandler&& handler, const endpoint_type& peer_endpoint, const asio::error_code& open_ec) const { @@ -1860,7 +1881,7 @@ private: { asio::post(self_->impl_.get_executor(), asio::detail::bind_handler( - ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec)); + static_cast<ConnectHandler&&>(handler), open_ec)); } else { @@ -1885,13 +1906,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WaitHandler> - void operator()(ASIO_MOVE_ARG(WaitHandler) handler, wait_type w) const + void operator()(WaitHandler&& handler, wait_type w) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a WaitHandler. diff --git a/3rdparty/asio/include/asio/basic_socket_acceptor.hpp b/3rdparty/asio/include/asio/basic_socket_acceptor.hpp index baa0c53ae6c..059d33ead53 100644 --- a/3rdparty/asio/include/asio/basic_socket_acceptor.hpp +++ b/3rdparty/asio/include/asio/basic_socket_acceptor.hpp @@ -2,7 +2,7 @@ // basic_socket_acceptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -15,6 +15,7 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +#include <utility> #include "asio/detail/config.hpp" #include "asio/any_io_executor.hpp" #include "asio/basic_socket.hpp" @@ -31,14 +32,12 @@ # include "asio/detail/null_socket_service.hpp" #elif defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_socket_service.hpp" +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/io_uring_socket_service.hpp" #else # include "asio/detail/reactive_socket_service.hpp" #endif -#if defined(ASIO_HAS_MOVE) -# include <utility> -#endif // defined(ASIO_HAS_MOVE) - #include "asio/detail/push_options.hpp" namespace asio { @@ -82,6 +81,11 @@ template <typename Protocol, typename Executor> class basic_socket_acceptor : public socket_base { +private: + class initiate_async_wait; + class initiate_async_accept; + class initiate_async_move_accept; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -103,6 +107,9 @@ public: #elif defined(ASIO_HAS_IOCP) typedef typename detail::win_iocp_socket_service< Protocol>::native_handle_type native_handle_type; +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) + typedef typename detail::io_uring_socket_service< + Protocol>::native_handle_type native_handle_type; #else typedef typename detail::reactive_socket_service< Protocol>::native_handle_type native_handle_type; @@ -141,9 +148,9 @@ public: */ template <typename ExecutionContext> explicit basic_socket_acceptor(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { } @@ -183,10 +190,10 @@ public: template <typename ExecutionContext> basic_socket_acceptor(ExecutionContext& context, const protocol_type& protocol, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : impl_(0, 0, context) { asio::error_code ec; @@ -272,9 +279,9 @@ public: template <typename ExecutionContext> basic_socket_acceptor(ExecutionContext& context, const endpoint_type& endpoint, bool reuse_addr = true, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -337,9 +344,9 @@ public: template <typename ExecutionContext> basic_socket_acceptor(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_acceptor, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -348,7 +355,6 @@ public: asio::detail::throw_error(ec, "assign"); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a basic_socket_acceptor from another. /** * This constructor moves an acceptor from one object to another. @@ -360,7 +366,7 @@ public: * constructed using the @c basic_socket_acceptor(const executor_type&) * constructor. */ - basic_socket_acceptor(basic_socket_acceptor&& other) ASIO_NOEXCEPT + basic_socket_acceptor(basic_socket_acceptor&& other) noexcept : impl_(std::move(other.impl_)) { } @@ -400,10 +406,10 @@ public: */ template <typename Protocol1, typename Executor1> basic_socket_acceptor(basic_socket_acceptor<Protocol1, Executor1>&& other, - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value - >::type = 0) + > = 0) : impl_(std::move(other.impl_)) { } @@ -421,17 +427,16 @@ public: * constructor. */ template <typename Protocol1, typename Executor1> - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_socket_acceptor& - >::type operator=(basic_socket_acceptor<Protocol1, Executor1>&& other) + > operator=(basic_socket_acceptor<Protocol1, Executor1>&& other) { basic_socket_acceptor tmp(std::move(other)); impl_ = std::move(tmp.impl_); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destroys the acceptor. /** @@ -444,7 +449,7 @@ public: } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + const executor_type& get_executor() noexcept { return impl_.get_executor(); } @@ -1191,21 +1196,28 @@ public: /// write, or to have pending error conditions. /** * This function is used to perform an asynchronous wait for an acceptor to - * enter a ready to read, write or error condition state. + * enter a ready to read, write or error condition state. It is an initiating + * function for an @ref asynchronous_operation, and always returns + * immediately. * * @param w Specifies the desired acceptor state. * - * @param handler The handler to be called when the wait operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the wait completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error // Result of operation + * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code) @endcode + * * @par Example * @code * void wait_handler(const asio::error_code& error) @@ -1237,15 +1249,15 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) - WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler, - void (asio::error_code)) - async_wait(wait_type w, - ASIO_MOVE_ARG(WaitHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WaitToken = default_completion_token_t<executor_type>> + auto async_wait(wait_type w, + WaitToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WaitToken, void (asio::error_code)>( + declval<initiate_async_wait>(), token, w)) { - return async_initiate<WaitHandler, void (asio::error_code)>( - initiate_async_wait(this), handler, w); + return async_initiate<WaitToken, void (asio::error_code)>( + initiate_async_wait(this), token, w); } #if !defined(ASIO_NO_EXTENSIONS) @@ -1269,9 +1281,9 @@ public: */ template <typename Protocol1, typename Executor1> void accept(basic_socket<Protocol1, Executor1>& peer, - typename constraint< + constraint_t< is_convertible<Protocol, Protocol1>::value - >::type = 0) + > = 0) { asio::error_code ec; impl_.get_service().accept(impl_.get_implementation(), @@ -1305,9 +1317,9 @@ public: template <typename Protocol1, typename Executor1> ASIO_SYNC_OP_VOID accept( basic_socket<Protocol1, Executor1>& peer, asio::error_code& ec, - typename constraint< + constraint_t< is_convertible<Protocol, Protocol1>::value - >::type = 0) + > = 0) { impl_.get_service().accept(impl_.get_implementation(), peer, static_cast<endpoint_type*>(0), ec); @@ -1317,23 +1329,30 @@ public: /// Start an asynchronous accept. /** * This function is used to asynchronously accept a new connection into a - * socket. The function call always returns immediately. + * socket, and additionally obtain the endpoint of the remote peer. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * @param peer The socket into which the new connection will be accepted. * Ownership of the peer object is retained by the caller, which must - * guarantee that it is valid until the handler is called. + * guarantee that it is valid until the completion handler is called. * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the accept completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code) @endcode + * * @par Example * @code * void accept_handler(const asio::error_code& error) @@ -1364,18 +1383,19 @@ public: */ template <typename Protocol1, typename Executor1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) - AcceptHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(AcceptHandler, - void (asio::error_code)) - async_accept(basic_socket<Protocol1, Executor1>& peer, - ASIO_MOVE_ARG(AcceptHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), - typename constraint< + AcceptToken = default_completion_token_t<executor_type>> + auto async_accept(basic_socket<Protocol1, Executor1>& peer, + AcceptToken&& token = default_completion_token_t<executor_type>(), + constraint_t< is_convertible<Protocol, Protocol1>::value - >::type = 0) - { - return async_initiate<AcceptHandler, void (asio::error_code)>( - initiate_async_accept(this), handler, + > = 0) + -> decltype( + async_initiate<AcceptToken, void (asio::error_code)>( + declval<initiate_async_accept>(), token, + &peer, static_cast<endpoint_type*>(0))) + { + return async_initiate<AcceptToken, void (asio::error_code)>( + initiate_async_accept(this), token, &peer, static_cast<endpoint_type*>(0)); } @@ -1452,29 +1472,35 @@ public: /// Start an asynchronous accept. /** * This function is used to asynchronously accept a new connection into a - * socket, and additionally obtain the endpoint of the remote peer. The - * function call always returns immediately. + * socket, and additionally obtain the endpoint of the remote peer. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * @param peer The socket into which the new connection will be accepted. * Ownership of the peer object is retained by the caller, which must - * guarantee that it is valid until the handler is called. + * guarantee that it is valid until the completion handler is called. * * @param peer_endpoint An endpoint object into which the endpoint of the * remote peer will be written. Ownership of the peer_endpoint object is * retained by the caller, which must guarantee that it is valid until the * handler is called. * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the accept completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code) @endcode + * * @par Per-Operation Cancellation * On POSIX or Windows operating systems, this asynchronous operation supports * cancellation for the following asio::cancellation_type values: @@ -1487,20 +1513,19 @@ public: */ template <typename Executor1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) - AcceptHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(AcceptHandler, - void (asio::error_code)) - async_accept(basic_socket<protocol_type, Executor1>& peer, + AcceptToken = default_completion_token_t<executor_type>> + auto async_accept(basic_socket<protocol_type, Executor1>& peer, endpoint_type& peer_endpoint, - ASIO_MOVE_ARG(AcceptHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + AcceptToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<AcceptToken, void (asio::error_code)>( + declval<initiate_async_accept>(), token, &peer, &peer_endpoint)) { - return async_initiate<AcceptHandler, void (asio::error_code)>( - initiate_async_accept(this), handler, &peer, &peer_endpoint); + return async_initiate<AcceptToken, void (asio::error_code)>( + initiate_async_accept(this), token, &peer, &peer_endpoint); } #endif // !defined(ASIO_NO_EXTENSIONS) -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Accept a new connection. /** * This function is used to accept a new connection from a peer. The function @@ -1568,27 +1593,36 @@ public: /// Start an asynchronous accept. /** - * This function is used to asynchronously accept a new connection. The - * function call always returns immediately. + * This function is used to asynchronously accept a new connection. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the accept completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, + * * // On success, the newly accepted socket. * typename Protocol::socket::template * rebind_executor<executor_type>::other peer * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, + * typename Protocol::socket::template + * rebind_executor<executor_type>::other)) @endcode + * * @par Example * @code * void accept_handler(const asio::error_code& error, @@ -1620,20 +1654,23 @@ public: template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor< - executor_type>::other)) MoveAcceptHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, - void (asio::error_code, - typename Protocol::socket::template - rebind_executor<executor_type>::other)) - async_accept( - ASIO_MOVE_ARG(MoveAcceptHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return async_initiate<MoveAcceptHandler, + executor_type>::other)) MoveAcceptToken + = default_completion_token_t<executor_type>> + auto async_accept( + MoveAcceptToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<MoveAcceptToken, + void (asio::error_code, typename Protocol::socket::template + rebind_executor<executor_type>::other)>( + declval<initiate_async_move_accept>(), token, + declval<const executor_type&>(), static_cast<endpoint_type*>(0), + static_cast<typename Protocol::socket::template + rebind_executor<executor_type>::other*>(0))) + { + return async_initiate<MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor<executor_type>::other)>( - initiate_async_move_accept(this), handler, + initiate_async_move_accept(this), token, impl_.get_executor(), static_cast<endpoint_type*>(0), static_cast<typename Protocol::socket::template rebind_executor<executor_type>::other*>(0)); @@ -1665,10 +1702,10 @@ public: template <typename Executor1> typename Protocol::socket::template rebind_executor<Executor1>::other accept(const Executor1& ex, - typename constraint< + constraint_t< is_executor<Executor1>::value || execution::is_executor<Executor1>::value - >::type = 0) + > = 0) { asio::error_code ec; typename Protocol::socket::template @@ -1705,9 +1742,9 @@ public: typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other accept(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) { asio::error_code ec; typename Protocol::socket::template rebind_executor< @@ -1748,10 +1785,10 @@ public: template <typename Executor1> typename Protocol::socket::template rebind_executor<Executor1>::other accept(const Executor1& ex, asio::error_code& ec, - typename constraint< + constraint_t< is_executor<Executor1>::value || execution::is_executor<Executor1>::value - >::type = 0) + > = 0) { typename Protocol::socket::template rebind_executor<Executor1>::other peer(ex); @@ -1791,9 +1828,9 @@ public: typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other accept(ExecutionContext& context, asio::error_code& ec, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) { typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other peer(context); @@ -1803,8 +1840,9 @@ public: /// Start an asynchronous accept. /** - * This function is used to asynchronously accept a new connection. The - * function call always returns immediately. + * This function is used to asynchronously accept a new connection. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. @@ -1812,19 +1850,29 @@ public: * @param ex The I/O executor object to be used for the newly accepted * socket. * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the accept completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, + * + * // On success, the newly accepted socket. * typename Protocol::socket::template rebind_executor< - * Executor1>::other peer // On success, the newly accepted socket. + * Executor1>::other peer * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, + * typename Protocol::socket::template rebind_executor< + * Executor1>::other)) @endcode + * * @par Example * @code * void accept_handler(const asio::error_code& error, @@ -1856,34 +1904,41 @@ public: template <typename Executor1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor< - Executor1>::other)) MoveAcceptHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, - void (asio::error_code, - typename Protocol::socket::template rebind_executor< - Executor1>::other)) - async_accept(const Executor1& ex, - ASIO_MOVE_ARG(MoveAcceptHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), - typename constraint< + constraint_t<is_executor<Executor1>::value + || execution::is_executor<Executor1>::value, + Executor1>>::other)) MoveAcceptToken + = default_completion_token_t<executor_type>> + auto async_accept(const Executor1& ex, + MoveAcceptToken&& token = default_completion_token_t<executor_type>(), + constraint_t< is_executor<Executor1>::value || execution::is_executor<Executor1>::value - >::type = 0) - { - typedef typename Protocol::socket::template rebind_executor< - Executor1>::other other_socket_type; - - return async_initiate<MoveAcceptHandler, - void (asio::error_code, other_socket_type)>( - initiate_async_move_accept(this), handler, - ex, static_cast<endpoint_type*>(0), - static_cast<other_socket_type*>(0)); + > = 0) + -> decltype( + async_initiate<MoveAcceptToken, + void (asio::error_code, + typename Protocol::socket::template rebind_executor< + Executor1>::other)>( + declval<initiate_async_move_accept>(), token, + ex, static_cast<endpoint_type*>(0), + static_cast<typename Protocol::socket::template + rebind_executor<Executor1>::other*>(0))) + { + return async_initiate<MoveAcceptToken, + void (asio::error_code, + typename Protocol::socket::template rebind_executor< + Executor1>::other)>( + initiate_async_move_accept(this), token, + ex, static_cast<endpoint_type*>(0), + static_cast<typename Protocol::socket::template + rebind_executor<Executor1>::other*>(0)); } /// Start an asynchronous accept. /** - * This function is used to asynchronously accept a new connection. The - * function call always returns immediately. + * This function is used to asynchronously accept a new connection. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. @@ -1891,20 +1946,29 @@ public: * @param context The I/O execution context object to be used for the newly * accepted socket. * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the accept completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, + * + * // On success, the newly accepted socket. * typename Protocol::socket::template rebind_executor< * typename ExecutionContext::executor_type>::other peer - * // On success, the newly accepted socket. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, + * typename Protocol::socket::template rebind_executor< + * typename ExecutionContext::executor_type>::other)) @endcode + * * @par Example * @code * void accept_handler(const asio::error_code& error, @@ -1936,27 +2000,31 @@ public: template <typename ExecutionContext, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor< - typename ExecutionContext::executor_type>::other)) MoveAcceptHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, + typename ExecutionContext::executor_type>::other)) MoveAcceptToken + = default_completion_token_t<executor_type>> + auto async_accept(ExecutionContext& context, + MoveAcceptToken&& token = default_completion_token_t<executor_type>(), + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) + -> decltype( + async_initiate<MoveAcceptToken, + void (asio::error_code, + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other)>( + declval<initiate_async_move_accept>(), token, + context.get_executor(), static_cast<endpoint_type*>(0), + static_cast<typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other*>(0))) + { + return async_initiate<MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor< - typename ExecutionContext::executor_type>::other)) - async_accept(ExecutionContext& context, - ASIO_MOVE_ARG(MoveAcceptHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), - typename constraint< - is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) - { - typedef typename Protocol::socket::template rebind_executor< - typename ExecutionContext::executor_type>::other other_socket_type; - - return async_initiate<MoveAcceptHandler, - void (asio::error_code, other_socket_type)>( - initiate_async_move_accept(this), handler, - context.get_executor(), static_cast<endpoint_type*>(0), - static_cast<other_socket_type*>(0)); + typename ExecutionContext::executor_type>::other)>( + initiate_async_move_accept(this), token, + context.get_executor(), static_cast<endpoint_type*>(0), + static_cast<typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other*>(0)); } /// Accept a new connection. @@ -2036,8 +2104,9 @@ public: /// Start an asynchronous accept. /** - * This function is used to asynchronously accept a new connection. The - * function call always returns immediately. + * This function is used to asynchronously accept a new connection. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. @@ -2045,23 +2114,31 @@ public: * @param peer_endpoint An endpoint object into which the endpoint of the * remote peer will be written. Ownership of the peer_endpoint object is * retained by the caller, which must guarantee that it is valid until the - * handler is called. + * completion handler is called. * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the accept completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, + * * // On success, the newly accepted socket. * typename Protocol::socket::template * rebind_executor<executor_type>::other peer * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, + * typename Protocol::socket::template + * rebind_executor<executor_type>::other)) @endcode + * * @par Example * @code * void accept_handler(const asio::error_code& error, @@ -2094,20 +2171,23 @@ public: template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor< - executor_type>::other)) MoveAcceptHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, - void (asio::error_code, - typename Protocol::socket::template - rebind_executor<executor_type>::other)) - async_accept(endpoint_type& peer_endpoint, - ASIO_MOVE_ARG(MoveAcceptHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return async_initiate<MoveAcceptHandler, + executor_type>::other)) MoveAcceptToken + = default_completion_token_t<executor_type>> + auto async_accept(endpoint_type& peer_endpoint, + MoveAcceptToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<MoveAcceptToken, + void (asio::error_code, typename Protocol::socket::template + rebind_executor<executor_type>::other)>( + declval<initiate_async_move_accept>(), token, + declval<const executor_type&>(), &peer_endpoint, + static_cast<typename Protocol::socket::template + rebind_executor<executor_type>::other*>(0))) + { + return async_initiate<MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor<executor_type>::other)>( - initiate_async_move_accept(this), handler, + initiate_async_move_accept(this), token, impl_.get_executor(), &peer_endpoint, static_cast<typename Protocol::socket::template rebind_executor<executor_type>::other*>(0)); @@ -2144,10 +2224,10 @@ public: template <typename Executor1> typename Protocol::socket::template rebind_executor<Executor1>::other accept(const Executor1& ex, endpoint_type& peer_endpoint, - typename constraint< + constraint_t< is_executor<Executor1>::value || execution::is_executor<Executor1>::value - >::type = 0) + > = 0) { asio::error_code ec; typename Protocol::socket::template @@ -2190,9 +2270,9 @@ public: typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other accept(ExecutionContext& context, endpoint_type& peer_endpoint, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) { asio::error_code ec; typename Protocol::socket::template rebind_executor< @@ -2240,10 +2320,10 @@ public: typename Protocol::socket::template rebind_executor<Executor1>::other accept(const executor_type& ex, endpoint_type& peer_endpoint, asio::error_code& ec, - typename constraint< + constraint_t< is_executor<Executor1>::value || execution::is_executor<Executor1>::value - >::type = 0) + > = 0) { typename Protocol::socket::template rebind_executor<Executor1>::other peer(ex); @@ -2290,9 +2370,9 @@ public: typename ExecutionContext::executor_type>::other accept(ExecutionContext& context, endpoint_type& peer_endpoint, asio::error_code& ec, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) { typename Protocol::socket::template rebind_executor< typename ExecutionContext::executor_type>::other peer(context); @@ -2303,8 +2383,9 @@ public: /// Start an asynchronous accept. /** - * This function is used to asynchronously accept a new connection. The - * function call always returns immediately. + * This function is used to asynchronously accept a new connection. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. @@ -2315,21 +2396,31 @@ public: * @param peer_endpoint An endpoint object into which the endpoint of the * remote peer will be written. Ownership of the peer_endpoint object is * retained by the caller, which must guarantee that it is valid until the - * handler is called. + * completion handler is called. * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the accept completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, + * + * // On success, the newly accepted socket. * typename Protocol::socket::template rebind_executor< - * Executor1>::other peer // On success, the newly accepted socket. + * Executor1>::other peer * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, + * typename Protocol::socket::template rebind_executor< + * Executor1>::other)) @endcode + * * @par Example * @code * void accept_handler(const asio::error_code& error, @@ -2362,34 +2453,39 @@ public: template <typename Executor1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor< - Executor1>::other)) MoveAcceptHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, - void (asio::error_code, - typename Protocol::socket::template rebind_executor< - Executor1>::other)) - async_accept(const Executor1& ex, endpoint_type& peer_endpoint, - ASIO_MOVE_ARG(MoveAcceptHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), - typename constraint< + constraint_t<is_executor<Executor1>::value + || execution::is_executor<Executor1>::value, + Executor1>>::other)) MoveAcceptToken + = default_completion_token_t<executor_type>> + auto async_accept(const Executor1& ex, endpoint_type& peer_endpoint, + MoveAcceptToken&& token = default_completion_token_t<executor_type>(), + constraint_t< is_executor<Executor1>::value || execution::is_executor<Executor1>::value - >::type = 0) + > = 0) + -> decltype( + async_initiate<MoveAcceptToken, + void (asio::error_code, + typename Protocol::socket::template rebind_executor< + Executor1>::other)>( + declval<initiate_async_move_accept>(), token, ex, &peer_endpoint, + static_cast<typename Protocol::socket::template + rebind_executor<Executor1>::other*>(0))) { - typedef typename Protocol::socket::template rebind_executor< - Executor1>::other other_socket_type; - - return async_initiate<MoveAcceptHandler, - void (asio::error_code, other_socket_type)>( - initiate_async_move_accept(this), handler, - ex, &peer_endpoint, - static_cast<other_socket_type*>(0)); + return async_initiate<MoveAcceptToken, + void (asio::error_code, + typename Protocol::socket::template rebind_executor< + Executor1>::other)>( + initiate_async_move_accept(this), token, ex, &peer_endpoint, + static_cast<typename Protocol::socket::template + rebind_executor<Executor1>::other*>(0)); } /// Start an asynchronous accept. /** - * This function is used to asynchronously accept a new connection. The - * function call always returns immediately. + * This function is used to asynchronously accept a new connection. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. * * This overload requires that the Protocol template parameter satisfy the * AcceptableProtocol type requirements. @@ -2400,22 +2496,31 @@ public: * @param peer_endpoint An endpoint object into which the endpoint of the * remote peer will be written. Ownership of the peer_endpoint object is * retained by the caller, which must guarantee that it is valid until the - * handler is called. + * completion handler is called. * - * @param handler The handler to be called when the accept operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the accept completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, + * + * // On success, the newly accepted socket. * typename Protocol::socket::template rebind_executor< * typename ExecutionContext::executor_type>::other peer - * // On success, the newly accepted socket. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, + * typename Protocol::socket::template rebind_executor< + * typename ExecutionContext::executor_type>::other)) @endcode + * * @par Example * @code * void accept_handler(const asio::error_code& error, @@ -2448,36 +2553,38 @@ public: template <typename ExecutionContext, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, typename Protocol::socket::template rebind_executor< - typename ExecutionContext::executor_type>::other)) MoveAcceptHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler, + typename ExecutionContext::executor_type>::other)) MoveAcceptToken + = default_completion_token_t<executor_type>> + auto async_accept(ExecutionContext& context, endpoint_type& peer_endpoint, + MoveAcceptToken&& token = default_completion_token_t<executor_type>(), + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) + -> decltype( + async_initiate<MoveAcceptToken, + void (asio::error_code, + typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other)>( + declval<initiate_async_move_accept>(), token, + context.get_executor(), &peer_endpoint, + static_cast<typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other*>(0))) + { + return async_initiate<MoveAcceptToken, void (asio::error_code, typename Protocol::socket::template rebind_executor< - typename ExecutionContext::executor_type>::other)) - async_accept(ExecutionContext& context, - endpoint_type& peer_endpoint, - ASIO_MOVE_ARG(MoveAcceptHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type), - typename constraint< - is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) - { - typedef typename Protocol::socket::template rebind_executor< - typename ExecutionContext::executor_type>::other other_socket_type; - - return async_initiate<MoveAcceptHandler, - void (asio::error_code, other_socket_type)>( - initiate_async_move_accept(this), handler, - context.get_executor(), &peer_endpoint, - static_cast<other_socket_type*>(0)); + typename ExecutionContext::executor_type>::other)>( + initiate_async_move_accept(this), token, + context.get_executor(), &peer_endpoint, + static_cast<typename Protocol::socket::template rebind_executor< + typename ExecutionContext::executor_type>::other*>(0)); } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) private: // Disallow copying and assignment. - basic_socket_acceptor(const basic_socket_acceptor&) ASIO_DELETED; + basic_socket_acceptor(const basic_socket_acceptor&) = delete; basic_socket_acceptor& operator=( - const basic_socket_acceptor&) ASIO_DELETED; + const basic_socket_acceptor&) = delete; class initiate_async_wait { @@ -2489,13 +2596,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WaitHandler> - void operator()(ASIO_MOVE_ARG(WaitHandler) handler, wait_type w) const + void operator()(WaitHandler&& handler, wait_type w) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a WaitHandler. @@ -2521,13 +2628,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename AcceptHandler, typename Protocol1, typename Executor1> - void operator()(ASIO_MOVE_ARG(AcceptHandler) handler, + void operator()(AcceptHandler&& handler, basic_socket<Protocol1, Executor1>* peer, endpoint_type* peer_endpoint) const { @@ -2555,13 +2662,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename MoveAcceptHandler, typename Executor1, typename Socket> - void operator()(ASIO_MOVE_ARG(MoveAcceptHandler) handler, + void operator()(MoveAcceptHandler&& handler, const Executor1& peer_ex, endpoint_type* peer_endpoint, Socket*) const { // If you get an error on the following line it means that your handler @@ -2585,6 +2692,9 @@ private: #elif defined(ASIO_HAS_IOCP) detail::io_object_impl< detail::win_iocp_socket_service<Protocol>, Executor> impl_; +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) + detail::io_object_impl< + detail::io_uring_socket_service<Protocol>, Executor> impl_; #else detail::io_object_impl< detail::reactive_socket_service<Protocol>, Executor> impl_; diff --git a/3rdparty/asio/include/asio/basic_socket_iostream.hpp b/3rdparty/asio/include/asio/basic_socket_iostream.hpp index b6fd88880de..902898d9502 100644 --- a/3rdparty/asio/include/asio/basic_socket_iostream.hpp +++ b/3rdparty/asio/include/asio/basic_socket_iostream.hpp @@ -2,7 +2,7 @@ // basic_socket_iostream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,55 +23,6 @@ #include <ostream> #include "asio/basic_socket_streambuf.hpp" -#if !defined(ASIO_HAS_VARIADIC_TEMPLATES) - -# include "asio/detail/variadic_templates.hpp" - -// A macro that should expand to: -// template <typename T1, ..., typename Tn> -// explicit basic_socket_iostream(T1 x1, ..., Tn xn) -// : std::basic_iostream<char>( -// &this->detail::socket_iostream_base< -// Protocol, Clock, WaitTraits>::streambuf_) -// { -// if (rdbuf()->connect(x1, ..., xn) == 0) -// this->setstate(std::ios_base::failbit); -// } -// This macro should only persist within this file. - -# define ASIO_PRIVATE_CTR_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - explicit basic_socket_iostream(ASIO_VARIADIC_BYVAL_PARAMS(n)) \ - : std::basic_iostream<char>( \ - &this->detail::socket_iostream_base< \ - Protocol, Clock, WaitTraits>::streambuf_) \ - { \ - this->setf(std::ios_base::unitbuf); \ - if (rdbuf()->connect(ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \ - this->setstate(std::ios_base::failbit); \ - } \ - /**/ - -// A macro that should expand to: -// template <typename T1, ..., typename Tn> -// void connect(T1 x1, ..., Tn xn) -// { -// if (rdbuf()->connect(x1, ..., xn) == 0) -// this->setstate(std::ios_base::failbit); -// } -// This macro should only persist within this file. - -# define ASIO_PRIVATE_CONNECT_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - void connect(ASIO_VARIADIC_BYVAL_PARAMS(n)) \ - { \ - if (rdbuf()->connect(ASIO_VARIADIC_BYVAL_ARGS(n)) == 0) \ - this->setstate(std::ios_base::failbit); \ - } \ - /**/ - -#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES) - #include "asio/detail/push_options.hpp" namespace asio { @@ -87,7 +38,6 @@ protected: { } -#if defined(ASIO_HAS_MOVE) socket_iostream_base(socket_iostream_base&& other) : streambuf_(std::move(other.streambuf_)) { @@ -103,7 +53,6 @@ protected: streambuf_ = std::move(other.streambuf_); return *this; } -#endif // defined(ASIO_HAS_MOVE) basic_socket_streambuf<Protocol, Clock, WaitTraits> streambuf_; }; @@ -118,11 +67,11 @@ template <typename Protocol, #if defined(ASIO_HAS_BOOST_DATE_TIME) \ && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) typename Clock = boost::posix_time::ptime, - typename WaitTraits = time_traits<Clock> > + typename WaitTraits = time_traits<Clock>> #else // defined(ASIO_HAS_BOOST_DATE_TIME) // && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) typename Clock = chrono::steady_clock, - typename WaitTraits = wait_traits<Clock> > + typename WaitTraits = wait_traits<Clock>> #endif // defined(ASIO_HAS_BOOST_DATE_TIME) // && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) class basic_socket_iostream; @@ -133,7 +82,7 @@ class basic_socket_iostream; #if defined(GENERATING_DOCUMENTATION) template <typename Protocol, typename Clock = chrono::steady_clock, - typename WaitTraits = wait_traits<Clock> > + typename WaitTraits = wait_traits<Clock>> #else // defined(GENERATING_DOCUMENTATION) template <typename Protocol, typename Clock, typename WaitTraits> #endif // defined(GENERATING_DOCUMENTATION) @@ -193,7 +142,6 @@ public: this->setf(std::ios_base::unitbuf); } -#if defined(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< @@ -205,8 +153,6 @@ public: this->setf(std::ios_base::unitbuf); } -#if defined(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< @@ -225,20 +171,13 @@ public: Protocol, Clock, WaitTraits>::operator=(std::move(other)); return *this; } -#endif // defined(ASIO_HAS_STD_IOSTREAM_MOVE) - // || defined(GENERATING_DOCUMENTATION) -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) -#if defined(GENERATING_DOCUMENTATION) /// Establish a connection to an endpoint corresponding to a resolver query. /** * This constructor automatically establishes a connection based on the * supplied resolver query parameters. The arguments are used to construct * a resolver query object. */ - template <typename T1, ..., typename TN> - explicit basic_socket_iostream(T1 t1, ..., TN tn); -#elif defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename... T> explicit basic_socket_iostream(T... x) : std::basic_iostream<char>( @@ -249,29 +188,19 @@ public: if (rdbuf()->connect(x...) == 0) this->setstate(std::ios_base::failbit); } -#else - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CTR_DEF) -#endif -#if defined(GENERATING_DOCUMENTATION) /// Establish a connection to an endpoint corresponding to a resolver query. /** * This function automatically establishes a connection based on the supplied * resolver query parameters. The arguments are used to construct a resolver * query object. */ - template <typename T1, ..., typename TN> - void connect(T1 t1, ..., TN tn); -#elif defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename... T> void connect(T... x) { if (rdbuf()->connect(x...) == 0) this->setstate(std::ios_base::failbit); } -#else - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CONNECT_DEF) -#endif /// Close the connection. void close() @@ -388,20 +317,15 @@ public: private: // Disallow copying and assignment. - basic_socket_iostream(const basic_socket_iostream&) ASIO_DELETED; + basic_socket_iostream(const basic_socket_iostream&) = delete; basic_socket_iostream& operator=( - const basic_socket_iostream&) ASIO_DELETED; + const basic_socket_iostream&) = delete; }; } // namespace asio #include "asio/detail/pop_options.hpp" -#if !defined(ASIO_HAS_VARIADIC_TEMPLATES) -# undef ASIO_PRIVATE_CTR_DEF -# undef ASIO_PRIVATE_CONNECT_DEF -#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES) - #endif // !defined(ASIO_NO_IOSTREAM) #endif // ASIO_BASIC_SOCKET_IOSTREAM_HPP diff --git a/3rdparty/asio/include/asio/basic_socket_streambuf.hpp b/3rdparty/asio/include/asio/basic_socket_streambuf.hpp index 11efcce1091..e3a5f836382 100644 --- a/3rdparty/asio/include/asio/basic_socket_streambuf.hpp +++ b/3rdparty/asio/include/asio/basic_socket_streambuf.hpp @@ -2,7 +2,7 @@ // basic_socket_streambuf.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -37,38 +37,6 @@ #endif // defined(ASIO_HAS_BOOST_DATE_TIME) // && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) -#if !defined(ASIO_HAS_VARIADIC_TEMPLATES) - -# include "asio/detail/variadic_templates.hpp" - -// A macro that should expand to: -// template <typename T1, ..., typename Tn> -// basic_socket_streambuf* connect(T1 x1, ..., Tn xn) -// { -// init_buffers(); -// typedef typename Protocol::resolver resolver_type; -// resolver_type resolver(socket().get_executor()); -// connect_to_endpoints( -// resolver.resolve(x1, ..., xn, ec_)); -// return !ec_ ? this : 0; -// } -// This macro should only persist within this file. - -# define ASIO_PRIVATE_CONNECT_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - basic_socket_streambuf* connect(ASIO_VARIADIC_BYVAL_PARAMS(n)) \ - { \ - init_buffers(); \ - typedef typename Protocol::resolver resolver_type; \ - resolver_type resolver(socket().get_executor()); \ - connect_to_endpoints( \ - resolver.resolve(ASIO_VARIADIC_BYVAL_ARGS(n), ec_)); \ - return !ec_ ? this : 0; \ - } \ - /**/ - -#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES) - #include "asio/detail/push_options.hpp" namespace asio { @@ -116,11 +84,11 @@ template <typename Protocol, #if defined(ASIO_HAS_BOOST_DATE_TIME) \ && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) typename Clock = boost::posix_time::ptime, - typename WaitTraits = time_traits<Clock> > + typename WaitTraits = time_traits<Clock>> #else // defined(ASIO_HAS_BOOST_DATE_TIME) // && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) typename Clock = chrono::steady_clock, - typename WaitTraits = wait_traits<Clock> > + typename WaitTraits = wait_traits<Clock>> #endif // defined(ASIO_HAS_BOOST_DATE_TIME) // && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) class basic_socket_streambuf; @@ -131,7 +99,7 @@ class basic_socket_streambuf; #if defined(GENERATING_DOCUMENTATION) template <typename Protocol, typename Clock = chrono::steady_clock, - typename WaitTraits = wait_traits<Clock> > + typename WaitTraits = wait_traits<Clock>> #else // defined(GENERATING_DOCUMENTATION) template <typename Protocol, typename Clock, typename WaitTraits> #endif // defined(GENERATING_DOCUMENTATION) @@ -197,7 +165,6 @@ public: init_buffers(); } -#if defined(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), @@ -241,7 +208,6 @@ public: other.init_buffers(); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destructor flushes buffered data. virtual ~basic_socket_streambuf() @@ -265,7 +231,6 @@ public: return !ec_ ? this : 0; } -#if defined(GENERATING_DOCUMENTATION) /// Establish a connection. /** * This function automatically establishes a connection based on the supplied @@ -275,9 +240,6 @@ public: * @return \c this if a connection was successfully established, a null * pointer otherwise. */ - template <typename T1, ..., typename TN> - basic_socket_streambuf* connect(T1 t1, ..., TN tn); -#elif defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename... T> basic_socket_streambuf* connect(T... x) { @@ -287,9 +249,6 @@ public: connect_to_endpoints(resolver.resolve(x..., ec_)); return !ec_ ? this : 0; } -#else - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CONNECT_DEF) -#endif /// Close the connection. /** @@ -559,9 +518,9 @@ protected: private: // Disallow copying and assignment. - basic_socket_streambuf(const basic_socket_streambuf&) ASIO_DELETED; + basic_socket_streambuf(const basic_socket_streambuf&) = delete; basic_socket_streambuf& operator=( - const basic_socket_streambuf&) ASIO_DELETED; + const basic_socket_streambuf&) = delete; void init_buffers() { @@ -678,10 +637,6 @@ private: #include "asio/detail/pop_options.hpp" -#if !defined(ASIO_HAS_VARIADIC_TEMPLATES) -# undef ASIO_PRIVATE_CONNECT_DEF -#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES) - #endif // !defined(ASIO_NO_IOSTREAM) #endif // ASIO_BASIC_SOCKET_STREAMBUF_HPP diff --git a/3rdparty/asio/include/asio/basic_stream_file.hpp b/3rdparty/asio/include/asio/basic_stream_file.hpp new file mode 100644 index 00000000000..4b2ca8775e5 --- /dev/null +++ b/3rdparty/asio/include/asio/basic_stream_file.hpp @@ -0,0 +1,744 @@ +// +// basic_stream_file.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_STREAM_FILE_HPP +#define ASIO_BASIC_STREAM_FILE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_FILE) \ + || defined(GENERATING_DOCUMENTATION) + +#include <cstddef> +#include "asio/async_result.hpp" +#include "asio/basic_file.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/non_const_lvalue.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +#if !defined(ASIO_BASIC_STREAM_FILE_FWD_DECL) +#define ASIO_BASIC_STREAM_FILE_FWD_DECL + +// Forward declaration with defaulted arguments. +template <typename Executor = any_io_executor> +class basic_stream_file; + +#endif // !defined(ASIO_BASIC_STREAM_FILE_FWD_DECL) + +/// Provides stream-oriented file functionality. +/** + * The basic_stream_file class template provides asynchronous and blocking + * stream-oriented file functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * @par Concepts: + * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. + */ +template <typename Executor> +class basic_stream_file + : public basic_file<Executor> +{ +private: + class initiate_async_write_some; + class initiate_async_read_some; + +public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the file type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The file type when rebound to the specified executor. + typedef basic_stream_file<Executor1> other; + }; + + /// The native representation of a file. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#else + typedef typename basic_file<Executor>::native_handle_type native_handle_type; +#endif + + /// Construct a basic_stream_file without opening it. + /** + * This constructor initialises a file without opening it. The file needs to + * be opened before data can be read from or or written to it. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + */ + explicit basic_stream_file(const executor_type& ex) + : basic_file<Executor>(ex) + { + this->impl_.get_service().set_is_stream( + this->impl_.get_implementation(), true); + } + + /// Construct a basic_stream_file without opening it. + /** + * This constructor initialises a file without opening it. The file needs to + * be opened before data can be read from or or written to it. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + */ + template <typename ExecutionContext> + explicit basic_stream_file(ExecutionContext& context, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_file<Executor>(context) + { + this->impl_.get_service().set_is_stream( + this->impl_.get_implementation(), true); + } + + /// Construct and open a basic_stream_file. + /** + * This constructor initialises and opens a file. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @throws asio::system_error Thrown on failure. + */ + basic_stream_file(const executor_type& ex, + const char* path, file_base::flags open_flags) + : basic_file<Executor>(ex) + { + asio::error_code ec; + this->impl_.get_service().set_is_stream( + this->impl_.get_implementation(), true); + this->impl_.get_service().open( + this->impl_.get_implementation(), + path, open_flags, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Construct and open a basic_stream_file. + /** + * This constructor initialises and opens a file. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @throws asio::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_stream_file(ExecutionContext& context, + const char* path, file_base::flags open_flags, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_file<Executor>(context) + { + asio::error_code ec; + this->impl_.get_service().set_is_stream( + this->impl_.get_implementation(), true); + this->impl_.get_service().open( + this->impl_.get_implementation(), + path, open_flags, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Construct and open a basic_stream_file. + /** + * This constructor initialises and opens a file. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @throws asio::system_error Thrown on failure. + */ + basic_stream_file(const executor_type& ex, + const std::string& path, file_base::flags open_flags) + : basic_file<Executor>(ex) + { + asio::error_code ec; + this->impl_.get_service().set_is_stream( + this->impl_.get_implementation(), true); + this->impl_.get_service().open( + this->impl_.get_implementation(), + path.c_str(), open_flags, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Construct and open a basic_stream_file. + /** + * This constructor initialises and opens a file. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + * + * @param path The path name identifying the file to be opened. + * + * @param open_flags A set of flags that determine how the file should be + * opened. + * + * @throws asio::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_stream_file(ExecutionContext& context, + const std::string& path, file_base::flags open_flags, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_file<Executor>(context) + { + asio::error_code ec; + this->impl_.get_service().set_is_stream( + this->impl_.get_implementation(), true); + this->impl_.get_service().open( + this->impl_.get_implementation(), + path.c_str(), open_flags, ec); + asio::detail::throw_error(ec, "open"); + } + + /// Construct a basic_stream_file on an existing native file. + /** + * This constructor initialises a stream file object to hold an existing + * native file. + * + * @param ex The I/O executor that the file will use, by default, to + * dispatch handlers for any asynchronous operations performed on the file. + * + * @param native_file The new underlying file implementation. + * + * @throws asio::system_error Thrown on failure. + */ + basic_stream_file(const executor_type& ex, + const native_handle_type& native_file) + : basic_file<Executor>(ex, native_file) + { + this->impl_.get_service().set_is_stream( + this->impl_.get_implementation(), true); + } + + /// Construct a basic_stream_file on an existing native file. + /** + * This constructor initialises a stream file object to hold an existing + * native file. + * + * @param context An execution context which provides the I/O executor that + * the file will use, by default, to dispatch handlers for any asynchronous + * operations performed on the file. + * + * @param native_file The new underlying file implementation. + * + * @throws asio::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_stream_file(ExecutionContext& context, + const native_handle_type& native_file, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_file<Executor>(context, native_file) + { + this->impl_.get_service().set_is_stream( + this->impl_.get_implementation(), true); + } + + /// Move-construct a basic_stream_file from another. + /** + * This constructor moves a stream file from one object to another. + * + * @param other The other basic_stream_file object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_file(const executor_type&) + * constructor. + */ + basic_stream_file(basic_stream_file&& other) noexcept + : basic_file<Executor>(std::move(other)) + { + } + + /// Move-assign a basic_stream_file from another. + /** + * This assignment operator moves a stream file from one object to another. + * + * @param other The other basic_stream_file object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_file(const executor_type&) + * constructor. + */ + basic_stream_file& operator=(basic_stream_file&& other) + { + basic_file<Executor>::operator=(std::move(other)); + return *this; + } + + /// Move-construct a basic_stream_file from a file of another executor + /// type. + /** + * This constructor moves a stream file from one object to another. + * + * @param other The other basic_stream_file object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_file(const executor_type&) + * constructor. + */ + template <typename Executor1> + basic_stream_file(basic_stream_file<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_file<Executor>(std::move(other)) + { + } + + /// Move-assign a basic_stream_file from a file of another executor type. + /** + * This assignment operator moves a stream file from one object to another. + * + * @param other The other basic_stream_file object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_file(const executor_type&) + * constructor. + */ + template <typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_stream_file& + > operator=(basic_stream_file<Executor1>&& other) + { + basic_file<Executor>::operator=(std::move(other)); + return *this; + } + + /// Destroys the file. + /** + * This function destroys the file, cancelling any outstanding asynchronous + * operations associated with the file as if by calling @c cancel. + */ + ~basic_stream_file() + { + } + + /// Seek to a position in the file. + /** + * This function updates the current position in the file. + * + * @param offset The requested position in the file, relative to @c whence. + * + * @param whence One of @c seek_set, @c seek_cur or @c seek_end. + * + * @returns The new position relative to the beginning of the file. + * + * @throws asio::system_error Thrown on failure. + */ + uint64_t seek(int64_t offset, file_base::seek_basis whence) + { + asio::error_code ec; + uint64_t n = this->impl_.get_service().seek( + this->impl_.get_implementation(), offset, whence, ec); + asio::detail::throw_error(ec, "seek"); + return n; + } + + /// Seek to a position in the file. + /** + * This function updates the current position in the file. + * + * @param offset The requested position in the file, relative to @c whence. + * + * @param whence One of @c seek_set, @c seek_cur or @c seek_end. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The new position relative to the beginning of the file. + */ + uint64_t seek(int64_t offset, file_base::seek_basis whence, + asio::error_code& ec) + { + return this->impl_.get_service().seek( + this->impl_.get_implementation(), offset, whence, ec); + } + + /// Write some data to the file. + /** + * This function is used to write data to the stream file. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the file. + * + * @returns The number of bytes written. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the end of the file was reached. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * file.write_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->impl_.get_service().write_some( + this->impl_.get_implementation(), buffers, ec); + asio::detail::throw_error(ec, "write_some"); + return s; + } + + /// Write some data to the file. + /** + * This function is used to write data to the stream file. The function call + * will block until one or more bytes of the data has been written + * successfully, or until an error occurs. + * + * @param buffers One or more data buffers to be written to the file. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers, + asio::error_code& ec) + { + return this->impl_.get_service().write_some( + this->impl_.get_implementation(), buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the stream file. + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. + * + * @param buffers One or more data buffers to be written to the file. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the completion handler is called. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a + * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * file.async_write_some(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total + */ + template <typename ConstBufferSequence, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_write_some(const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_write_some>(), token, buffers)) + { + return async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + initiate_async_write_some(this), token, buffers); + } + + /// Read some data from the file. + /** + * This function is used to read data from the stream file. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @returns The number of bytes read. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the end of the file was reached. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * file.read_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = this->impl_.get_service().read_some( + this->impl_.get_implementation(), buffers, ec); + asio::detail::throw_error(ec, "read_some"); + return s; + } + + /// Read some data from the file. + /** + * This function is used to read data from the stream file. The function + * call will block until one or more bytes of data has been read successfully, + * or until an error occurs. + * + * @param buffers One or more buffers into which the data will be read. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes read. Returns 0 if an error occurred. + * + * @note The read_some operation may not read all of the requested number of + * bytes. Consider using the @ref read function if you need to ensure that + * the requested amount of data is read before the blocking operation + * completes. + */ + template <typename MutableBufferSequence> + std::size_t read_some(const MutableBufferSequence& buffers, + asio::error_code& ec) + { + return this->impl_.get_service().read_some( + this->impl_.get_implementation(), buffers, ec); + } + + /// Start an asynchronous read. + /** + * This function is used to asynchronously read data from the stream file. + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. + * + * @param buffers One or more buffers into which the data will be read. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the completion handler is called. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes read. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a + * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * + * @note The read operation may not read all of the requested number of bytes. + * Consider using the @ref async_read function if you need to ensure that the + * requested amount of data is read before the asynchronous operation + * completes. + * + * @par Example + * To read into a single data buffer use the @ref buffer function as follows: + * @code + * file.async_read_some(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on reading into multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + * + * @par Per-Operation Cancellation + * On POSIX or Windows operating systems, this asynchronous operation supports + * cancellation for the following asio::cancellation_type values: + * + * @li @c cancellation_type::terminal + * + * @li @c cancellation_type::partial + * + * @li @c cancellation_type::total + */ + template <typename MutableBufferSequence, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_read_some(const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_read_some>(), token, buffers)) + { + return async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + initiate_async_read_some(this), token, buffers); + } + +private: + // Disallow copying and assignment. + basic_stream_file(const basic_stream_file&) = delete; + basic_stream_file& operator=(const basic_stream_file&) = delete; + + class initiate_async_write_some + { + public: + typedef Executor executor_type; + + explicit initiate_async_write_some(basic_stream_file* self) + : self_(self) + { + } + + const executor_type& get_executor() const noexcept + { + return self_->get_executor(); + } + + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(WriteHandler&& handler, + const ConstBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue<WriteHandler> handler2(handler); + self_->impl_.get_service().async_write_some( + self_->impl_.get_implementation(), buffers, + handler2.value, self_->impl_.get_executor()); + } + + private: + basic_stream_file* self_; + }; + + class initiate_async_read_some + { + public: + typedef Executor executor_type; + + explicit initiate_async_read_some(basic_stream_file* self) + : self_(self) + { + } + + const executor_type& get_executor() const noexcept + { + return self_->get_executor(); + } + + template <typename ReadHandler, typename MutableBufferSequence> + void operator()(ReadHandler&& handler, + const MutableBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a ReadHandler. + ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; + + detail::non_const_lvalue<ReadHandler> handler2(handler); + self_->impl_.get_service().async_read_some( + self_->impl_.get_implementation(), buffers, + handler2.value, self_->impl_.get_executor()); + } + + private: + basic_stream_file* self_; + }; +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_FILE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_BASIC_STREAM_FILE_HPP diff --git a/3rdparty/asio/include/asio/basic_stream_socket.hpp b/3rdparty/asio/include/asio/basic_stream_socket.hpp index 5b573849333..e3a79450037 100644 --- a/3rdparty/asio/include/asio/basic_stream_socket.hpp +++ b/3rdparty/asio/include/asio/basic_stream_socket.hpp @@ -2,7 +2,7 @@ // basic_stream_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -46,11 +46,12 @@ class basic_stream_socket; * @e Distinct @e objects: Safe.@n * @e Shared @e objects: Unsafe. * - * Synchronous @c send, @c receive, and @c connect operations are thread safe - * with respect to each other, if the underlying operating system calls are - * also thread safe. This means that it is permitted to perform concurrent - * calls to these synchronous operations on a single socket object. Other - * synchronous operations, such as @c open or @c close, are not thread safe. + * Synchronous @c send, @c receive, @c connect, and @c shutdown operations are + * thread safe with respect to each other, if the underlying operating system + * calls are also thread safe. This means that it is permitted to perform + * concurrent calls to these synchronous operations on a single socket object. + * Other synchronous operations, such as @c open or @c close, are not thread + * safe. * * @par Concepts: * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. @@ -59,6 +60,10 @@ template <typename Protocol, typename Executor> class basic_stream_socket : public basic_socket<Protocol, Executor> { +private: + class initiate_async_send; + class initiate_async_receive; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -111,9 +116,9 @@ public: */ template <typename ExecutionContext> explicit basic_stream_socket(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context) { } @@ -150,10 +155,10 @@ public: */ template <typename ExecutionContext> basic_stream_socket(ExecutionContext& context, const protocol_type& protocol, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : basic_socket<Protocol, Executor>(context, protocol) { } @@ -196,9 +201,9 @@ public: */ template <typename ExecutionContext> basic_stream_socket(ExecutionContext& context, const endpoint_type& endpoint, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context, endpoint) { } @@ -241,14 +246,13 @@ public: template <typename ExecutionContext> basic_stream_socket(ExecutionContext& context, const protocol_type& protocol, const native_handle_type& native_socket, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(context, protocol, native_socket) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a basic_stream_socket from another. /** * This constructor moves a stream socket from one object to another. @@ -260,7 +264,7 @@ public: * constructed using the @c basic_stream_socket(const executor_type&) * constructor. */ - basic_stream_socket(basic_stream_socket&& other) ASIO_NOEXCEPT + basic_stream_socket(basic_stream_socket&& other) noexcept : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -296,10 +300,10 @@ public: */ template <typename Protocol1, typename Executor1> basic_stream_socket(basic_stream_socket<Protocol1, Executor1>&& other, - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value - >::type = 0) + > = 0) : basic_socket<Protocol, Executor>(std::move(other)) { } @@ -316,16 +320,15 @@ public: * constructor. */ template <typename Protocol1, typename Executor1> - typename constraint< + constraint_t< is_convertible<Protocol1, Protocol>::value && is_convertible<Executor1, Executor>::value, basic_stream_socket& - >::type operator=(basic_stream_socket<Protocol1, Executor1>&& other) + > operator=(basic_stream_socket<Protocol1, Executor1>&& other) { basic_socket<Protocol, Executor>::operator=(std::move(other)); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destroys the socket. /** @@ -438,25 +441,31 @@ public: /// Start an asynchronous send. /** * This function is used to asynchronously send data on the stream socket. - * The function call always returns immediately. + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. + * remain valid until the completion handler is called. * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the send completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. + * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The send operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes. @@ -482,44 +491,51 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_send(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_send(const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send>(), token, + buffers, socket_base::message_flags(0))) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send(this), handler, + initiate_async_send(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous send. /** * This function is used to asynchronously send data on the stream socket. - * The function call always returns immediately. + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. * * @param buffers One or more data buffers to be sent on the socket. Although * the buffers object may be copied as necessary, ownership of the underlying * memory blocks is retained by the caller, which must guarantee that they - * remain valid until the handler is called. + * remain valid until the completion handler is called. * * @param flags Flags specifying how the send call is to be made. * - * @param handler The handler to be called when the send operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the send completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes sent. + * std::size_t bytes_transferred // Number of bytes sent. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The send operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes. @@ -545,18 +561,18 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_send(const ConstBufferSequence& buffers, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_send(const ConstBufferSequence& buffers, socket_base::message_flags flags, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send>(), token, buffers, flags)) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send(this), handler, buffers, flags); + initiate_async_send(this), token, buffers, flags); } /// Receive some data on the socket. @@ -667,25 +683,31 @@ public: /// Start an asynchronous receive. /** * This function is used to asynchronously receive data from the stream - * socket. The function call always returns immediately. + * socket. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The receive operation may not receive all of the requested number of * bytes. Consider using the @ref async_read function if you need to ensure * that the requested amount of data is received before the asynchronous @@ -713,44 +735,51 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_receive(const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive>(), token, + buffers, socket_base::message_flags(0))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive(this), handler, + initiate_async_receive(this), token, buffers, socket_base::message_flags(0)); } /// Start an asynchronous receive. /** * This function is used to asynchronously receive data from the stream - * socket. The function call always returns immediately. + * socket. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param buffers One or more buffers into which the data will be received. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param flags Flags specifying how the receive call is to be made. * - * @param handler The handler to be called when the receive operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the receive completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes received. + * std::size_t bytes_transferred // Number of bytes received. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The receive operation may not receive all of the requested number of * bytes. Consider using the @ref async_read function if you need to ensure * that the requested amount of data is received before the asynchronous @@ -778,18 +807,18 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_receive(const MutableBufferSequence& buffers, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_receive(const MutableBufferSequence& buffers, socket_base::message_flags flags, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive>(), token, buffers, flags)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive(this), handler, buffers, flags); + initiate_async_receive(this), token, buffers, flags); } /// Write some data to the socket. @@ -856,25 +885,31 @@ public: /// Start an asynchronous write. /** * This function is used to asynchronously write data to the stream socket. - * The function call always returns immediately. + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. * * @param buffers One or more data buffers to be written to the socket. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. + * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes. @@ -900,17 +935,18 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_write_some(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_write_some(const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_send>(), token, + buffers, socket_base::message_flags(0))) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_send(this), handler, + initiate_async_send(this), token, buffers, socket_base::message_flags(0)); } @@ -980,25 +1016,31 @@ public: /// Start an asynchronous read. /** * This function is used to asynchronously read data from the stream socket. - * The function call always returns immediately. + * socket. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param buffers One or more buffers into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. + * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the * requested amount of data is read before the asynchronous operation @@ -1025,24 +1067,25 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_read_some(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_read_some(const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_receive>(), token, + buffers, socket_base::message_flags(0))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_receive(this), handler, + initiate_async_receive(this), token, buffers, socket_base::message_flags(0)); } private: // Disallow copying and assignment. - basic_stream_socket(const basic_stream_socket&) ASIO_DELETED; - basic_stream_socket& operator=(const basic_stream_socket&) ASIO_DELETED; + basic_stream_socket(const basic_stream_socket&) = delete; + basic_stream_socket& operator=(const basic_stream_socket&) = delete; class initiate_async_send { @@ -1054,13 +1097,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, const ConstBufferSequence& buffers, socket_base::message_flags flags) const { @@ -1088,13 +1131,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, const MutableBufferSequence& buffers, socket_base::message_flags flags) const { diff --git a/3rdparty/asio/include/asio/basic_streambuf.hpp b/3rdparty/asio/include/asio/basic_streambuf.hpp index 3e0c6e4a22e..0450811dca1 100644 --- a/3rdparty/asio/include/asio/basic_streambuf.hpp +++ b/3rdparty/asio/include/asio/basic_streambuf.hpp @@ -2,7 +2,7 @@ // basic_streambuf.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -103,7 +103,7 @@ namespace asio { * @endcode */ #if defined(GENERATING_DOCUMENTATION) -template <typename Allocator = std::allocator<char> > +template <typename Allocator = std::allocator<char>> #else template <typename Allocator> #endif @@ -155,7 +155,7 @@ public: * } * @endcode */ - std::size_t size() const ASIO_NOEXCEPT + std::size_t size() const noexcept { return pptr() - gptr(); } @@ -165,7 +165,7 @@ public: * @returns The allowed maximum of the sum of the sizes of the input sequence * and output sequence. */ - std::size_t max_size() const ASIO_NOEXCEPT + std::size_t max_size() const noexcept { return max_size_; } @@ -175,7 +175,7 @@ public: * @returns The current total capacity of the streambuf, i.e. for both the * input sequence and output sequence. */ - std::size_t capacity() const ASIO_NOEXCEPT + std::size_t capacity() const noexcept { return buffer_.capacity(); } @@ -189,7 +189,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 ASIO_NOEXCEPT + const_buffers_type data() const noexcept { return asio::buffer(asio::const_buffer(gptr(), (pptr() - gptr()) * sizeof(char_type))); @@ -361,7 +361,7 @@ private: /// Adapts basic_streambuf to the dynamic buffer sequence type requirements. #if defined(GENERATING_DOCUMENTATION) -template <typename Allocator = std::allocator<char> > +template <typename Allocator = std::allocator<char>> #else template <typename Allocator> #endif @@ -383,39 +383,37 @@ public: } /// Copy construct a basic_streambuf_ref. - basic_streambuf_ref(const basic_streambuf_ref& other) ASIO_NOEXCEPT + basic_streambuf_ref(const basic_streambuf_ref& other) noexcept : sb_(other.sb_) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move construct a basic_streambuf_ref. - basic_streambuf_ref(basic_streambuf_ref&& other) ASIO_NOEXCEPT + basic_streambuf_ref(basic_streambuf_ref&& other) noexcept : sb_(other.sb_) { } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Get the size of the input sequence. - std::size_t size() const ASIO_NOEXCEPT + std::size_t size() const noexcept { return sb_.size(); } /// Get the maximum size of the dynamic buffer. - std::size_t max_size() const ASIO_NOEXCEPT + std::size_t max_size() const noexcept { return sb_.max_size(); } /// Get the current capacity of the dynamic buffer. - std::size_t capacity() const ASIO_NOEXCEPT + std::size_t capacity() const noexcept { return sb_.capacity(); } /// Get a list of buffers that represents the input sequence. - const_buffers_type data() const ASIO_NOEXCEPT + const_buffers_type data() const noexcept { return sb_.data(); } diff --git a/3rdparty/asio/include/asio/basic_streambuf_fwd.hpp b/3rdparty/asio/include/asio/basic_streambuf_fwd.hpp index 5856c966466..1ff320d4637 100644 --- a/3rdparty/asio/include/asio/basic_streambuf_fwd.hpp +++ b/3rdparty/asio/include/asio/basic_streambuf_fwd.hpp @@ -2,7 +2,7 @@ // basic_streambuf_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,10 +23,10 @@ namespace asio { -template <typename Allocator = std::allocator<char> > +template <typename Allocator = std::allocator<char>> class basic_streambuf; -template <typename Allocator = std::allocator<char> > +template <typename Allocator = std::allocator<char>> class basic_streambuf_ref; } // namespace asio diff --git a/3rdparty/asio/include/asio/basic_waitable_timer.hpp b/3rdparty/asio/include/asio/basic_waitable_timer.hpp index 3b9adcec7f4..5e9df3ef4f8 100644 --- a/3rdparty/asio/include/asio/basic_waitable_timer.hpp +++ b/3rdparty/asio/include/asio/basic_waitable_timer.hpp @@ -2,7 +2,7 @@ // basic_waitable_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,6 +17,7 @@ #include "asio/detail/config.hpp" #include <cstddef> +#include <utility> #include "asio/any_io_executor.hpp" #include "asio/detail/chrono_time_traits.hpp" #include "asio/detail/deadline_timer_service.hpp" @@ -27,10 +28,6 @@ #include "asio/error.hpp" #include "asio/wait_traits.hpp" -#if defined(ASIO_HAS_MOVE) -# include <utility> -#endif // defined(ASIO_HAS_MOVE) - #include "asio/detail/push_options.hpp" namespace asio { @@ -141,6 +138,9 @@ class basic_waitable_timer; template <typename Clock, typename WaitTraits, typename Executor> class basic_waitable_timer { +private: + class initiate_async_wait; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -191,9 +191,9 @@ public: */ template <typename ExecutionContext> explicit basic_waitable_timer(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { } @@ -230,9 +230,9 @@ public: template <typename ExecutionContext> explicit basic_waitable_timer(ExecutionContext& context, const time_point& expiry_time, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -273,9 +273,9 @@ public: template <typename ExecutionContext> explicit basic_waitable_timer(ExecutionContext& context, const duration& expiry_time, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -284,7 +284,6 @@ public: asio::detail::throw_error(ec, "expires_after"); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a basic_waitable_timer from another. /** * This constructor moves a timer from one object to another. @@ -337,9 +336,9 @@ public: template <typename Executor1> basic_waitable_timer( basic_waitable_timer<Clock, WaitTraits, Executor1>&& other, - typename constraint< - is_convertible<Executor1, Executor>::value - >::type = 0) + constraint_t< + is_convertible<Executor1, Executor>::value + > = 0) : impl_(std::move(other.impl_)) { } @@ -357,16 +356,15 @@ public: * constructor. */ template <typename Executor1> - typename constraint< + constraint_t< is_convertible<Executor1, Executor>::value, basic_waitable_timer& - >::type operator=(basic_waitable_timer<Clock, WaitTraits, Executor1>&& other) + > operator=(basic_waitable_timer<Clock, WaitTraits, Executor1>&& other) { basic_waitable_timer tmp(std::move(other)); impl_ = std::move(tmp.impl_); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destroys the timer. /** @@ -378,7 +376,7 @@ public: } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + const executor_type& get_executor() noexcept { return impl_.get_executor(); } @@ -726,27 +724,33 @@ public: /// Start an asynchronous wait on the timer. /** * This function may be used to initiate an asynchronous wait against the - * timer. It always returns immediately. + * timer. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * - * For each call to async_wait(), the supplied handler will be called exactly - * once. The handler will be called when: + * For each call to async_wait(), the completion handler will be called + * exactly once. The completion handler will be called when: * * @li The timer has expired. * * @li The timer was cancelled, in which case the handler is passed the error * code asio::error::operation_aborted. * - * @param handler The handler to be called when the timer expires. Copies - * will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the timer expires. Potential + * completion tokens include @ref use_future, @ref use_awaitable, @ref + * yield_context, or a function object with the correct completion signature. + * The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -759,22 +763,21 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) - WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler, - void (asio::error_code)) - async_wait( - ASIO_MOVE_ARG(WaitHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WaitToken = default_completion_token_t<executor_type>> + auto async_wait( + WaitToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WaitToken, void (asio::error_code)>( + declval<initiate_async_wait>(), token)) { - return async_initiate<WaitHandler, void (asio::error_code)>( - initiate_async_wait(this), handler); + return async_initiate<WaitToken, void (asio::error_code)>( + initiate_async_wait(this), token); } private: // Disallow copying and assignment. - basic_waitable_timer(const basic_waitable_timer&) ASIO_DELETED; - basic_waitable_timer& operator=( - const basic_waitable_timer&) ASIO_DELETED; + basic_waitable_timer(const basic_waitable_timer&) = delete; + basic_waitable_timer& operator=(const basic_waitable_timer&) = delete; class initiate_async_wait { @@ -786,13 +789,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WaitHandler> - void operator()(ASIO_MOVE_ARG(WaitHandler) handler) const + void operator()(WaitHandler&& handler) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a WaitHandler. @@ -810,7 +813,7 @@ private: detail::io_object_impl< detail::deadline_timer_service< - detail::chrono_time_traits<Clock, WaitTraits> >, + detail::chrono_time_traits<Clock, WaitTraits>>, executor_type > impl_; }; diff --git a/3rdparty/asio/include/asio/basic_writable_pipe.hpp b/3rdparty/asio/include/asio/basic_writable_pipe.hpp new file mode 100644 index 00000000000..4c389c9b464 --- /dev/null +++ b/3rdparty/asio/include/asio/basic_writable_pipe.hpp @@ -0,0 +1,622 @@ +// +// basic_writable_pipe.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BASIC_WRITABLE_PIPE_HPP +#define ASIO_BASIC_WRITABLE_PIPE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PIPE) \ + || defined(GENERATING_DOCUMENTATION) + +#include <string> +#include <utility> +#include "asio/any_io_executor.hpp" +#include "asio/async_result.hpp" +#include "asio/detail/handler_type_requirements.hpp" +#include "asio/detail/io_object_impl.hpp" +#include "asio/detail/non_const_lvalue.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/error.hpp" +#include "asio/execution_context.hpp" +#if defined(ASIO_HAS_IOCP) +# include "asio/detail/win_iocp_handle_service.hpp" +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/io_uring_descriptor_service.hpp" +#else +# include "asio/detail/reactive_descriptor_service.hpp" +#endif + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Provides pipe functionality. +/** + * The basic_writable_pipe class provides a wrapper over pipe + * functionality. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + */ +template <typename Executor = any_io_executor> +class basic_writable_pipe +{ +private: + class initiate_async_write_some; + +public: + /// The type of the executor associated with the object. + typedef Executor executor_type; + + /// Rebinds the pipe type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The pipe type when rebound to the specified executor. + typedef basic_writable_pipe<Executor1> other; + }; + + /// The native representation of a pipe. +#if defined(GENERATING_DOCUMENTATION) + typedef implementation_defined native_handle_type; +#elif defined(ASIO_HAS_IOCP) + typedef detail::win_iocp_handle_service::native_handle_type + native_handle_type; +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) + typedef detail::io_uring_descriptor_service::native_handle_type + native_handle_type; +#else + typedef detail::reactive_descriptor_service::native_handle_type + native_handle_type; +#endif + + /// A basic_writable_pipe is always the lowest layer. + typedef basic_writable_pipe lowest_layer_type; + + /// Construct a basic_writable_pipe without opening it. + /** + * This constructor creates a pipe without opening it. + * + * @param ex The I/O executor that the pipe will use, by default, to dispatch + * handlers for any asynchronous operations performed on the pipe. + */ + explicit basic_writable_pipe(const executor_type& ex) + : impl_(0, ex) + { + } + + /// Construct a basic_writable_pipe without opening it. + /** + * This constructor creates a pipe without opening it. + * + * @param context An execution context which provides the I/O executor that + * the pipe will use, by default, to dispatch handlers for any asynchronous + * operations performed on the pipe. + */ + template <typename ExecutionContext> + explicit basic_writable_pipe(ExecutionContext& context, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(0, 0, context) + { + } + + /// Construct a basic_writable_pipe on an existing native pipe. + /** + * This constructor creates a pipe object to hold an existing native + * pipe. + * + * @param ex The I/O executor that the pipe will use, by default, to + * dispatch handlers for any asynchronous operations performed on the + * pipe. + * + * @param native_pipe A native pipe. + * + * @throws asio::system_error Thrown on failure. + */ + basic_writable_pipe(const executor_type& ex, + const native_handle_type& native_pipe) + : impl_(0, ex) + { + asio::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + native_pipe, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Construct a basic_writable_pipe on an existing native pipe. + /** + * This constructor creates a pipe object to hold an existing native + * pipe. + * + * @param context An execution context which provides the I/O executor that + * the pipe will use, by default, to dispatch handlers for any + * asynchronous operations performed on the pipe. + * + * @param native_pipe A native pipe. + * + * @throws asio::system_error Thrown on failure. + */ + template <typename ExecutionContext> + basic_writable_pipe(ExecutionContext& context, + const native_handle_type& native_pipe, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) + : impl_(0, 0, context) + { + asio::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), + native_pipe, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Move-construct a basic_writable_pipe from another. + /** + * This constructor moves a pipe from one object to another. + * + * @param other The other basic_writable_pipe object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_writable_pipe(const executor_type&) + * constructor. + */ + basic_writable_pipe(basic_writable_pipe&& other) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_writable_pipe from another. + /** + * This assignment operator moves a pipe from one object to another. + * + * @param other The other basic_writable_pipe object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_writable_pipe(const executor_type&) + * constructor. + */ + basic_writable_pipe& operator=(basic_writable_pipe&& other) + { + impl_ = std::move(other.impl_); + return *this; + } + + // All pipes have access to each other's implementations. + template <typename Executor1> + friend class basic_writable_pipe; + + /// Move-construct a basic_writable_pipe from a pipe of another executor type. + /** + * This constructor moves a pipe from one object to another. + * + * @param other The other basic_writable_pipe object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_writable_pipe(const executor_type&) + * constructor. + */ + template <typename Executor1> + basic_writable_pipe(basic_writable_pipe<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_writable_pipe from a pipe of another executor type. + /** + * This assignment operator moves a pipe from one object to another. + * + * @param other The other basic_writable_pipe object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_writable_pipe(const executor_type&) + * constructor. + */ + template <typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_writable_pipe& + > operator=(basic_writable_pipe<Executor1>&& other) + { + basic_writable_pipe tmp(std::move(other)); + impl_ = std::move(tmp.impl_); + return *this; + } + + /// Destroys the pipe. + /** + * This function destroys the pipe, cancelling any outstanding + * asynchronous wait operations associated with the pipe as if by + * calling @c cancel. + */ + ~basic_writable_pipe() + { + } + + /// Get the executor associated with the object. + const executor_type& get_executor() noexcept + { + return impl_.get_executor(); + } + + /// Get a reference to the lowest layer. + /** + * This function returns a reference to the lowest layer in a stack of + * layers. Since a basic_writable_pipe cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A reference to the lowest layer in the stack of layers. Ownership + * is not transferred to the caller. + */ + lowest_layer_type& lowest_layer() + { + return *this; + } + + /// Get a const reference to the lowest layer. + /** + * This function returns a const reference to the lowest layer in a stack of + * layers. Since a basic_writable_pipe cannot contain any further layers, it + * simply returns a reference to itself. + * + * @return A const reference to the lowest layer in the stack of layers. + * Ownership is not transferred to the caller. + */ + const lowest_layer_type& lowest_layer() const + { + return *this; + } + + /// Assign an existing native pipe to the pipe. + /* + * This function opens the pipe to hold an existing native pipe. + * + * @param native_pipe A native pipe. + * + * @throws asio::system_error Thrown on failure. + */ + void assign(const native_handle_type& native_pipe) + { + asio::error_code ec; + impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec); + asio::detail::throw_error(ec, "assign"); + } + + /// Assign an existing native pipe to the pipe. + /* + * This function opens the pipe to hold an existing native pipe. + * + * @param native_pipe A native pipe. + * + * @param ec Set to indicate what error occurred, if any. + */ + ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe, + asio::error_code& ec) + { + impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Determine whether the pipe is open. + bool is_open() const + { + return impl_.get_service().is_open(impl_.get_implementation()); + } + + /// Close the pipe. + /** + * This function is used to close the pipe. Any asynchronous write operations + * will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + */ + void close() + { + asio::error_code ec; + impl_.get_service().close(impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "close"); + } + + /// Close the pipe. + /** + * This function is used to close the pipe. Any asynchronous write operations + * will be cancelled immediately, and will complete with the + * asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + ASIO_SYNC_OP_VOID close(asio::error_code& ec) + { + impl_.get_service().close(impl_.get_implementation(), ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Release ownership of the underlying native pipe. + /** + * This function causes all outstanding asynchronous write operations to + * finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. Ownership of the + * native pipe is then transferred to the caller. + * + * @throws asio::system_error Thrown on failure. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with asio::error::operation_not_supported on + * these platforms. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release() + { + asio::error_code ec; + native_handle_type s = impl_.get_service().release( + impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "release"); + return s; + } + + /// Release ownership of the underlying native pipe. + /** + * This function causes all outstanding asynchronous write operations to + * finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. Ownership of the + * native pipe is then transferred to the caller. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with asio::error::operation_not_supported on + * these platforms. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release(asio::error_code& ec) + { + return impl_.get_service().release(impl_.get_implementation(), ec); + } + + /// Get the native pipe representation. + /** + * This function may be used to obtain the underlying representation of the + * pipe. This is intended to allow access to native pipe + * functionality that is not otherwise provided. + */ + native_handle_type native_handle() + { + return impl_.get_service().native_handle(impl_.get_implementation()); + } + + /// Cancel all asynchronous operations associated with the pipe. + /** + * This function causes all outstanding asynchronous write operations to + * finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. + * + * @throws asio::system_error Thrown on failure. + */ + void cancel() + { + asio::error_code ec; + impl_.get_service().cancel(impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "cancel"); + } + + /// Cancel all asynchronous operations associated with the pipe. + /** + * This function causes all outstanding asynchronous write operations to + * finish immediately, and the handlers for cancelled operations will be + * passed the asio::error::operation_aborted error. + * + * @param ec Set to indicate what error occurred, if any. + */ + ASIO_SYNC_OP_VOID cancel(asio::error_code& ec) + { + impl_.get_service().cancel(impl_.get_implementation(), ec); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + /// Write some data to the pipe. + /** + * This function is used to write data to the pipe. The function call will + * block until one or more bytes of the data has been written successfully, + * or until an error occurs. + * + * @param buffers One or more data buffers to be written to the pipe. + * + * @returns The number of bytes written. + * + * @throws asio::system_error Thrown on failure. An error code of + * asio::error::eof indicates that the connection was closed by the + * peer. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * pipe.write_some(asio::buffer(data, size)); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers) + { + asio::error_code ec; + std::size_t s = impl_.get_service().write_some( + impl_.get_implementation(), buffers, ec); + asio::detail::throw_error(ec, "write_some"); + return s; + } + + /// Write some data to the pipe. + /** + * This function is used to write data to the pipe. The function call will + * block until one or more bytes of the data has been written successfully, + * or until an error occurs. + * + * @param buffers One or more data buffers to be written to the pipe. + * + * @param ec Set to indicate what error occurred, if any. + * + * @returns The number of bytes written. Returns 0 if an error occurred. + * + * @note The write_some operation may not transmit all of the data to the + * peer. Consider using the @ref write function if you need to ensure that + * all data is written before the blocking operation completes. + */ + template <typename ConstBufferSequence> + std::size_t write_some(const ConstBufferSequence& buffers, + asio::error_code& ec) + { + return impl_.get_service().write_some( + impl_.get_implementation(), buffers, ec); + } + + /// Start an asynchronous write. + /** + * This function is used to asynchronously write data to the pipe. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. + * + * @param buffers One or more data buffers to be written to the pipe. + * Although the buffers object may be copied as necessary, ownership of the + * underlying memory blocks is retained by the caller, which must guarantee + * that they remain valid until the completion handler is called. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: + * @code void handler( + * const asio::error_code& error, // Result of operation. + * std::size_t bytes_transferred // Number of bytes written. + * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a + * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * + * @note The write operation may not transmit all of the data to the peer. + * Consider using the @ref async_write function if you need to ensure that all + * data is written before the asynchronous operation completes. + * + * @par Example + * To write a single data buffer use the @ref buffer function as follows: + * @code + * pipe.async_write_some(asio::buffer(data, size), handler); + * @endcode + * See the @ref buffer documentation for information on writing multiple + * buffers in one go, and how to use it with arrays, boost::array or + * std::vector. + */ + template <typename ConstBufferSequence, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_write_some(const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_write_some>(), token, buffers)) + { + return async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + initiate_async_write_some(this), token, buffers); + } + +private: + // Disallow copying and assignment. + basic_writable_pipe(const basic_writable_pipe&) = delete; + basic_writable_pipe& operator=(const basic_writable_pipe&) = delete; + + class initiate_async_write_some + { + public: + typedef Executor executor_type; + + explicit initiate_async_write_some(basic_writable_pipe* self) + : self_(self) + { + } + + const executor_type& get_executor() const noexcept + { + return self_->get_executor(); + } + + template <typename WriteHandler, typename ConstBufferSequence> + void operator()(WriteHandler&& handler, + const ConstBufferSequence& buffers) const + { + // If you get an error on the following line it means that your handler + // does not meet the documented type requirements for a WriteHandler. + ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check; + + detail::non_const_lvalue<WriteHandler> handler2(handler); + self_->impl_.get_service().async_write_some( + self_->impl_.get_implementation(), buffers, + handler2.value, self_->impl_.get_executor()); + } + + private: + basic_writable_pipe* self_; + }; + +#if defined(ASIO_HAS_IOCP) + detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_; +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) + detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_; +#else + detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_; +#endif +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_PIPE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_BASIC_WRITABLE_PIPE_HPP diff --git a/3rdparty/asio/include/asio/bind_allocator.hpp b/3rdparty/asio/include/asio/bind_allocator.hpp new file mode 100644 index 00000000000..27910a2ec69 --- /dev/null +++ b/3rdparty/asio/include/asio/bind_allocator.hpp @@ -0,0 +1,530 @@ +// +// bind_allocator.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BIND_ALLOCATOR_HPP +#define ASIO_BIND_ALLOCATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/associated_allocator.hpp" +#include "asio/associator.hpp" +#include "asio/async_result.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Helper to automatically define nested typedef result_type. + +template <typename T, typename = void> +struct allocator_binder_result_type +{ +protected: + typedef void result_type_or_void; +}; + +template <typename T> +struct allocator_binder_result_type<T, void_t<typename T::result_type>> +{ + typedef typename T::result_type result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R> +struct allocator_binder_result_type<R(*)()> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R> +struct allocator_binder_result_type<R(&)()> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R, typename A1> +struct allocator_binder_result_type<R(*)(A1)> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R, typename A1> +struct allocator_binder_result_type<R(&)(A1)> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R, typename A1, typename A2> +struct allocator_binder_result_type<R(*)(A1, A2)> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R, typename A1, typename A2> +struct allocator_binder_result_type<R(&)(A1, A2)> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +// Helper to automatically define nested typedef argument_type. + +template <typename T, typename = void> +struct allocator_binder_argument_type {}; + +template <typename T> +struct allocator_binder_argument_type<T, void_t<typename T::argument_type>> +{ + typedef typename T::argument_type argument_type; +}; + +template <typename R, typename A1> +struct allocator_binder_argument_type<R(*)(A1)> +{ + typedef A1 argument_type; +}; + +template <typename R, typename A1> +struct allocator_binder_argument_type<R(&)(A1)> +{ + typedef A1 argument_type; +}; + +// Helper to automatically define nested typedefs first_argument_type and +// second_argument_type. + +template <typename T, typename = void> +struct allocator_binder_argument_types {}; + +template <typename T> +struct allocator_binder_argument_types<T, + void_t<typename T::first_argument_type>> +{ + typedef typename T::first_argument_type first_argument_type; + typedef typename T::second_argument_type second_argument_type; +}; + +template <typename R, typename A1, typename A2> +struct allocator_binder_argument_type<R(*)(A1, A2)> +{ + typedef A1 first_argument_type; + typedef A2 second_argument_type; +}; + +template <typename R, typename A1, typename A2> +struct allocator_binder_argument_type<R(&)(A1, A2)> +{ + typedef A1 first_argument_type; + typedef A2 second_argument_type; +}; + +} // namespace detail + +/// A call wrapper type to bind an allocator of type @c Allocator +/// to an object of type @c T. +template <typename T, typename Allocator> +class allocator_binder +#if !defined(GENERATING_DOCUMENTATION) + : public detail::allocator_binder_result_type<T>, + public detail::allocator_binder_argument_type<T>, + public detail::allocator_binder_argument_types<T> +#endif // !defined(GENERATING_DOCUMENTATION) +{ +public: + /// The type of the target object. + typedef T target_type; + + /// The type of the associated allocator. + typedef Allocator allocator_type; + +#if defined(GENERATING_DOCUMENTATION) + /// The return type if a function. + /** + * The type of @c result_type is based on the type @c T of the wrapper's + * target object: + * + * @li if @c T is a pointer to function type, @c result_type is a synonym for + * the return type of @c T; + * + * @li if @c T is a class type with a member type @c result_type, then @c + * result_type is a synonym for @c T::result_type; + * + * @li otherwise @c result_type is not defined. + */ + typedef see_below result_type; + + /// The type of the function's argument. + /** + * The type of @c argument_type is based on the type @c T of the wrapper's + * target object: + * + * @li if @c T is a pointer to a function type accepting a single argument, + * @c argument_type is a synonym for the return type of @c T; + * + * @li if @c T is a class type with a member type @c argument_type, then @c + * argument_type is a synonym for @c T::argument_type; + * + * @li otherwise @c argument_type is not defined. + */ + typedef see_below argument_type; + + /// The type of the function's first argument. + /** + * The type of @c first_argument_type is based on the type @c T of the + * wrapper's target object: + * + * @li if @c T is a pointer to a function type accepting two arguments, @c + * first_argument_type is a synonym for the return type of @c T; + * + * @li if @c T is a class type with a member type @c first_argument_type, + * then @c first_argument_type is a synonym for @c T::first_argument_type; + * + * @li otherwise @c first_argument_type is not defined. + */ + typedef see_below first_argument_type; + + /// The type of the function's second argument. + /** + * The type of @c second_argument_type is based on the type @c T of the + * wrapper's target object: + * + * @li if @c T is a pointer to a function type accepting two arguments, @c + * second_argument_type is a synonym for the return type of @c T; + * + * @li if @c T is a class type with a member type @c first_argument_type, + * then @c second_argument_type is a synonym for @c T::second_argument_type; + * + * @li otherwise @c second_argument_type is not defined. + */ + typedef see_below second_argument_type; +#endif // defined(GENERATING_DOCUMENTATION) + + /// Construct an allocator wrapper for the specified object. + /** + * This constructor is only valid if the type @c T is constructible from type + * @c U. + */ + template <typename U> + allocator_binder(const allocator_type& s, U&& u) + : allocator_(s), + target_(static_cast<U&&>(u)) + { + } + + /// Copy constructor. + allocator_binder(const allocator_binder& other) + : allocator_(other.get_allocator()), + target_(other.get()) + { + } + + /// Construct a copy, but specify a different allocator. + allocator_binder(const allocator_type& s, const allocator_binder& other) + : allocator_(s), + target_(other.get()) + { + } + + /// Construct a copy of a different allocator wrapper type. + /** + * This constructor is only valid if the @c Allocator type is + * constructible from type @c OtherAllocator, and the type @c T is + * constructible from type @c U. + */ + template <typename U, typename OtherAllocator> + allocator_binder(const allocator_binder<U, OtherAllocator>& other, + constraint_t<is_constructible<Allocator, OtherAllocator>::value> = 0, + constraint_t<is_constructible<T, U>::value> = 0) + : allocator_(other.get_allocator()), + target_(other.get()) + { + } + + /// Construct a copy of a different allocator wrapper type, but + /// specify a different allocator. + /** + * This constructor is only valid if the type @c T is constructible from type + * @c U. + */ + template <typename U, typename OtherAllocator> + allocator_binder(const allocator_type& s, + const allocator_binder<U, OtherAllocator>& other, + constraint_t<is_constructible<T, U>::value> = 0) + : allocator_(s), + target_(other.get()) + { + } + + /// Move constructor. + allocator_binder(allocator_binder&& other) + : allocator_(static_cast<allocator_type&&>( + other.get_allocator())), + target_(static_cast<T&&>(other.get())) + { + } + + /// Move construct the target object, but specify a different allocator. + allocator_binder(const allocator_type& s, + allocator_binder&& other) + : allocator_(s), + target_(static_cast<T&&>(other.get())) + { + } + + /// Move construct from a different allocator wrapper type. + template <typename U, typename OtherAllocator> + allocator_binder( + allocator_binder<U, OtherAllocator>&& other, + constraint_t<is_constructible<Allocator, OtherAllocator>::value> = 0, + constraint_t<is_constructible<T, U>::value> = 0) + : allocator_(static_cast<OtherAllocator&&>( + other.get_allocator())), + target_(static_cast<U&&>(other.get())) + { + } + + /// Move construct from a different allocator wrapper type, but + /// specify a different allocator. + template <typename U, typename OtherAllocator> + allocator_binder(const allocator_type& s, + allocator_binder<U, OtherAllocator>&& other, + constraint_t<is_constructible<T, U>::value> = 0) + : allocator_(s), + target_(static_cast<U&&>(other.get())) + { + } + + /// Destructor. + ~allocator_binder() + { + } + + /// Obtain a reference to the target object. + target_type& get() noexcept + { + return target_; + } + + /// Obtain a reference to the target object. + const target_type& get() const noexcept + { + return target_; + } + + /// Obtain the associated allocator. + allocator_type get_allocator() const noexcept + { + return allocator_; + } + + /// Forwarding function call operator. + template <typename... Args> + result_of_t<T(Args...)> operator()(Args&&... args) + { + return target_(static_cast<Args&&>(args)...); + } + + /// Forwarding function call operator. + template <typename... Args> + result_of_t<T(Args...)> operator()(Args&&... args) const + { + return target_(static_cast<Args&&>(args)...); + } + +private: + Allocator allocator_; + T target_; +}; + +/// Associate an object of type @c T with an allocator of type +/// @c Allocator. +template <typename Allocator, typename T> +ASIO_NODISCARD inline allocator_binder<decay_t<T>, Allocator> +bind_allocator(const Allocator& s, T&& t) +{ + return allocator_binder<decay_t<T>, Allocator>(s, static_cast<T&&>(t)); +} + +#if !defined(GENERATING_DOCUMENTATION) + +namespace detail { + +template <typename TargetAsyncResult, typename Allocator, typename = void> +class allocator_binder_completion_handler_async_result +{ +public: + template <typename T> + explicit allocator_binder_completion_handler_async_result(T&) + { + } +}; + +template <typename TargetAsyncResult, typename Allocator> +class allocator_binder_completion_handler_async_result< + TargetAsyncResult, Allocator, + void_t<typename TargetAsyncResult::completion_handler_type>> +{ +private: + TargetAsyncResult target_; + +public: + typedef allocator_binder< + typename TargetAsyncResult::completion_handler_type, Allocator> + completion_handler_type; + + explicit allocator_binder_completion_handler_async_result( + typename TargetAsyncResult::completion_handler_type& handler) + : target_(handler) + { + } + + auto get() -> decltype(target_.get()) + { + return target_.get(); + } +}; + +template <typename TargetAsyncResult, typename = void> +struct allocator_binder_async_result_return_type +{ +}; + +template <typename TargetAsyncResult> +struct allocator_binder_async_result_return_type< + TargetAsyncResult, void_type<typename TargetAsyncResult::return_type>> +{ + typedef typename TargetAsyncResult::return_type return_type; +}; + +} // namespace detail + +template <typename T, typename Allocator, typename Signature> +class async_result<allocator_binder<T, Allocator>, Signature> : + public detail::allocator_binder_completion_handler_async_result< + async_result<T, Signature>, Allocator>, + public detail::allocator_binder_async_result_return_type< + async_result<T, Signature>> +{ +public: + explicit async_result(allocator_binder<T, Allocator>& b) + : detail::allocator_binder_completion_handler_async_result< + async_result<T, Signature>, Allocator>(b.get()) + { + } + + template <typename Initiation> + struct init_wrapper + { + template <typename Init> + init_wrapper(const Allocator& allocator, Init&& init) + : allocator_(allocator), + initiation_(static_cast<Init&&>(init)) + { + } + + template <typename Handler, typename... Args> + void operator()(Handler&& handler, Args&&... args) + { + static_cast<Initiation&&>(initiation_)( + allocator_binder<decay_t<Handler>, Allocator>( + allocator_, static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); + } + + template <typename Handler, typename... Args> + void operator()(Handler&& handler, Args&&... args) const + { + initiation_( + allocator_binder<decay_t<Handler>, Allocator>( + allocator_, static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); + } + + Allocator allocator_; + Initiation initiation_; + }; + + template <typename Initiation, typename RawCompletionToken, typename... Args> + static auto initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) + -> decltype( + async_initiate<T, Signature>( + declval<init_wrapper<decay_t<Initiation>>>(), + token.get(), static_cast<Args&&>(args)...)) + { + return async_initiate<T, Signature>( + init_wrapper<decay_t<Initiation>>(token.get_allocator(), + static_cast<Initiation&&>(initiation)), + token.get(), static_cast<Args&&>(args)...); + } + +private: + async_result(const async_result&) = delete; + async_result& operator=(const async_result&) = delete; + + async_result<T, Signature> target_; +}; + +template <template <typename, typename> class Associator, + typename T, typename Allocator, typename DefaultCandidate> +struct associator<Associator, allocator_binder<T, Allocator>, DefaultCandidate> + : Associator<T, DefaultCandidate> +{ + static typename Associator<T, DefaultCandidate>::type get( + const allocator_binder<T, Allocator>& b) noexcept + { + return Associator<T, DefaultCandidate>::get(b.get()); + } + + static auto get(const allocator_binder<T, Allocator>& b, + const DefaultCandidate& c) noexcept + -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c)) + { + return Associator<T, DefaultCandidate>::get(b.get(), c); + } +}; + +template <typename T, typename Allocator, typename Allocator1> +struct associated_allocator<allocator_binder<T, Allocator>, Allocator1> +{ + typedef Allocator type; + + static auto get(const allocator_binder<T, Allocator>& b, + const Allocator1& = Allocator1()) noexcept + -> decltype(b.get_allocator()) + { + return b.get_allocator(); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BIND_ALLOCATOR_HPP diff --git a/3rdparty/asio/include/asio/bind_cancellation_slot.hpp b/3rdparty/asio/include/asio/bind_cancellation_slot.hpp index 2a17d8f7327..7be13426283 100644 --- a/3rdparty/asio/include/asio/bind_cancellation_slot.hpp +++ b/3rdparty/asio/include/asio/bind_cancellation_slot.hpp @@ -2,7 +2,7 @@ // bind_cancellation_slot.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,7 +17,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" #include "asio/associated_cancellation_slot.hpp" #include "asio/associator.hpp" #include "asio/async_result.hpp" @@ -37,8 +36,7 @@ protected: }; template <typename T> -struct cancellation_slot_binder_result_type<T, - typename void_type<typename T::result_type>::type> +struct cancellation_slot_binder_result_type<T, void_t<typename T::result_type>> { typedef typename T::result_type result_type; protected: @@ -100,7 +98,7 @@ struct cancellation_slot_binder_argument_type {}; template <typename T> struct cancellation_slot_binder_argument_type<T, - typename void_type<typename T::argument_type>::type> + void_t<typename T::argument_type>> { typedef typename T::argument_type argument_type; }; @@ -125,7 +123,7 @@ struct cancellation_slot_binder_argument_types {}; template <typename T> struct cancellation_slot_binder_argument_types<T, - typename void_type<typename T::first_argument_type>::type> + void_t<typename T::first_argument_type>> { typedef typename T::first_argument_type first_argument_type; typedef typename T::second_argument_type second_argument_type; @@ -145,21 +143,6 @@ struct cancellation_slot_binder_argument_type<R(&)(A1, A2)> typedef A2 second_argument_type; }; -// Helper to enable SFINAE on zero-argument operator() below. - -template <typename T, typename = void> -struct cancellation_slot_binder_result_of0 -{ - typedef void type; -}; - -template <typename T> -struct cancellation_slot_binder_result_of0<T, - typename void_type<typename result_of<T()>::type>::type> -{ - typedef typename result_of<T()>::type type; -}; - } // namespace detail /// A call wrapper type to bind a cancellation slot of type @c CancellationSlot @@ -247,10 +230,9 @@ public: * @c U. */ template <typename U> - cancellation_slot_binder(const cancellation_slot_type& s, - ASIO_MOVE_ARG(U) u) + cancellation_slot_binder(const cancellation_slot_type& s, U&& u) : slot_(s), - target_(ASIO_MOVE_CAST(U)(u)) + target_(static_cast<U&&>(u)) { } @@ -277,7 +259,10 @@ public: */ template <typename U, typename OtherCancellationSlot> cancellation_slot_binder( - const cancellation_slot_binder<U, OtherCancellationSlot>& other) + const cancellation_slot_binder<U, OtherCancellationSlot>& other, + constraint_t<is_constructible<CancellationSlot, + OtherCancellationSlot>::value> = 0, + constraint_t<is_constructible<T, U>::value> = 0) : slot_(other.get_cancellation_slot()), target_(other.get()) { @@ -291,19 +276,18 @@ public: */ template <typename U, typename OtherCancellationSlot> cancellation_slot_binder(const cancellation_slot_type& s, - const cancellation_slot_binder<U, OtherCancellationSlot>& other) + const cancellation_slot_binder<U, OtherCancellationSlot>& other, + constraint_t<is_constructible<T, U>::value> = 0) : slot_(s), target_(other.get()) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move constructor. cancellation_slot_binder(cancellation_slot_binder&& other) - : slot_(ASIO_MOVE_CAST(cancellation_slot_type)( + : slot_(static_cast<cancellation_slot_type&&>( other.get_cancellation_slot())), - target_(ASIO_MOVE_CAST(T)(other.get())) + target_(static_cast<T&&>(other.get())) { } @@ -312,17 +296,20 @@ public: cancellation_slot_binder(const cancellation_slot_type& s, cancellation_slot_binder&& other) : slot_(s), - target_(ASIO_MOVE_CAST(T)(other.get())) + target_(static_cast<T&&>(other.get())) { } /// Move construct from a different cancellation slot wrapper type. template <typename U, typename OtherCancellationSlot> cancellation_slot_binder( - cancellation_slot_binder<U, OtherCancellationSlot>&& other) - : slot_(ASIO_MOVE_CAST(OtherCancellationSlot)( + cancellation_slot_binder<U, OtherCancellationSlot>&& other, + constraint_t<is_constructible<CancellationSlot, + OtherCancellationSlot>::value> = 0, + constraint_t<is_constructible<T, U>::value> = 0) + : slot_(static_cast<OtherCancellationSlot&&>( other.get_cancellation_slot())), - target_(ASIO_MOVE_CAST(U)(other.get())) + target_(static_cast<U&&>(other.get())) { } @@ -330,126 +317,50 @@ public: /// specify a different cancellation slot. template <typename U, typename OtherCancellationSlot> cancellation_slot_binder(const cancellation_slot_type& s, - cancellation_slot_binder<U, OtherCancellationSlot>&& other) + cancellation_slot_binder<U, OtherCancellationSlot>&& other, + constraint_t<is_constructible<T, U>::value> = 0) : slot_(s), - target_(ASIO_MOVE_CAST(U)(other.get())) + target_(static_cast<U&&>(other.get())) { } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Destructor. ~cancellation_slot_binder() { } /// Obtain a reference to the target object. - target_type& get() ASIO_NOEXCEPT + target_type& get() noexcept { return target_; } /// Obtain a reference to the target object. - const target_type& get() const ASIO_NOEXCEPT + const target_type& get() const noexcept { return target_; } /// Obtain the associated cancellation slot. - cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT + cancellation_slot_type get_cancellation_slot() const noexcept { return slot_; } -#if defined(GENERATING_DOCUMENTATION) - - template <typename... Args> auto operator()(Args&& ...); - template <typename... Args> auto operator()(Args&& ...) const; - -#elif defined(ASIO_HAS_VARIADIC_TEMPLATES) - /// Forwarding function call operator. template <typename... Args> - typename result_of<T(Args...)>::type operator()( - ASIO_MOVE_ARG(Args)... args) + result_of_t<T(Args...)> operator()(Args&&... args) { - return target_(ASIO_MOVE_CAST(Args)(args)...); + return target_(static_cast<Args&&>(args)...); } /// Forwarding function call operator. template <typename... Args> - typename result_of<T(Args...)>::type operator()( - ASIO_MOVE_ARG(Args)... args) const - { - return target_(ASIO_MOVE_CAST(Args)(args)...); - } - -#elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER) - - typename detail::cancellation_slot_binder_result_of0<T>::type operator()() - { - return target_(); - } - - typename detail::cancellation_slot_binder_result_of0<T>::type - operator()() const - { - return target_(); - } - -#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \ - ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - { \ - return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF) -#undef ASIO_PRIVATE_BINDER_CALL_DEF - -#else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER) - - typedef typename detail::cancellation_slot_binder_result_type< - T>::result_type_or_void result_type_or_void; - - result_type_or_void operator()() + result_of_t<T(Args...)> operator()(Args&&... args) const { - return target_(); + return target_(static_cast<Args&&>(args)...); } - result_type_or_void operator()() const - { - return target_(); - } - -#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - result_type_or_void operator()( \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - result_type_or_void operator()( \ - ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - { \ - return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF) -#undef ASIO_PRIVATE_BINDER_CALL_DEF - -#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER) - private: CancellationSlot slot_; T target_; @@ -458,12 +369,12 @@ private: /// Associate an object of type @c T with a cancellation slot of type /// @c CancellationSlot. template <typename CancellationSlot, typename T> -inline cancellation_slot_binder<typename decay<T>::type, CancellationSlot> -bind_cancellation_slot(const CancellationSlot& s, ASIO_MOVE_ARG(T) t) +ASIO_NODISCARD inline +cancellation_slot_binder<decay_t<T>, CancellationSlot> +bind_cancellation_slot(const CancellationSlot& s, T&& t) { - return cancellation_slot_binder< - typename decay<T>::type, CancellationSlot>( - s, ASIO_MOVE_CAST(T)(t)); + return cancellation_slot_binder<decay_t<T>, CancellationSlot>( + s, static_cast<T&&>(t)); } #if !defined(GENERATING_DOCUMENTATION) @@ -471,21 +382,39 @@ bind_cancellation_slot(const CancellationSlot& s, ASIO_MOVE_ARG(T) t) namespace detail { template <typename TargetAsyncResult, - typename CancellationSlot, typename = void> -struct cancellation_slot_binder_async_result_completion_handler_type + typename CancellationSlot, typename = void> +class cancellation_slot_binder_completion_handler_async_result { +public: + template <typename T> + explicit cancellation_slot_binder_completion_handler_async_result(T&) + { + } }; template <typename TargetAsyncResult, typename CancellationSlot> -struct cancellation_slot_binder_async_result_completion_handler_type< - TargetAsyncResult, CancellationSlot, - typename void_type< - typename TargetAsyncResult::completion_handler_type - >::type> +class cancellation_slot_binder_completion_handler_async_result< + TargetAsyncResult, CancellationSlot, + void_t<typename TargetAsyncResult::completion_handler_type>> { +private: + TargetAsyncResult target_; + +public: typedef cancellation_slot_binder< typename TargetAsyncResult::completion_handler_type, CancellationSlot> completion_handler_type; + + explicit cancellation_slot_binder_completion_handler_async_result( + typename TargetAsyncResult::completion_handler_type& handler) + : target_(handler) + { + } + + auto get() -> decltype(target_.get()) + { + return target_.get(); + } }; template <typename TargetAsyncResult, typename = void> @@ -495,10 +424,7 @@ struct cancellation_slot_binder_async_result_return_type template <typename TargetAsyncResult> struct cancellation_slot_binder_async_result_return_type< - TargetAsyncResult, - typename void_type< - typename TargetAsyncResult::return_type - >::type> + TargetAsyncResult, void_t<typename TargetAsyncResult::return_type>> { typedef typename TargetAsyncResult::return_type return_type; }; @@ -507,178 +433,68 @@ struct cancellation_slot_binder_async_result_return_type< template <typename T, typename CancellationSlot, typename Signature> class async_result<cancellation_slot_binder<T, CancellationSlot>, Signature> : - public detail::cancellation_slot_binder_async_result_completion_handler_type< - async_result<T, Signature>, CancellationSlot>, + public detail::cancellation_slot_binder_completion_handler_async_result< + async_result<T, Signature>, CancellationSlot>, public detail::cancellation_slot_binder_async_result_return_type< - async_result<T, Signature> > + async_result<T, Signature>> { public: explicit async_result(cancellation_slot_binder<T, CancellationSlot>& b) - : target_(b.get()) + : detail::cancellation_slot_binder_completion_handler_async_result< + async_result<T, Signature>, CancellationSlot>(b.get()) { } - typename async_result<T, Signature>::return_type get() - { - return target_.get(); - } - template <typename Initiation> struct init_wrapper { template <typename Init> - init_wrapper(const CancellationSlot& slot, ASIO_MOVE_ARG(Init) init) + init_wrapper(const CancellationSlot& slot, Init&& init) : slot_(slot), - initiation_(ASIO_MOVE_CAST(Init)(init)) + initiation_(static_cast<Init&&>(init)) { } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Handler, typename... Args> - void operator()( - ASIO_MOVE_ARG(Handler) handler, - ASIO_MOVE_ARG(Args)... args) + void operator()(Handler&& handler, Args&&... args) { - ASIO_MOVE_CAST(Initiation)(initiation_)( - cancellation_slot_binder< - typename decay<Handler>::type, CancellationSlot>( - slot_, ASIO_MOVE_CAST(Handler)(handler)), - ASIO_MOVE_CAST(Args)(args)...); + static_cast<Initiation&&>(initiation_)( + cancellation_slot_binder<decay_t<Handler>, CancellationSlot>( + slot_, static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); } template <typename Handler, typename... Args> - void operator()( - ASIO_MOVE_ARG(Handler) handler, - ASIO_MOVE_ARG(Args)... args) const + void operator()(Handler&& handler, Args&&... args) const { initiation_( - cancellation_slot_binder< - typename decay<Handler>::type, CancellationSlot>( - slot_, ASIO_MOVE_CAST(Handler)(handler)), - ASIO_MOVE_CAST(Args)(args)...); + cancellation_slot_binder<decay_t<Handler>, CancellationSlot>( + slot_, static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); } -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Handler> - void operator()( - ASIO_MOVE_ARG(Handler) handler) - { - ASIO_MOVE_CAST(Initiation)(initiation_)( - cancellation_slot_binder< - typename decay<Handler>::type, CancellationSlot>( - slot_, ASIO_MOVE_CAST(Handler)(handler))); - } - - template <typename Handler> - void operator()( - ASIO_MOVE_ARG(Handler) handler) const - { - initiation_( - cancellation_slot_binder< - typename decay<Handler>::type, CancellationSlot>( - slot_, ASIO_MOVE_CAST(Handler)(handler))); - } - -#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \ - template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \ - void operator()( \ - ASIO_MOVE_ARG(Handler) handler, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - ASIO_MOVE_CAST(Initiation)(initiation_)( \ - cancellation_slot_binder< \ - typename decay<Handler>::type, CancellationSlot>( \ - slot_, ASIO_MOVE_CAST(Handler)(handler)), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \ - void operator()( \ - ASIO_MOVE_ARG(Handler) handler, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - { \ - initiation_( \ - cancellation_slot_binder< \ - typename decay<Handler>::type, CancellationSlot>( \ - slot_, ASIO_MOVE_CAST(Handler)(handler)), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF) -#undef ASIO_PRIVATE_INIT_WRAPPER_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - CancellationSlot slot_; Initiation initiation_; }; -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Initiation, typename RawCompletionToken, typename... Args> - static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, - (async_result<T, Signature>::initiate( - declval<init_wrapper<typename decay<Initiation>::type> >(), - declval<T>(), declval<ASIO_MOVE_ARG(Args)>()...))) - initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token, - ASIO_MOVE_ARG(Args)... args) - { - return async_initiate<T, Signature>( - init_wrapper<typename decay<Initiation>::type>( - token.get_cancellation_slot(), - ASIO_MOVE_CAST(Initiation)(initiation)), - token.get(), ASIO_MOVE_CAST(Args)(args)...); - } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Initiation, typename RawCompletionToken> - static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, - (async_result<T, Signature>::initiate( - declval<init_wrapper<typename decay<Initiation>::type> >(), - declval<T>()))) - initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token) + static auto initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) + -> decltype( + async_initiate<T, Signature>( + declval<init_wrapper<decay_t<Initiation>>>(), + token.get(), static_cast<Args&&>(args)...)) { return async_initiate<T, Signature>( - init_wrapper<typename decay<Initiation>::type>( + init_wrapper<decay_t<Initiation>>( token.get_cancellation_slot(), - ASIO_MOVE_CAST(Initiation)(initiation)), - token.get()); + static_cast<Initiation&&>(initiation)), + token.get(), static_cast<Args&&>(args)...); } -#define ASIO_PRIVATE_INITIATE_DEF(n) \ - template <typename Initiation, typename RawCompletionToken, \ - ASIO_VARIADIC_TPARAMS(n)> \ - static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \ - (async_result<T, Signature>::initiate( \ - declval<init_wrapper<typename decay<Initiation>::type> >(), \ - declval<T>(), ASIO_VARIADIC_MOVE_DECLVAL(n)))) \ - initiate( \ - ASIO_MOVE_ARG(Initiation) initiation, \ - ASIO_MOVE_ARG(RawCompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - return async_initiate<T, Signature>( \ - init_wrapper<typename decay<Initiation>::type>( \ - token.get_cancellation_slot(), \ - ASIO_MOVE_CAST(Initiation)(initiation)), \ - token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF) -#undef ASIO_PRIVATE_INITIATE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - private: - async_result(const async_result&) ASIO_DELETED; - async_result& operator=(const async_result&) ASIO_DELETED; + async_result(const async_result&) = delete; + async_result& operator=(const async_result&) = delete; async_result<T, Signature> target_; }; @@ -688,11 +504,17 @@ template <template <typename, typename> class Associator, struct associator<Associator, cancellation_slot_binder<T, CancellationSlot>, DefaultCandidate> + : Associator<T, DefaultCandidate> { - typedef typename Associator<T, DefaultCandidate>::type type; + static typename Associator<T, DefaultCandidate>::type get( + const cancellation_slot_binder<T, CancellationSlot>& b) noexcept + { + return Associator<T, DefaultCandidate>::get(b.get()); + } - static type get(const cancellation_slot_binder<T, CancellationSlot>& b, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + static auto get(const cancellation_slot_binder<T, CancellationSlot>& b, + const DefaultCandidate& c) noexcept + -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c)) { return Associator<T, DefaultCandidate>::get(b.get(), c); } @@ -705,8 +527,9 @@ struct associated_cancellation_slot< { typedef CancellationSlot type; - static type get(const cancellation_slot_binder<T, CancellationSlot>& b, - const CancellationSlot1& = CancellationSlot1()) ASIO_NOEXCEPT + static auto get(const cancellation_slot_binder<T, CancellationSlot>& b, + const CancellationSlot1& = CancellationSlot1()) noexcept + -> decltype(b.get_cancellation_slot()) { return b.get_cancellation_slot(); } diff --git a/3rdparty/asio/include/asio/bind_executor.hpp b/3rdparty/asio/include/asio/bind_executor.hpp index 4da0b01e268..f117b4ce903 100644 --- a/3rdparty/asio/include/asio/bind_executor.hpp +++ b/3rdparty/asio/include/asio/bind_executor.hpp @@ -2,7 +2,7 @@ // bind_executor.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,7 +17,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" #include "asio/associated_executor.hpp" #include "asio/associator.hpp" #include "asio/async_result.hpp" @@ -41,8 +40,7 @@ protected: }; template <typename T> -struct executor_binder_result_type<T, - typename void_type<typename T::result_type>::type> +struct executor_binder_result_type<T, void_t<typename T::result_type>> { typedef typename T::result_type result_type; protected: @@ -103,8 +101,7 @@ template <typename T, typename = void> struct executor_binder_argument_type {}; template <typename T> -struct executor_binder_argument_type<T, - typename void_type<typename T::argument_type>::type> +struct executor_binder_argument_type<T, void_t<typename T::argument_type>> { typedef typename T::argument_type argument_type; }; @@ -129,7 +126,7 @@ struct executor_binder_argument_types {}; template <typename T> struct executor_binder_argument_types<T, - typename void_type<typename T::first_argument_type>::type> + void_t<typename T::first_argument_type>> { typedef typename T::first_argument_type first_argument_type; typedef typename T::second_argument_type second_argument_type; @@ -160,9 +157,9 @@ class executor_binder_base<T, Executor, true> { protected: template <typename E, typename U> - executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u) - : executor_(ASIO_MOVE_CAST(E)(e)), - target_(executor_arg_t(), executor_, ASIO_MOVE_CAST(U)(u)) + executor_binder_base(E&& e, U&& u) + : executor_(static_cast<E&&>(e)), + target_(executor_arg_t(), executor_, static_cast<U&&>(u)) { } @@ -175,9 +172,9 @@ class executor_binder_base<T, Executor, false> { protected: template <typename E, typename U> - executor_binder_base(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(U) u) - : executor_(ASIO_MOVE_CAST(E)(e)), - target_(ASIO_MOVE_CAST(U)(u)) + executor_binder_base(E&& e, U&& u) + : executor_(static_cast<E&&>(e)), + target_(static_cast<U&&>(u)) { } @@ -185,21 +182,6 @@ protected: 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 void_type<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 @@ -290,8 +272,8 @@ public: */ template <typename U> executor_binder(executor_arg_t, const executor_type& e, - ASIO_MOVE_ARG(U) u) - : base_type(e, ASIO_MOVE_CAST(U)(u)) + U&& u) + : base_type(e, static_cast<U&&>(u)) { } @@ -315,7 +297,9 @@ public: * @c U. */ template <typename U, typename OtherExecutor> - executor_binder(const executor_binder<U, OtherExecutor>& other) + executor_binder(const executor_binder<U, OtherExecutor>& other, + constraint_t<is_constructible<Executor, OtherExecutor>::value> = 0, + constraint_t<is_constructible<T, U>::value> = 0) : base_type(other.get_executor(), other.get()) { } @@ -328,32 +312,33 @@ public: */ template <typename U, typename OtherExecutor> executor_binder(executor_arg_t, const executor_type& e, - const executor_binder<U, OtherExecutor>& other) + const executor_binder<U, OtherExecutor>& other, + constraint_t<is_constructible<T, U>::value> = 0) : base_type(e, other.get()) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move constructor. executor_binder(executor_binder&& other) - : base_type(ASIO_MOVE_CAST(executor_type)(other.get_executor()), - ASIO_MOVE_CAST(T)(other.get())) + : base_type(static_cast<executor_type&&>(other.get_executor()), + static_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, ASIO_MOVE_CAST(T)(other.get())) + : base_type(e, static_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(ASIO_MOVE_CAST(OtherExecutor)(other.get_executor()), - ASIO_MOVE_CAST(U)(other.get())) + executor_binder(executor_binder<U, OtherExecutor>&& other, + constraint_t<is_constructible<Executor, OtherExecutor>::value> = 0, + constraint_t<is_constructible<T, U>::value> = 0) + : base_type(static_cast<OtherExecutor&&>(other.get_executor()), + static_cast<U&&>(other.get())) { } @@ -361,124 +346,49 @@ public: /// different executor. template <typename U, typename OtherExecutor> executor_binder(executor_arg_t, const executor_type& e, - executor_binder<U, OtherExecutor>&& other) - : base_type(e, ASIO_MOVE_CAST(U)(other.get())) + executor_binder<U, OtherExecutor>&& other, + constraint_t<is_constructible<T, U>::value> = 0) + : base_type(e, static_cast<U&&>(other.get())) { } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Destructor. ~executor_binder() { } /// Obtain a reference to the target object. - target_type& get() ASIO_NOEXCEPT + target_type& get() noexcept { return this->target_; } /// Obtain a reference to the target object. - const target_type& get() const ASIO_NOEXCEPT + const target_type& get() const noexcept { return this->target_; } /// Obtain the associated executor. - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return this->executor_; } -#if defined(GENERATING_DOCUMENTATION) - - template <typename... Args> auto operator()(Args&& ...); - template <typename... Args> auto operator()(Args&& ...) const; - -#elif defined(ASIO_HAS_VARIADIC_TEMPLATES) - /// Forwarding function call operator. template <typename... Args> - typename result_of<T(Args...)>::type operator()( - ASIO_MOVE_ARG(Args)... args) + result_of_t<T(Args...)> operator()(Args&&... args) { - return this->target_(ASIO_MOVE_CAST(Args)(args)...); + return this->target_(static_cast<Args&&>(args)...); } /// Forwarding function call operator. template <typename... Args> - typename result_of<T(Args...)>::type operator()( - ASIO_MOVE_ARG(Args)... args) const + result_of_t<T(Args...)> operator()(Args&&... args) const { - return this->target_(ASIO_MOVE_CAST(Args)(args)...); + return this->target_(static_cast<Args&&>(args)...); } -#elif defined(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 ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \ - ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - { \ - return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF) -#undef ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF - -#else // defined(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 ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - result_type_or_void operator()( \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - result_type_or_void operator()( \ - ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - { \ - return this->target_(ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF) -#undef ASIO_PRIVATE_BIND_EXECUTOR_CALL_DEF - -#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER) - private: typedef detail::executor_binder_base<T, Executor, uses_executor<T, Executor>::value> base_type; @@ -486,27 +396,27 @@ private: /// 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, ASIO_MOVE_ARG(T) t, - typename constraint< +ASIO_NODISCARD inline executor_binder<decay_t<T>, Executor> +bind_executor(const Executor& ex, T&& t, + constraint_t< is_executor<Executor>::value || execution::is_executor<Executor>::value - >::type = 0) + > = 0) { - return executor_binder<typename decay<T>::type, Executor>( - executor_arg_t(), ex, ASIO_MOVE_CAST(T)(t)); + return executor_binder<decay_t<T>, Executor>( + executor_arg_t(), ex, static_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, ASIO_MOVE_ARG(T) t, - typename constraint<is_convertible< - ExecutionContext&, execution_context&>::value>::type = 0) +ASIO_NODISCARD inline executor_binder<decay_t<T>, + typename ExecutionContext::executor_type> +bind_executor(ExecutionContext& ctx, T&& t, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) { - return executor_binder<typename decay<T>::type, - typename ExecutionContext::executor_type>( - executor_arg_t(), ctx.get_executor(), ASIO_MOVE_CAST(T)(t)); + return executor_binder<decay_t<T>, typename ExecutionContext::executor_type>( + executor_arg_t(), ctx.get_executor(), static_cast<T&&>(t)); } #if !defined(GENERATING_DOCUMENTATION) @@ -518,20 +428,38 @@ struct uses_executor<executor_binder<T, Executor>, Executor> namespace detail { template <typename TargetAsyncResult, typename Executor, typename = void> -struct executor_binder_async_result_completion_handler_type +class executor_binder_completion_handler_async_result { +public: + template <typename T> + explicit executor_binder_completion_handler_async_result(T&) + { + } }; template <typename TargetAsyncResult, typename Executor> -struct executor_binder_async_result_completion_handler_type< - TargetAsyncResult, Executor, - typename void_type< - typename TargetAsyncResult::completion_handler_type - >::type> +class executor_binder_completion_handler_async_result< + TargetAsyncResult, Executor, + void_t<typename TargetAsyncResult::completion_handler_type >> { +private: + TargetAsyncResult target_; + +public: typedef executor_binder< typename TargetAsyncResult::completion_handler_type, Executor> completion_handler_type; + + explicit executor_binder_completion_handler_async_result( + typename TargetAsyncResult::completion_handler_type& handler) + : target_(handler) + { + } + + auto get() -> decltype(target_.get()) + { + return target_.get(); + } }; template <typename TargetAsyncResult, typename = void> @@ -540,11 +468,8 @@ struct executor_binder_async_result_return_type }; template <typename TargetAsyncResult> -struct executor_binder_async_result_return_type< - TargetAsyncResult, - typename void_type< - typename TargetAsyncResult::return_type - >::type> +struct executor_binder_async_result_return_type<TargetAsyncResult, + void_t<typename TargetAsyncResult::return_type>> { typedef typename TargetAsyncResult::return_type return_type; }; @@ -553,181 +478,83 @@ struct executor_binder_async_result_return_type< template <typename T, typename Executor, typename Signature> class async_result<executor_binder<T, Executor>, Signature> : - public detail::executor_binder_async_result_completion_handler_type< - async_result<T, Signature>, Executor>, + public detail::executor_binder_completion_handler_async_result< + async_result<T, Signature>, Executor>, public detail::executor_binder_async_result_return_type< - async_result<T, Signature> > + async_result<T, Signature>> { public: explicit async_result(executor_binder<T, Executor>& b) - : target_(b.get()) + : detail::executor_binder_completion_handler_async_result< + async_result<T, Signature>, Executor>(b.get()) { } - typename async_result<T, Signature>::return_type get() - { - return target_.get(); - } - template <typename Initiation> struct init_wrapper { template <typename Init> - init_wrapper(const Executor& ex, ASIO_MOVE_ARG(Init) init) + init_wrapper(const Executor& ex, Init&& init) : ex_(ex), - initiation_(ASIO_MOVE_CAST(Init)(init)) + initiation_(static_cast<Init&&>(init)) { } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Handler, typename... Args> - void operator()( - ASIO_MOVE_ARG(Handler) handler, - ASIO_MOVE_ARG(Args)... args) + void operator()(Handler&& handler, Args&&... args) { - ASIO_MOVE_CAST(Initiation)(initiation_)( - executor_binder<typename decay<Handler>::type, Executor>( - executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), - ASIO_MOVE_CAST(Args)(args)...); + static_cast<Initiation&&>(initiation_)( + executor_binder<decay_t<Handler>, Executor>( + executor_arg_t(), ex_, static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); } template <typename Handler, typename... Args> - void operator()( - ASIO_MOVE_ARG(Handler) handler, - ASIO_MOVE_ARG(Args)... args) const + void operator()(Handler&& handler, Args&&... args) const { initiation_( - executor_binder<typename decay<Handler>::type, Executor>( - executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), - ASIO_MOVE_CAST(Args)(args)...); + executor_binder<decay_t<Handler>, Executor>( + executor_arg_t(), ex_, static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); } -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Handler> - void operator()( - ASIO_MOVE_ARG(Handler) handler) - { - ASIO_MOVE_CAST(Initiation)(initiation_)( - executor_binder<typename decay<Handler>::type, Executor>( - executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler))); - } - - template <typename Handler> - void operator()( - ASIO_MOVE_ARG(Handler) handler) const - { - initiation_( - executor_binder<typename decay<Handler>::type, Executor>( - executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler))); - } - -#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \ - template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \ - void operator()( \ - ASIO_MOVE_ARG(Handler) handler, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - ASIO_MOVE_CAST(Initiation)(initiation_)( \ - executor_binder<typename decay<Handler>::type, Executor>( \ - executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \ - void operator()( \ - ASIO_MOVE_ARG(Handler) handler, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - { \ - initiation_( \ - executor_binder<typename decay<Handler>::type, Executor>( \ - executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF) -#undef ASIO_PRIVATE_INIT_WRAPPER_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - Executor ex_; Initiation initiation_; }; -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Initiation, typename RawCompletionToken, typename... Args> - static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, - (async_result<T, Signature>::initiate( - declval<init_wrapper<typename decay<Initiation>::type> >(), - declval<T>(), declval<ASIO_MOVE_ARG(Args)>()...))) - initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token, - ASIO_MOVE_ARG(Args)... args) - { - return async_initiate<T, Signature>( - init_wrapper<typename decay<Initiation>::type>( - token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)), - token.get(), ASIO_MOVE_CAST(Args)(args)...); - } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Initiation, typename RawCompletionToken> - static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, - (async_result<T, Signature>::initiate( - declval<init_wrapper<typename decay<Initiation>::type> >(), - declval<T>()))) - initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token) + static auto initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) + -> decltype( + async_initiate<T, Signature>( + declval<init_wrapper<decay_t<Initiation>>>(), + token.get(), static_cast<Args&&>(args)...)) { return async_initiate<T, Signature>( - init_wrapper<typename decay<Initiation>::type>( - token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)), - token.get()); + init_wrapper<decay_t<Initiation>>( + token.get_executor(), static_cast<Initiation&&>(initiation)), + token.get(), static_cast<Args&&>(args)...); } -#define ASIO_PRIVATE_INITIATE_DEF(n) \ - template <typename Initiation, typename RawCompletionToken, \ - ASIO_VARIADIC_TPARAMS(n)> \ - static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \ - (async_result<T, Signature>::initiate( \ - declval<init_wrapper<typename decay<Initiation>::type> >(), \ - declval<T>(), ASIO_VARIADIC_MOVE_DECLVAL(n)))) \ - initiate( \ - ASIO_MOVE_ARG(Initiation) initiation, \ - ASIO_MOVE_ARG(RawCompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - return async_initiate<T, Signature>( \ - init_wrapper<typename decay<Initiation>::type>( \ - token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)), \ - token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF) -#undef ASIO_PRIVATE_INITIATE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - private: - async_result(const async_result&) ASIO_DELETED; - async_result& operator=(const async_result&) ASIO_DELETED; - - async_result<T, Signature> target_; + async_result(const async_result&) = delete; + async_result& operator=(const async_result&) = delete; }; template <template <typename, typename> class Associator, typename T, typename Executor, typename DefaultCandidate> struct associator<Associator, executor_binder<T, Executor>, DefaultCandidate> + : Associator<T, DefaultCandidate> { - typedef typename Associator<T, DefaultCandidate>::type type; + static typename Associator<T, DefaultCandidate>::type get( + const executor_binder<T, Executor>& b) noexcept + { + return Associator<T, DefaultCandidate>::get(b.get()); + } - static type get(const executor_binder<T, Executor>& b, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + static auto get(const executor_binder<T, Executor>& b, + const DefaultCandidate& c) noexcept + -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c)) { return Associator<T, DefaultCandidate>::get(b.get(), c); } @@ -738,8 +565,9 @@ struct associated_executor<executor_binder<T, Executor>, Executor1> { typedef Executor type; - static type get(const executor_binder<T, Executor>& b, - const Executor1& = Executor1()) ASIO_NOEXCEPT + static auto get(const executor_binder<T, Executor>& b, + const Executor1& = Executor1()) noexcept + -> decltype(b.get_executor()) { return b.get_executor(); } diff --git a/3rdparty/asio/include/asio/bind_immediate_executor.hpp b/3rdparty/asio/include/asio/bind_immediate_executor.hpp new file mode 100644 index 00000000000..b02c520a689 --- /dev/null +++ b/3rdparty/asio/include/asio/bind_immediate_executor.hpp @@ -0,0 +1,549 @@ +// +// bind_immediate_executor.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BIND_IMMEDIATE_EXECUTOR_HPP +#define ASIO_BIND_IMMEDIATE_EXECUTOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/associated_immediate_executor.hpp" +#include "asio/associator.hpp" +#include "asio/async_result.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Helper to automatically define nested typedef result_type. + +template <typename T, typename = void> +struct immediate_executor_binder_result_type +{ +protected: + typedef void result_type_or_void; +}; + +template <typename T> +struct immediate_executor_binder_result_type<T, void_t<typename T::result_type>> +{ + typedef typename T::result_type result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R> +struct immediate_executor_binder_result_type<R(*)()> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R> +struct immediate_executor_binder_result_type<R(&)()> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R, typename A1> +struct immediate_executor_binder_result_type<R(*)(A1)> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R, typename A1> +struct immediate_executor_binder_result_type<R(&)(A1)> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R, typename A1, typename A2> +struct immediate_executor_binder_result_type<R(*)(A1, A2)> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +template <typename R, typename A1, typename A2> +struct immediate_executor_binder_result_type<R(&)(A1, A2)> +{ + typedef R result_type; +protected: + typedef result_type result_type_or_void; +}; + +// Helper to automatically define nested typedef argument_type. + +template <typename T, typename = void> +struct immediate_executor_binder_argument_type {}; + +template <typename T> +struct immediate_executor_binder_argument_type<T, + void_t<typename T::argument_type>> +{ + typedef typename T::argument_type argument_type; +}; + +template <typename R, typename A1> +struct immediate_executor_binder_argument_type<R(*)(A1)> +{ + typedef A1 argument_type; +}; + +template <typename R, typename A1> +struct immediate_executor_binder_argument_type<R(&)(A1)> +{ + typedef A1 argument_type; +}; + +// Helper to automatically define nested typedefs first_argument_type and +// second_argument_type. + +template <typename T, typename = void> +struct immediate_executor_binder_argument_types {}; + +template <typename T> +struct immediate_executor_binder_argument_types<T, + void_t<typename T::first_argument_type>> +{ + typedef typename T::first_argument_type first_argument_type; + typedef typename T::second_argument_type second_argument_type; +}; + +template <typename R, typename A1, typename A2> +struct immediate_executor_binder_argument_type<R(*)(A1, A2)> +{ + typedef A1 first_argument_type; + typedef A2 second_argument_type; +}; + +template <typename R, typename A1, typename A2> +struct immediate_executor_binder_argument_type<R(&)(A1, A2)> +{ + typedef A1 first_argument_type; + typedef A2 second_argument_type; +}; + +} // namespace detail + +/// A call wrapper type to bind a immediate executor of type @c Executor +/// to an object of type @c T. +template <typename T, typename Executor> +class immediate_executor_binder +#if !defined(GENERATING_DOCUMENTATION) + : public detail::immediate_executor_binder_result_type<T>, + public detail::immediate_executor_binder_argument_type<T>, + public detail::immediate_executor_binder_argument_types<T> +#endif // !defined(GENERATING_DOCUMENTATION) +{ +public: + /// The type of the target object. + typedef T target_type; + + /// The type of the associated immediate executor. + typedef Executor immediate_executor_type; + +#if defined(GENERATING_DOCUMENTATION) + /// The return type if a function. + /** + * The type of @c result_type is based on the type @c T of the wrapper's + * target object: + * + * @li if @c T is a pointer to function type, @c result_type is a synonym for + * the return type of @c T; + * + * @li if @c T is a class type with a member type @c result_type, then @c + * result_type is a synonym for @c T::result_type; + * + * @li otherwise @c result_type is not defined. + */ + typedef see_below result_type; + + /// The type of the function's argument. + /** + * The type of @c argument_type is based on the type @c T of the wrapper's + * target object: + * + * @li if @c T is a pointer to a function type accepting a single argument, + * @c argument_type is a synonym for the return type of @c T; + * + * @li if @c T is a class type with a member type @c argument_type, then @c + * argument_type is a synonym for @c T::argument_type; + * + * @li otherwise @c argument_type is not defined. + */ + typedef see_below argument_type; + + /// The type of the function's first argument. + /** + * The type of @c first_argument_type is based on the type @c T of the + * wrapper's target object: + * + * @li if @c T is a pointer to a function type accepting two arguments, @c + * first_argument_type is a synonym for the return type of @c T; + * + * @li if @c T is a class type with a member type @c first_argument_type, + * then @c first_argument_type is a synonym for @c T::first_argument_type; + * + * @li otherwise @c first_argument_type is not defined. + */ + typedef see_below first_argument_type; + + /// The type of the function's second argument. + /** + * The type of @c second_argument_type is based on the type @c T of the + * wrapper's target object: + * + * @li if @c T is a pointer to a function type accepting two arguments, @c + * second_argument_type is a synonym for the return type of @c T; + * + * @li if @c T is a class type with a member type @c first_argument_type, + * then @c second_argument_type is a synonym for @c T::second_argument_type; + * + * @li otherwise @c second_argument_type is not defined. + */ + typedef see_below second_argument_type; +#endif // defined(GENERATING_DOCUMENTATION) + + /// Construct a immediate executor wrapper for the specified object. + /** + * This constructor is only valid if the type @c T is constructible from type + * @c U. + */ + template <typename U> + immediate_executor_binder(const immediate_executor_type& e, + U&& u) + : executor_(e), + target_(static_cast<U&&>(u)) + { + } + + /// Copy constructor. + immediate_executor_binder(const immediate_executor_binder& other) + : executor_(other.get_immediate_executor()), + target_(other.get()) + { + } + + /// Construct a copy, but specify a different immediate executor. + immediate_executor_binder(const immediate_executor_type& e, + const immediate_executor_binder& other) + : executor_(e), + target_(other.get()) + { + } + + /// Construct a copy of a different immediate executor wrapper type. + /** + * This constructor is only valid if the @c Executor type is + * constructible from type @c OtherExecutor, and the type @c T is + * constructible from type @c U. + */ + template <typename U, typename OtherExecutor> + immediate_executor_binder( + const immediate_executor_binder<U, OtherExecutor>& other, + constraint_t<is_constructible<Executor, OtherExecutor>::value> = 0, + constraint_t<is_constructible<T, U>::value> = 0) + : executor_(other.get_immediate_executor()), + target_(other.get()) + { + } + + /// Construct a copy of a different immediate executor wrapper type, but + /// specify a different immediate executor. + /** + * This constructor is only valid if the type @c T is constructible from type + * @c U. + */ + template <typename U, typename OtherExecutor> + immediate_executor_binder(const immediate_executor_type& e, + const immediate_executor_binder<U, OtherExecutor>& other, + constraint_t<is_constructible<T, U>::value> = 0) + : executor_(e), + target_(other.get()) + { + } + + /// Move constructor. + immediate_executor_binder(immediate_executor_binder&& other) + : executor_(static_cast<immediate_executor_type&&>( + other.get_immediate_executor())), + target_(static_cast<T&&>(other.get())) + { + } + + /// Move construct the target object, but specify a different immediate + /// executor. + immediate_executor_binder(const immediate_executor_type& e, + immediate_executor_binder&& other) + : executor_(e), + target_(static_cast<T&&>(other.get())) + { + } + + /// Move construct from a different immediate executor wrapper type. + template <typename U, typename OtherExecutor> + immediate_executor_binder( + immediate_executor_binder<U, OtherExecutor>&& other, + constraint_t<is_constructible<Executor, OtherExecutor>::value> = 0, + constraint_t<is_constructible<T, U>::value> = 0) + : executor_(static_cast<OtherExecutor&&>( + other.get_immediate_executor())), + target_(static_cast<U&&>(other.get())) + { + } + + /// Move construct from a different immediate executor wrapper type, but + /// specify a different immediate executor. + template <typename U, typename OtherExecutor> + immediate_executor_binder(const immediate_executor_type& e, + immediate_executor_binder<U, OtherExecutor>&& other, + constraint_t<is_constructible<T, U>::value> = 0) + : executor_(e), + target_(static_cast<U&&>(other.get())) + { + } + + /// Destructor. + ~immediate_executor_binder() + { + } + + /// Obtain a reference to the target object. + target_type& get() noexcept + { + return target_; + } + + /// Obtain a reference to the target object. + const target_type& get() const noexcept + { + return target_; + } + + /// Obtain the associated immediate executor. + immediate_executor_type get_immediate_executor() const noexcept + { + return executor_; + } + + /// Forwarding function call operator. + template <typename... Args> + result_of_t<T(Args...)> operator()(Args&&... args) + { + return target_(static_cast<Args&&>(args)...); + } + + /// Forwarding function call operator. + template <typename... Args> + result_of_t<T(Args...)> operator()(Args&&... args) const + { + return target_(static_cast<Args&&>(args)...); + } + +private: + Executor executor_; + T target_; +}; + +/// Associate an object of type @c T with a immediate executor of type +/// @c Executor. +template <typename Executor, typename T> +ASIO_NODISCARD inline immediate_executor_binder<decay_t<T>, Executor> +bind_immediate_executor(const Executor& e, T&& t) +{ + return immediate_executor_binder< + decay_t<T>, Executor>( + e, static_cast<T&&>(t)); +} + +#if !defined(GENERATING_DOCUMENTATION) + +namespace detail { + +template <typename TargetAsyncResult, typename Executor, typename = void> +class immediate_executor_binder_completion_handler_async_result +{ +public: + template <typename T> + explicit immediate_executor_binder_completion_handler_async_result(T&) + { + } +}; + +template <typename TargetAsyncResult, typename Executor> +class immediate_executor_binder_completion_handler_async_result< + TargetAsyncResult, Executor, + void_t< + typename TargetAsyncResult::completion_handler_type + >> +{ +private: + TargetAsyncResult target_; + +public: + typedef immediate_executor_binder< + typename TargetAsyncResult::completion_handler_type, Executor> + completion_handler_type; + + explicit immediate_executor_binder_completion_handler_async_result( + typename TargetAsyncResult::completion_handler_type& handler) + : target_(handler) + { + } + + auto get() -> decltype(target_.get()) + { + return target_.get(); + } +}; + +template <typename TargetAsyncResult, typename = void> +struct immediate_executor_binder_async_result_return_type +{ +}; + +template <typename TargetAsyncResult> +struct immediate_executor_binder_async_result_return_type< + TargetAsyncResult, + void_t< + typename TargetAsyncResult::return_type + >> +{ + typedef typename TargetAsyncResult::return_type return_type; +}; + +} // namespace detail + +template <typename T, typename Executor, typename Signature> +class async_result<immediate_executor_binder<T, Executor>, Signature> : + public detail::immediate_executor_binder_completion_handler_async_result< + async_result<T, Signature>, Executor>, + public detail::immediate_executor_binder_async_result_return_type< + async_result<T, Signature>> +{ +public: + explicit async_result(immediate_executor_binder<T, Executor>& b) + : detail::immediate_executor_binder_completion_handler_async_result< + async_result<T, Signature>, Executor>(b.get()) + { + } + + template <typename Initiation> + struct init_wrapper + { + template <typename Init> + init_wrapper(const Executor& e, Init&& init) + : executor_(e), + initiation_(static_cast<Init&&>(init)) + { + } + + template <typename Handler, typename... Args> + void operator()(Handler&& handler, Args&&... args) + { + static_cast<Initiation&&>(initiation_)( + immediate_executor_binder< + decay_t<Handler>, Executor>( + executor_, static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); + } + + template <typename Handler, typename... Args> + void operator()(Handler&& handler, Args&&... args) const + { + initiation_( + immediate_executor_binder< + decay_t<Handler>, Executor>( + executor_, static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); + } + + Executor executor_; + Initiation initiation_; + }; + + template <typename Initiation, typename RawCompletionToken, typename... Args> + static auto initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) + -> decltype( + async_initiate<T, Signature>( + declval<init_wrapper<decay_t<Initiation>>>(), + token.get(), static_cast<Args&&>(args)...)) + { + return async_initiate<T, Signature>( + init_wrapper<decay_t<Initiation>>( + token.get_immediate_executor(), + static_cast<Initiation&&>(initiation)), + token.get(), static_cast<Args&&>(args)...); + } + +private: + async_result(const async_result&) = delete; + async_result& operator=(const async_result&) = delete; + + async_result<T, Signature> target_; +}; + +template <template <typename, typename> class Associator, + typename T, typename Executor, typename DefaultCandidate> +struct associator<Associator, + immediate_executor_binder<T, Executor>, + DefaultCandidate> + : Associator<T, DefaultCandidate> +{ + static typename Associator<T, DefaultCandidate>::type get( + const immediate_executor_binder<T, Executor>& b) noexcept + { + return Associator<T, DefaultCandidate>::get(b.get()); + } + + static auto get(const immediate_executor_binder<T, Executor>& b, + const DefaultCandidate& c) noexcept + -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c)) + { + return Associator<T, DefaultCandidate>::get(b.get(), c); + } +}; + +template <typename T, typename Executor, typename Executor1> +struct associated_immediate_executor< + immediate_executor_binder<T, Executor>, + Executor1> +{ + typedef Executor type; + + static auto get(const immediate_executor_binder<T, Executor>& b, + const Executor1& = Executor1()) noexcept + -> decltype(b.get_immediate_executor()) + { + return b.get_immediate_executor(); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BIND_IMMEDIATE_EXECUTOR_HPP diff --git a/3rdparty/asio/include/asio/buffer.hpp b/3rdparty/asio/include/asio/buffer.hpp index 32848dc7850..ad49f290a66 100644 --- a/3rdparty/asio/include/asio/buffer.hpp +++ b/3rdparty/asio/include/asio/buffer.hpp @@ -2,7 +2,7 @@ // buffer.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -27,6 +27,7 @@ #include "asio/detail/string_view.hpp" #include "asio/detail/throw_exception.hpp" #include "asio/detail/type_traits.hpp" +#include "asio/is_contiguous_iterator.hpp" #if defined(ASIO_MSVC) && (ASIO_MSVC >= 1700) # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0) @@ -48,21 +49,6 @@ # include "asio/detail/functional.hpp" #endif // ASIO_ENABLE_BUFFER_DEBUGGING -#if defined(ASIO_HAS_BOOST_WORKAROUND) -# include <boost/detail/workaround.hpp> -# if !defined(__clang__) -# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) -# define ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND -# endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) -# elif BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) -# define ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND -# endif // BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) -#endif // defined(ASIO_HAS_BOOST_WORKAROUND) - -#if defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) -# include "asio/detail/type_traits.hpp" -#endif // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) - #include "asio/detail/push_options.hpp" namespace asio { @@ -93,14 +79,14 @@ class mutable_buffer { public: /// Construct an empty buffer. - mutable_buffer() ASIO_NOEXCEPT + mutable_buffer() noexcept : data_(0), size_(0) { } /// Construct a buffer to represent a given memory range. - mutable_buffer(void* data, std::size_t size) ASIO_NOEXCEPT + mutable_buffer(void* data, std::size_t size) noexcept : data_(data), size_(size) { @@ -122,7 +108,7 @@ public: #endif // ASIO_ENABLE_BUFFER_DEBUGGING /// Get a pointer to the beginning of the memory range. - void* data() const ASIO_NOEXCEPT + void* data() const noexcept { #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) if (size_ && debug_check_) @@ -132,13 +118,13 @@ public: } /// Get the size of the memory range. - std::size_t size() const ASIO_NOEXCEPT + std::size_t size() const noexcept { return size_; } /// Move the start of the buffer by the specified number of bytes. - mutable_buffer& operator+=(std::size_t n) ASIO_NOEXCEPT + mutable_buffer& operator+=(std::size_t n) noexcept { std::size_t offset = n < size_ ? n : size_; data_ = static_cast<char*>(data_) + offset; @@ -170,7 +156,7 @@ public: typedef const mutable_buffer* const_iterator; /// Construct to represent a given memory range. - mutable_buffers_1(void* data, std::size_t size) ASIO_NOEXCEPT + mutable_buffers_1(void* data, std::size_t size) noexcept : mutable_buffer(data, size) { } @@ -184,19 +170,19 @@ public: #endif // ASIO_ENABLE_BUFFER_DEBUGGING /// Construct to represent a single modifiable buffer. - explicit mutable_buffers_1(const mutable_buffer& b) ASIO_NOEXCEPT + explicit mutable_buffers_1(const mutable_buffer& b) noexcept : mutable_buffer(b) { } /// Get a random-access iterator to the first element. - const_iterator begin() const ASIO_NOEXCEPT + const_iterator begin() const noexcept { return this; } /// Get a random-access iterator for one past the last element. - const_iterator end() const ASIO_NOEXCEPT + const_iterator end() const noexcept { return begin() + 1; } @@ -227,21 +213,21 @@ class const_buffer { public: /// Construct an empty buffer. - const_buffer() ASIO_NOEXCEPT + const_buffer() noexcept : data_(0), size_(0) { } /// Construct a buffer to represent a given memory range. - const_buffer(const void* data, std::size_t size) ASIO_NOEXCEPT + const_buffer(const void* data, std::size_t size) noexcept : data_(data), size_(size) { } /// Construct a non-modifiable buffer from a modifiable one. - const_buffer(const mutable_buffer& b) ASIO_NOEXCEPT + const_buffer(const mutable_buffer& b) noexcept : data_(b.data()), size_(b.size()) #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) @@ -266,7 +252,7 @@ public: #endif // ASIO_ENABLE_BUFFER_DEBUGGING /// Get a pointer to the beginning of the memory range. - const void* data() const ASIO_NOEXCEPT + const void* data() const noexcept { #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) if (size_ && debug_check_) @@ -276,13 +262,13 @@ public: } /// Get the size of the memory range. - std::size_t size() const ASIO_NOEXCEPT + std::size_t size() const noexcept { return size_; } /// Move the start of the buffer by the specified number of bytes. - const_buffer& operator+=(std::size_t n) ASIO_NOEXCEPT + const_buffer& operator+=(std::size_t n) noexcept { std::size_t offset = n < size_ ? n : size_; data_ = static_cast<const char*>(data_) + offset; @@ -314,7 +300,7 @@ public: typedef const const_buffer* const_iterator; /// Construct to represent a given memory range. - const_buffers_1(const void* data, std::size_t size) ASIO_NOEXCEPT + const_buffers_1(const void* data, std::size_t size) noexcept : const_buffer(data, size) { } @@ -328,19 +314,19 @@ public: #endif // ASIO_ENABLE_BUFFER_DEBUGGING /// Construct to represent a single non-modifiable buffer. - explicit const_buffers_1(const const_buffer& b) ASIO_NOEXCEPT + explicit const_buffers_1(const const_buffer& b) noexcept : const_buffer(b) { } /// Get a random-access iterator to the first element. - const_iterator begin() const ASIO_NOEXCEPT + const_iterator begin() const noexcept { return this; } /// Get a random-access iterator for one past the last element. - const_iterator end() const ASIO_NOEXCEPT + const_iterator end() const noexcept { return begin() + 1; } @@ -361,13 +347,13 @@ public: typedef const mutable_buffer* const_iterator; /// Get a random-access iterator to the first element. - const_iterator begin() const ASIO_NOEXCEPT + const_iterator begin() const noexcept { return &buf_; } /// Get a random-access iterator for one past the last element. - const_iterator end() const ASIO_NOEXCEPT + const_iterator end() const noexcept { return &buf_; } @@ -386,9 +372,9 @@ private: /// Get an iterator to the first element in a buffer sequence. template <typename MutableBuffer> inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b, - typename constraint< + constraint_t< is_convertible<const MutableBuffer*, const mutable_buffer*>::value - >::type = 0) ASIO_NOEXCEPT + > = 0) noexcept { return static_cast<const mutable_buffer*>(detail::addressof(b)); } @@ -396,22 +382,20 @@ inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b, /// Get an iterator to the first element in a buffer sequence. template <typename ConstBuffer> inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b, - typename constraint< + constraint_t< is_convertible<const ConstBuffer*, const const_buffer*>::value - >::type = 0) ASIO_NOEXCEPT + > = 0) noexcept { return static_cast<const const_buffer*>(detail::addressof(b)); } -#if defined(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, - typename constraint< + constraint_t< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value - >::type = 0) ASIO_NOEXCEPT -> decltype(c.begin()) + > = 0) noexcept -> decltype(c.begin()) { return c.begin(); } @@ -419,38 +403,14 @@ inline auto buffer_sequence_begin(C& c, /// Get an iterator to the first element in a buffer sequence. template <typename C> inline auto buffer_sequence_begin(const C& c, - typename constraint< - !is_convertible<const C*, const mutable_buffer*>::value - && !is_convertible<const C*, const const_buffer*>::value - >::type = 0) ASIO_NOEXCEPT -> decltype(c.begin()) -{ - return c.begin(); -} - -#else // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) - -template <typename C> -inline typename C::iterator buffer_sequence_begin(C& c, - typename constraint< - !is_convertible<const C*, const mutable_buffer*>::value - && !is_convertible<const C*, const const_buffer*>::value - >::type = 0) ASIO_NOEXCEPT -{ - return c.begin(); -} - -template <typename C> -inline typename C::const_iterator buffer_sequence_begin(const C& c, - typename constraint< + constraint_t< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value - >::type = 0) ASIO_NOEXCEPT + > = 0) noexcept -> decltype(c.begin()) { return c.begin(); } -#endif // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) - /*@}*/ /** @defgroup buffer_sequence_end asio::buffer_sequence_end @@ -463,9 +423,9 @@ inline typename C::const_iterator buffer_sequence_begin(const C& c, /// Get an iterator to one past the end element in a buffer sequence. template <typename MutableBuffer> inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b, - typename constraint< + constraint_t< is_convertible<const MutableBuffer*, const mutable_buffer*>::value - >::type = 0) ASIO_NOEXCEPT + > = 0) noexcept { return static_cast<const mutable_buffer*>(detail::addressof(b)) + 1; } @@ -473,22 +433,20 @@ inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b, /// Get an iterator to one past the end element in a buffer sequence. template <typename ConstBuffer> inline const const_buffer* buffer_sequence_end(const ConstBuffer& b, - typename constraint< + constraint_t< is_convertible<const ConstBuffer*, const const_buffer*>::value - >::type = 0) ASIO_NOEXCEPT + > = 0) noexcept { return static_cast<const const_buffer*>(detail::addressof(b)) + 1; } -#if defined(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, - typename constraint< + constraint_t< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value - >::type = 0) ASIO_NOEXCEPT -> decltype(c.end()) + > = 0) noexcept -> decltype(c.end()) { return c.end(); } @@ -496,38 +454,14 @@ inline auto buffer_sequence_end(C& c, /// Get an iterator to one past the end element in a buffer sequence. template <typename C> inline auto buffer_sequence_end(const C& c, - typename constraint< - !is_convertible<const C*, const mutable_buffer*>::value - && !is_convertible<const C*, const const_buffer*>::value - >::type = 0) ASIO_NOEXCEPT -> decltype(c.end()) -{ - return c.end(); -} - -#else // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) - -template <typename C> -inline typename C::iterator buffer_sequence_end(C& c, - typename constraint< - !is_convertible<const C*, const mutable_buffer*>::value - && !is_convertible<const C*, const const_buffer*>::value - >::type = 0) ASIO_NOEXCEPT -{ - return c.end(); -} - -template <typename C> -inline typename C::const_iterator buffer_sequence_end(const C& c, - typename constraint< + constraint_t< !is_convertible<const C*, const mutable_buffer*>::value && !is_convertible<const C*, const const_buffer*>::value - >::type = 0) ASIO_NOEXCEPT + > = 0) noexcept -> decltype(c.end()) { return c.end(); } -#endif // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION) - /*@}*/ namespace detail { @@ -539,25 +473,25 @@ struct multiple_buffers {}; // Helper trait to detect single buffers. template <typename BufferSequence> struct buffer_sequence_cardinality : - conditional< + conditional_t< is_same<BufferSequence, mutable_buffer>::value #if !defined(ASIO_NO_DEPRECATED) || is_same<BufferSequence, mutable_buffers_1>::value || is_same<BufferSequence, const_buffers_1>::value #endif // !defined(ASIO_NO_DEPRECATED) || is_same<BufferSequence, const_buffer>::value, - one_buffer, multiple_buffers>::type {}; + one_buffer, multiple_buffers> {}; template <typename Iterator> inline std::size_t buffer_size(one_buffer, - Iterator begin, Iterator) ASIO_NOEXCEPT + Iterator begin, Iterator) noexcept { return const_buffer(*begin).size(); } template <typename Iterator> inline std::size_t buffer_size(multiple_buffers, - Iterator begin, Iterator end) ASIO_NOEXCEPT + Iterator begin, Iterator end) noexcept { std::size_t total_buffer_size = 0; @@ -592,7 +526,7 @@ inline std::size_t buffer_size(multiple_buffers, * ConstBufferSequence or @c MutableBufferSequence type requirements. */ template <typename BufferSequence> -inline std::size_t buffer_size(const BufferSequence& b) ASIO_NOEXCEPT +inline std::size_t buffer_size(const BufferSequence& b) noexcept { return detail::buffer_size( detail::buffer_sequence_cardinality<BufferSequence>(), @@ -627,14 +561,14 @@ inline std::size_t buffer_size(const BufferSequence& b) ASIO_NOEXCEPT /// Cast a non-modifiable buffer to a specified pointer to POD type. template <typename PointerToPodType> -inline PointerToPodType buffer_cast(const mutable_buffer& b) ASIO_NOEXCEPT +inline PointerToPodType buffer_cast(const mutable_buffer& b) noexcept { 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) ASIO_NOEXCEPT +inline PointerToPodType buffer_cast(const const_buffer& b) noexcept { return static_cast<PointerToPodType>(b.data()); } @@ -648,7 +582,7 @@ inline PointerToPodType buffer_cast(const const_buffer& b) ASIO_NOEXCEPT * @relates mutable_buffer */ inline mutable_buffer operator+(const mutable_buffer& b, - std::size_t n) ASIO_NOEXCEPT + std::size_t n) noexcept { std::size_t offset = n < b.size() ? n : b.size(); char* new_data = static_cast<char*>(b.data()) + offset; @@ -665,7 +599,7 @@ inline mutable_buffer operator+(const mutable_buffer& b, * @relates mutable_buffer */ inline mutable_buffer operator+(std::size_t n, - const mutable_buffer& b) ASIO_NOEXCEPT + const mutable_buffer& b) noexcept { return b + n; } @@ -675,7 +609,7 @@ inline mutable_buffer operator+(std::size_t n, * @relates const_buffer */ inline const_buffer operator+(const const_buffer& b, - std::size_t n) ASIO_NOEXCEPT + std::size_t n) noexcept { std::size_t offset = n < b.size() ? n : b.size(); const char* new_data = static_cast<const char*>(b.data()) + offset; @@ -692,7 +626,7 @@ inline const_buffer operator+(const const_buffer& b, * @relates const_buffer */ inline const_buffer operator+(std::size_t n, - const const_buffer& b) ASIO_NOEXCEPT + const const_buffer& b) noexcept { return b + n; } @@ -891,6 +825,25 @@ private: * bufs2.push_back(asio::buffer(d2)); * bufs2.push_back(asio::buffer(d3)); * bytes_transferred = sock.send(bufs2); @endcode + * + * @par Buffer Literals + * + * The `_buf` literal suffix, defined in namespace + * <tt>asio::buffer_literals</tt>, may be used to create @c const_buffer + * objects from string, binary integer, and hexadecimal integer literals. + * For example: + * + * @code + * using namespace asio::buffer_literals; + * + * asio::const_buffer b1 = "hello"_buf; + * asio::const_buffer b2 = 0xdeadbeef_buf; + * asio::const_buffer b3 = 0x0123456789abcdef0123456789abcdef_buf; + * asio::const_buffer b4 = 0b1010101011001100_buf; @endcode + * + * Note that the memory associated with a buffer literal is valid for the + * lifetime of the program. This means that the buffer can be safely used with + * asynchronous operations. */ /*@{*/ @@ -906,8 +859,8 @@ private: /** * @returns <tt>mutable_buffer(b)</tt>. */ -inline ASIO_MUTABLE_BUFFER buffer( - const mutable_buffer& b) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + const mutable_buffer& b) noexcept { return ASIO_MUTABLE_BUFFER(b); } @@ -919,8 +872,9 @@ inline ASIO_MUTABLE_BUFFER buffer( * b.data(), * min(b.size(), max_size_in_bytes)); @endcode */ -inline ASIO_MUTABLE_BUFFER buffer(const mutable_buffer& b, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + const mutable_buffer& b, + std::size_t max_size_in_bytes) noexcept { return ASIO_MUTABLE_BUFFER( mutable_buffer(b.data(), @@ -936,8 +890,8 @@ inline ASIO_MUTABLE_BUFFER buffer(const mutable_buffer& b, /** * @returns <tt>const_buffer(b)</tt>. */ -inline ASIO_CONST_BUFFER buffer( - const const_buffer& b) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const const_buffer& b) noexcept { return ASIO_CONST_BUFFER(b); } @@ -949,8 +903,9 @@ inline ASIO_CONST_BUFFER buffer( * b.data(), * min(b.size(), max_size_in_bytes)); @endcode */ -inline ASIO_CONST_BUFFER buffer(const const_buffer& b, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const const_buffer& b, + std::size_t max_size_in_bytes) noexcept { return ASIO_CONST_BUFFER(b.data(), b.size() < max_size_in_bytes @@ -965,8 +920,8 @@ inline ASIO_CONST_BUFFER buffer(const const_buffer& b, /** * @returns <tt>mutable_buffer(data, size_in_bytes)</tt>. */ -inline ASIO_MUTABLE_BUFFER buffer(void* data, - std::size_t size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + void* data, std::size_t size_in_bytes) noexcept { return ASIO_MUTABLE_BUFFER(data, size_in_bytes); } @@ -975,8 +930,8 @@ inline ASIO_MUTABLE_BUFFER buffer(void* data, /** * @returns <tt>const_buffer(data, size_in_bytes)</tt>. */ -inline ASIO_CONST_BUFFER buffer(const void* data, - std::size_t size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const void* data, std::size_t size_in_bytes) noexcept { return ASIO_CONST_BUFFER(data, size_in_bytes); } @@ -989,7 +944,8 @@ inline ASIO_CONST_BUFFER buffer(const void* data, * N * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N]) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + PodType (&data)[N]) noexcept { return ASIO_MUTABLE_BUFFER(data, N * sizeof(PodType)); } @@ -1002,8 +958,9 @@ inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N]) ASIO_NOEXCEPT * min(N * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N], - std::size_t max_size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + PodType (&data)[N], + std::size_t max_size_in_bytes) noexcept { return ASIO_MUTABLE_BUFFER(data, N * sizeof(PodType) < max_size_in_bytes @@ -1018,8 +975,8 @@ inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N], * N * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_CONST_BUFFER buffer( - const PodType (&data)[N]) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const PodType (&data)[N]) noexcept { return ASIO_CONST_BUFFER(data, N * sizeof(PodType)); } @@ -1032,84 +989,15 @@ inline ASIO_CONST_BUFFER buffer( * min(N * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_CONST_BUFFER buffer(const PodType (&data)[N], - std::size_t max_size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const PodType (&data)[N], + std::size_t max_size_in_bytes) noexcept { return ASIO_CONST_BUFFER(data, N * sizeof(PodType) < max_size_in_bytes ? N * sizeof(PodType) : max_size_in_bytes); } -#if defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) - -// Borland C++ and Sun Studio think the overloads: -// -// unspecified buffer(boost::array<PodType, N>& array ...); -// -// and -// -// unspecified buffer(boost::array<const PodType, N>& array ...); -// -// are ambiguous. This will be worked around by using a buffer_types traits -// class that contains typedefs for the appropriate buffer and container -// classes, based on whether PodType is const or non-const. - -namespace detail { - -template <bool IsConst> -struct buffer_types_base; - -template <> -struct buffer_types_base<false> -{ - typedef mutable_buffer buffer_type; - typedef ASIO_MUTABLE_BUFFER container_type; -}; - -template <> -struct buffer_types_base<true> -{ - typedef const_buffer buffer_type; - typedef ASIO_CONST_BUFFER container_type; -}; - -template <typename PodType> -struct buffer_types - : public buffer_types_base<is_const<PodType>::value> -{ -}; - -} // namespace detail - -template <typename PodType, std::size_t N> -inline typename detail::buffer_types<PodType>::container_type -buffer(boost::array<PodType, N>& data) ASIO_NOEXCEPT -{ - typedef typename asio::detail::buffer_types<PodType>::buffer_type - buffer_type; - typedef typename asio::detail::buffer_types<PodType>::container_type - container_type; - return container_type( - buffer_type(data.c_array(), data.size() * sizeof(PodType))); -} - -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) ASIO_NOEXCEPT -{ - typedef typename asio::detail::buffer_types<PodType>::buffer_type - buffer_type; - typedef typename asio::detail::buffer_types<PodType>::container_type - container_type; - return container_type( - buffer_type(data.c_array(), - data.size() * sizeof(PodType) < max_size_in_bytes - ? data.size() * sizeof(PodType) : max_size_in_bytes)); -} - -#else // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) - /// Create a new modifiable buffer that represents the given POD array. /** * @returns A mutable_buffer value equivalent to: @@ -1118,8 +1006,8 @@ buffer(boost::array<PodType, N>& data, * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_MUTABLE_BUFFER buffer( - boost::array<PodType, N>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + boost::array<PodType, N>& data) noexcept { return ASIO_MUTABLE_BUFFER( data.c_array(), data.size() * sizeof(PodType)); @@ -1133,8 +1021,9 @@ inline ASIO_MUTABLE_BUFFER buffer( * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_MUTABLE_BUFFER buffer(boost::array<PodType, N>& data, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + boost::array<PodType, N>& data, + std::size_t max_size_in_bytes) noexcept { return ASIO_MUTABLE_BUFFER(data.c_array(), data.size() * sizeof(PodType) < max_size_in_bytes @@ -1149,8 +1038,8 @@ inline ASIO_MUTABLE_BUFFER buffer(boost::array<PodType, N>& data, * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_CONST_BUFFER buffer( - boost::array<const PodType, N>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + boost::array<const PodType, N>& data) noexcept { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); } @@ -1163,16 +1052,15 @@ inline ASIO_CONST_BUFFER buffer( * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_CONST_BUFFER buffer(boost::array<const PodType, N>& data, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + boost::array<const PodType, N>& data, + std::size_t max_size_in_bytes) noexcept { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType) < max_size_in_bytes ? data.size() * sizeof(PodType) : max_size_in_bytes); } -#endif // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND) - /// Create a new non-modifiable buffer that represents the given POD array. /** * @returns A const_buffer value equivalent to: @@ -1181,8 +1069,8 @@ inline ASIO_CONST_BUFFER buffer(boost::array<const PodType, N>& data, * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_CONST_BUFFER buffer( - const boost::array<PodType, N>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const boost::array<PodType, N>& data) noexcept { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); } @@ -1195,16 +1083,15 @@ inline ASIO_CONST_BUFFER buffer( * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_CONST_BUFFER buffer(const boost::array<PodType, N>& data, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const boost::array<PodType, N>& data, + std::size_t max_size_in_bytes) noexcept { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType) < max_size_in_bytes ? data.size() * sizeof(PodType) : max_size_in_bytes); } -#if defined(ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION) - /// Create a new modifiable buffer that represents the given POD array. /** * @returns A mutable_buffer value equivalent to: @@ -1213,8 +1100,8 @@ inline ASIO_CONST_BUFFER buffer(const boost::array<PodType, N>& data, * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_MUTABLE_BUFFER buffer( - std::array<PodType, N>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + std::array<PodType, N>& data) noexcept { return ASIO_MUTABLE_BUFFER(data.data(), data.size() * sizeof(PodType)); } @@ -1227,8 +1114,9 @@ inline ASIO_MUTABLE_BUFFER buffer( * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_MUTABLE_BUFFER buffer(std::array<PodType, N>& data, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + std::array<PodType, N>& data, + std::size_t max_size_in_bytes) noexcept { return ASIO_MUTABLE_BUFFER(data.data(), data.size() * sizeof(PodType) < max_size_in_bytes @@ -1243,8 +1131,8 @@ inline ASIO_MUTABLE_BUFFER buffer(std::array<PodType, N>& data, * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_CONST_BUFFER buffer( - std::array<const PodType, N>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + std::array<const PodType, N>& data) noexcept { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); } @@ -1257,8 +1145,9 @@ inline ASIO_CONST_BUFFER buffer( * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_CONST_BUFFER buffer(std::array<const PodType, N>& data, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + std::array<const PodType, N>& data, + std::size_t max_size_in_bytes) noexcept { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType) < max_size_in_bytes @@ -1273,8 +1162,8 @@ inline ASIO_CONST_BUFFER buffer(std::array<const PodType, N>& data, * data.size() * sizeof(PodType)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_CONST_BUFFER buffer( - const std::array<PodType, N>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const std::array<PodType, N>& data) noexcept { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType)); } @@ -1287,16 +1176,15 @@ inline ASIO_CONST_BUFFER buffer( * min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode */ template <typename PodType, std::size_t N> -inline ASIO_CONST_BUFFER buffer(const std::array<PodType, N>& data, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const std::array<PodType, N>& data, + std::size_t max_size_in_bytes) noexcept { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType) < max_size_in_bytes ? data.size() * sizeof(PodType) : max_size_in_bytes); } -#endif // defined(ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION) - /// Create a new modifiable buffer that represents the given POD vector. /** * @returns A mutable_buffer value equivalent to: @@ -1308,8 +1196,8 @@ inline ASIO_CONST_BUFFER buffer(const std::array<PodType, N>& data, * invalidate iterators. */ template <typename PodType, typename Allocator> -inline ASIO_MUTABLE_BUFFER buffer( - std::vector<PodType, Allocator>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + std::vector<PodType, Allocator>& data) noexcept { return ASIO_MUTABLE_BUFFER( data.size() ? &data[0] : 0, data.size() * sizeof(PodType) @@ -1332,8 +1220,9 @@ inline ASIO_MUTABLE_BUFFER buffer( * invalidate iterators. */ template <typename PodType, typename Allocator> -inline ASIO_MUTABLE_BUFFER buffer(std::vector<PodType, Allocator>& data, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + std::vector<PodType, Allocator>& data, + std::size_t max_size_in_bytes) noexcept { return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) < max_size_in_bytes @@ -1357,8 +1246,8 @@ inline ASIO_MUTABLE_BUFFER buffer(std::vector<PodType, Allocator>& data, * invalidate iterators. */ template <typename PodType, typename Allocator> -inline ASIO_CONST_BUFFER buffer( - const std::vector<PodType, Allocator>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const std::vector<PodType, Allocator>& data) noexcept { return ASIO_CONST_BUFFER( data.size() ? &data[0] : 0, data.size() * sizeof(PodType) @@ -1381,9 +1270,9 @@ inline ASIO_CONST_BUFFER buffer( * invalidate iterators. */ template <typename PodType, typename Allocator> -inline ASIO_CONST_BUFFER buffer( +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( const std::vector<PodType, Allocator>& data, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT + std::size_t max_size_in_bytes) noexcept { return ASIO_CONST_BUFFER(data.size() ? &data[0] : 0, data.size() * sizeof(PodType) < max_size_in_bytes @@ -1405,8 +1294,8 @@ inline ASIO_CONST_BUFFER buffer( * given string object. */ template <typename Elem, typename Traits, typename Allocator> -inline ASIO_MUTABLE_BUFFER buffer( - std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + std::basic_string<Elem, Traits, Allocator>& data) noexcept { return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0, data.size() * sizeof(Elem) @@ -1429,9 +1318,9 @@ inline ASIO_MUTABLE_BUFFER buffer( * given string object. */ template <typename Elem, typename Traits, typename Allocator> -inline ASIO_MUTABLE_BUFFER buffer( +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( std::basic_string<Elem, Traits, Allocator>& data, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT + std::size_t max_size_in_bytes) noexcept { return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0, data.size() * sizeof(Elem) < max_size_in_bytes @@ -1452,8 +1341,8 @@ inline ASIO_MUTABLE_BUFFER buffer( * given string object. */ template <typename Elem, typename Traits, typename Allocator> -inline ASIO_CONST_BUFFER buffer( - const std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const std::basic_string<Elem, Traits, Allocator>& data) noexcept { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(Elem) #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) @@ -1475,9 +1364,9 @@ inline ASIO_CONST_BUFFER buffer( * given string object. */ template <typename Elem, typename Traits, typename Allocator> -inline ASIO_CONST_BUFFER buffer( +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( const std::basic_string<Elem, Traits, Allocator>& data, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT + std::size_t max_size_in_bytes) noexcept { return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(Elem) < max_size_in_bytes @@ -1493,14 +1382,14 @@ inline ASIO_CONST_BUFFER buffer( #if defined(ASIO_HAS_STRING_VIEW) \ || defined(GENERATING_DOCUMENTATION) -/// Create a new modifiable buffer that represents the given string_view. +/// Create a new non-modifiable buffer that represents the given string_view. /** * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0, * data.size() * sizeof(Elem))</tt>. */ template <typename Elem, typename Traits> -inline ASIO_CONST_BUFFER buffer( - basic_string_view<Elem, Traits> data) ASIO_NOEXCEPT +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + basic_string_view<Elem, Traits> data) noexcept { return ASIO_CONST_BUFFER(data.size() ? &data[0] : 0, data.size() * sizeof(Elem) @@ -1520,9 +1409,9 @@ inline ASIO_CONST_BUFFER buffer( * min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode */ template <typename Elem, typename Traits> -inline ASIO_CONST_BUFFER buffer( +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( basic_string_view<Elem, Traits> data, - std::size_t max_size_in_bytes) ASIO_NOEXCEPT + std::size_t max_size_in_bytes) noexcept { return ASIO_CONST_BUFFER(data.size() ? &data[0] : 0, data.size() * sizeof(Elem) < max_size_in_bytes @@ -1538,6 +1427,215 @@ inline ASIO_CONST_BUFFER buffer( #endif // defined(ASIO_HAS_STRING_VIEW) // || defined(GENERATING_DOCUMENTATION) +/// Create a new modifiable buffer from a contiguous container. +/** + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( + * data.size() ? &data[0] : 0, + * data.size() * sizeof(typename T::value_type)); @endcode + */ +template <typename T> +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + T& data, + constraint_t< + is_contiguous_iterator<typename T::iterator>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, const_buffer>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, mutable_buffer>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_const< + remove_reference_t< + typename std::iterator_traits<typename T::iterator>::reference + > + >::value, + defaulted_constraint + > = defaulted_constraint()) noexcept +{ + return ASIO_MUTABLE_BUFFER( + data.size() ? detail::to_address(data.begin()) : 0, + data.size() * sizeof(typename T::value_type)); +} + +/// Create a new modifiable buffer from a contiguous container. +/** + * @returns A mutable_buffer value equivalent to: + * @code mutable_buffer( + * data.size() ? &data[0] : 0, + * min( + * data.size() * sizeof(typename T::value_type), + * max_size_in_bytes)); @endcode + */ +template <typename T> +ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer( + T& data, std::size_t max_size_in_bytes, + constraint_t< + is_contiguous_iterator<typename T::iterator>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, const_buffer>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, mutable_buffer>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_const< + remove_reference_t< + typename std::iterator_traits<typename T::iterator>::reference + > + >::value, + defaulted_constraint + > = defaulted_constraint()) noexcept +{ + return ASIO_MUTABLE_BUFFER( + data.size() ? detail::to_address(data.begin()) : 0, + data.size() * sizeof(typename T::value_type) < max_size_in_bytes + ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes); +} + +/// Create a new non-modifiable buffer from a contiguous container. +/** + * @returns A const_buffer value equivalent to: + * @code const_buffer( + * data.size() ? &data[0] : 0, + * data.size() * sizeof(typename T::value_type)); @endcode + */ +template <typename T> +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + T& data, + constraint_t< + is_contiguous_iterator<typename T::iterator>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, const_buffer>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, mutable_buffer>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + is_const< + remove_reference_t< + typename std::iterator_traits<typename T::iterator>::reference + > + >::value, + defaulted_constraint + > = defaulted_constraint()) noexcept +{ + return ASIO_CONST_BUFFER( + data.size() ? detail::to_address(data.begin()) : 0, + data.size() * sizeof(typename T::value_type)); +} + +/// Create a new non-modifiable buffer from a contiguous container. +/** + * @returns A const_buffer value equivalent to: + * @code const_buffer( + * data.size() ? &data[0] : 0, + * min( + * data.size() * sizeof(typename T::value_type), + * max_size_in_bytes)); @endcode + */ +template <typename T> +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + T& data, std::size_t max_size_in_bytes, + constraint_t< + is_contiguous_iterator<typename T::iterator>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, const_buffer>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, mutable_buffer>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + is_const< + remove_reference_t< + typename std::iterator_traits<typename T::iterator>::reference + > + >::value, + defaulted_constraint + > = defaulted_constraint()) noexcept +{ + return ASIO_CONST_BUFFER( + data.size() ? detail::to_address(data.begin()) : 0, + data.size() * sizeof(typename T::value_type) < max_size_in_bytes + ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes); +} + +/// Create a new non-modifiable buffer from a contiguous container. +/** + * @returns A const_buffer value equivalent to: + * @code const_buffer( + * data.size() ? &data[0] : 0, + * data.size() * sizeof(typename T::value_type)); @endcode + */ +template <typename T> +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const T& data, + constraint_t< + is_contiguous_iterator<typename T::const_iterator>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, const_buffer>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, mutable_buffer>::value, + defaulted_constraint + > = defaulted_constraint()) noexcept +{ + return ASIO_CONST_BUFFER( + data.size() ? detail::to_address(data.begin()) : 0, + data.size() * sizeof(typename T::value_type)); +} + +/// Create a new non-modifiable buffer from a contiguous container. +/** + * @returns A const_buffer value equivalent to: + * @code const_buffer( + * data.size() ? &data[0] : 0, + * min( + * data.size() * sizeof(typename T::value_type), + * max_size_in_bytes)); @endcode + */ +template <typename T> +ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer( + const T& data, std::size_t max_size_in_bytes, + constraint_t< + is_contiguous_iterator<typename T::const_iterator>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, const_buffer>::value, + defaulted_constraint + > = defaulted_constraint(), + constraint_t< + !is_convertible<T, mutable_buffer>::value, + defaulted_constraint + > = defaulted_constraint()) noexcept +{ + return ASIO_CONST_BUFFER( + data.size() ? detail::to_address(data.begin()) : 0, + data.size() * sizeof(typename T::value_type) < max_size_in_bytes + ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes); +} + /*@}*/ /// Adapt a basic_string to the DynamicBuffer requirements. @@ -1570,7 +1668,7 @@ public: */ explicit dynamic_string_buffer(std::basic_string<Elem, Traits, Allocator>& s, std::size_t maximum_size = - (std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT + (std::numeric_limits<std::size_t>::max)()) noexcept : string_(s), #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) size_((std::numeric_limits<std::size_t>::max)()), @@ -1580,7 +1678,7 @@ public: } /// @b DynamicBuffer_v2: Copy construct a dynamic buffer. - dynamic_string_buffer(const dynamic_string_buffer& other) ASIO_NOEXCEPT + dynamic_string_buffer(const dynamic_string_buffer& other) noexcept : string_(other.string_), #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) size_(other.size_), @@ -1589,9 +1687,8 @@ public: { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move construct a dynamic buffer. - dynamic_string_buffer(dynamic_string_buffer&& other) ASIO_NOEXCEPT + dynamic_string_buffer(dynamic_string_buffer&& other) noexcept : string_(other.string_), #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) size_(other.size_), @@ -1599,7 +1696,6 @@ public: max_size_(other.max_size_) { } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// @b DynamicBuffer_v1: Get the size of the input sequence. /// @b DynamicBuffer_v2: Get the current size of the underlying memory. @@ -1608,7 +1704,7 @@ public: * @b DynamicBuffer_v2: The current size of the underlying string if less than * max_size(). Otherwise returns max_size(). */ - std::size_t size() const ASIO_NOEXCEPT + std::size_t size() const noexcept { #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) if (size_ != (std::numeric_limits<std::size_t>::max)()) @@ -1621,7 +1717,7 @@ public: /** * @returns The allowed maximum size of the underlying memory. */ - std::size_t max_size() const ASIO_NOEXCEPT + std::size_t max_size() const noexcept { return max_size_; } @@ -1632,7 +1728,7 @@ public: * @returns The current capacity of the underlying string if less than * max_size(). Otherwise returns max_size(). */ - std::size_t capacity() const ASIO_NOEXCEPT + std::size_t capacity() const noexcept { return (std::min)(string_.capacity(), max_size()); } @@ -1648,7 +1744,7 @@ public: * @note The returned object is invalidated by any @c dynamic_string_buffer * or @c basic_string member function that resizes or erases the string. */ - const_buffers_type data() const ASIO_NOEXCEPT + const_buffers_type data() const noexcept { return const_buffers_type(asio::buffer(string_, size_)); } @@ -1669,7 +1765,7 @@ public: * @note The returned object is invalidated by any @c dynamic_string_buffer * or @c basic_string member function that resizes or erases the string. */ - mutable_buffers_type data(std::size_t pos, std::size_t n) ASIO_NOEXCEPT + mutable_buffers_type data(std::size_t pos, std::size_t n) noexcept { return mutable_buffers_type(asio::buffer( asio::buffer(string_, max_size_) + pos, n)); @@ -1688,7 +1784,7 @@ public: * or @c basic_string member function that resizes or erases the string. */ const_buffers_type data(std::size_t pos, - std::size_t n) const ASIO_NOEXCEPT + std::size_t n) const noexcept { return const_buffers_type(asio::buffer( asio::buffer(string_, max_size_) + pos, n)); @@ -1838,7 +1934,7 @@ public: */ explicit dynamic_vector_buffer(std::vector<Elem, Allocator>& v, std::size_t maximum_size = - (std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT + (std::numeric_limits<std::size_t>::max)()) noexcept : vector_(v), #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) size_((std::numeric_limits<std::size_t>::max)()), @@ -1848,7 +1944,7 @@ public: } /// @b DynamicBuffer_v2: Copy construct a dynamic buffer. - dynamic_vector_buffer(const dynamic_vector_buffer& other) ASIO_NOEXCEPT + dynamic_vector_buffer(const dynamic_vector_buffer& other) noexcept : vector_(other.vector_), #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) size_(other.size_), @@ -1857,9 +1953,8 @@ public: { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move construct a dynamic buffer. - dynamic_vector_buffer(dynamic_vector_buffer&& other) ASIO_NOEXCEPT + dynamic_vector_buffer(dynamic_vector_buffer&& other) noexcept : vector_(other.vector_), #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) size_(other.size_), @@ -1867,7 +1962,6 @@ public: max_size_(other.max_size_) { } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// @b DynamicBuffer_v1: Get the size of the input sequence. /// @b DynamicBuffer_v2: Get the current size of the underlying memory. @@ -1876,7 +1970,7 @@ public: * @b DynamicBuffer_v2: The current size of the underlying vector if less than * max_size(). Otherwise returns max_size(). */ - std::size_t size() const ASIO_NOEXCEPT + std::size_t size() const noexcept { #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) if (size_ != (std::numeric_limits<std::size_t>::max)()) @@ -1891,7 +1985,7 @@ public: * of the input sequence and output sequence. @b DynamicBuffer_v2: The allowed * maximum size of the underlying memory. */ - std::size_t max_size() const ASIO_NOEXCEPT + std::size_t max_size() const noexcept { return max_size_; } @@ -1904,7 +1998,7 @@ public: * The current capacity of the underlying vector if less than max_size(). * Otherwise returns max_size(). */ - std::size_t capacity() const ASIO_NOEXCEPT + std::size_t capacity() const noexcept { return (std::min)(vector_.capacity(), max_size()); } @@ -1921,7 +2015,7 @@ public: * or @c vector member function that modifies the input sequence or output * sequence. */ - const_buffers_type data() const ASIO_NOEXCEPT + const_buffers_type data() const noexcept { return const_buffers_type(asio::buffer(vector_, size_)); } @@ -1942,7 +2036,7 @@ public: * @note The returned object is invalidated by any @c dynamic_vector_buffer * or @c vector member function that resizes or erases the vector. */ - mutable_buffers_type data(std::size_t pos, std::size_t n) ASIO_NOEXCEPT + mutable_buffers_type data(std::size_t pos, std::size_t n) noexcept { return mutable_buffers_type(asio::buffer( asio::buffer(vector_, max_size_) + pos, n)); @@ -1961,7 +2055,7 @@ public: * or @c vector member function that resizes or erases the vector. */ const_buffers_type data(std::size_t pos, - std::size_t n) const ASIO_NOEXCEPT + std::size_t n) const noexcept { return const_buffers_type(asio::buffer( asio::buffer(vector_, max_size_) + pos, n)); @@ -2096,8 +2190,9 @@ private: * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data)</tt>. */ template <typename Elem, typename Traits, typename Allocator> -inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( - std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline +dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( + std::basic_string<Elem, Traits, Allocator>& data) noexcept { return dynamic_string_buffer<Elem, Traits, Allocator>(data); } @@ -2108,9 +2203,10 @@ inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( * max_size)</tt>. */ template <typename Elem, typename Traits, typename Allocator> -inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( +ASIO_NODISCARD inline +dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( std::basic_string<Elem, Traits, Allocator>& data, - std::size_t max_size) ASIO_NOEXCEPT + std::size_t max_size) noexcept { return dynamic_string_buffer<Elem, Traits, Allocator>(data, max_size); } @@ -2120,8 +2216,9 @@ inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer( * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data)</tt>. */ template <typename Elem, typename Allocator> -inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer( - std::vector<Elem, Allocator>& data) ASIO_NOEXCEPT +ASIO_NODISCARD inline +dynamic_vector_buffer<Elem, Allocator> dynamic_buffer( + std::vector<Elem, Allocator>& data) noexcept { return dynamic_vector_buffer<Elem, Allocator>(data); } @@ -2131,9 +2228,10 @@ inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer( * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data, max_size)</tt>. */ template <typename Elem, typename Allocator> -inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer( +ASIO_NODISCARD inline +dynamic_vector_buffer<Elem, Allocator> dynamic_buffer( std::vector<Elem, Allocator>& data, - std::size_t max_size) ASIO_NOEXCEPT + std::size_t max_size) noexcept { return dynamic_vector_buffer<Elem, Allocator>(data, max_size); } @@ -2185,7 +2283,7 @@ inline std::size_t buffer_copy_1(const mutable_buffer& target, template <typename TargetIterator, typename SourceIterator> inline std::size_t buffer_copy(one_buffer, one_buffer, TargetIterator target_begin, TargetIterator, - SourceIterator source_begin, SourceIterator) ASIO_NOEXCEPT + SourceIterator source_begin, SourceIterator) noexcept { return (buffer_copy_1)(*target_begin, *source_begin); } @@ -2194,7 +2292,7 @@ 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) ASIO_NOEXCEPT + std::size_t max_bytes_to_copy) noexcept { return (buffer_copy_1)(*target_begin, asio::buffer(*source_begin, max_bytes_to_copy)); @@ -2205,7 +2303,7 @@ 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)()) ASIO_NOEXCEPT + = (std::numeric_limits<std::size_t>::max)()) noexcept { std::size_t total_bytes_copied = 0; SourceIterator source_iter = source_begin; @@ -2228,7 +2326,7 @@ 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)()) ASIO_NOEXCEPT + = (std::numeric_limits<std::size_t>::max)()) noexcept { std::size_t total_bytes_copied = 0; TargetIterator target_iter = target_begin; @@ -2249,7 +2347,7 @@ std::size_t buffer_copy(multiple_buffers, one_buffer, 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) ASIO_NOEXCEPT + SourceIterator source_begin, SourceIterator source_end) noexcept { std::size_t total_bytes_copied = 0; @@ -2294,7 +2392,7 @@ 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) ASIO_NOEXCEPT + std::size_t max_bytes_to_copy) noexcept { std::size_t total_bytes_copied = 0; @@ -2361,7 +2459,7 @@ std::size_t buffer_copy(multiple_buffers, multiple_buffers, */ template <typename MutableBufferSequence, typename ConstBufferSequence> inline std::size_t buffer_copy(const MutableBufferSequence& target, - const ConstBufferSequence& source) ASIO_NOEXCEPT + const ConstBufferSequence& source) noexcept { return detail::buffer_copy( detail::buffer_sequence_cardinality<MutableBufferSequence>(), @@ -2399,7 +2497,7 @@ inline std::size_t buffer_copy(const MutableBufferSequence& target, template <typename MutableBufferSequence, typename ConstBufferSequence> inline std::size_t buffer_copy(const MutableBufferSequence& target, const ConstBufferSequence& source, - std::size_t max_bytes_to_copy) ASIO_NOEXCEPT + std::size_t max_bytes_to_copy) noexcept { return detail::buffer_copy( detail::buffer_sequence_cardinality<MutableBufferSequence>(), @@ -2489,6 +2587,163 @@ struct is_dynamic_buffer { }; +namespace buffer_literals { +namespace detail { + +template <char... Chars> +struct chars {}; + +template <unsigned char... Bytes> +struct bytes {}; + +// Literal processor that converts binary literals to an array of bytes. + +template <typename Bytes, char... Chars> +struct bin_literal; + +template <unsigned char... Bytes> +struct bin_literal<bytes<Bytes...>> +{ + static const std::size_t size = sizeof...(Bytes); + static const unsigned char data[sizeof...(Bytes)]; +}; + +template <unsigned char... Bytes> +const unsigned char bin_literal<bytes<Bytes...>>::data[sizeof...(Bytes)] + = { Bytes... }; + +template <unsigned char... Bytes, char Bit7, char Bit6, char Bit5, + char Bit4, char Bit3, char Bit2, char Bit1, char Bit0, char... Chars> +struct bin_literal<bytes<Bytes...>, Bit7, Bit6, + Bit5, Bit4, Bit3, Bit2, Bit1, Bit0, Chars...> : + bin_literal< + bytes<Bytes..., + static_cast<unsigned char>( + (Bit7 == '1' ? 0x80 : 0) | + (Bit6 == '1' ? 0x40 : 0) | + (Bit5 == '1' ? 0x20 : 0) | + (Bit4 == '1' ? 0x10 : 0) | + (Bit3 == '1' ? 0x08 : 0) | + (Bit2 == '1' ? 0x04 : 0) | + (Bit1 == '1' ? 0x02 : 0) | + (Bit0 == '1' ? 0x01 : 0)) + >, Chars...> {}; + +template <unsigned char... Bytes, char... Chars> +struct bin_literal<bytes<Bytes...>, Chars...> +{ + static_assert(sizeof...(Chars) == 0, + "number of digits in a binary buffer literal must be a multiple of 8"); + + static const std::size_t size = 0; + static const unsigned char data[1]; +}; + +template <unsigned char... Bytes, char... Chars> +const unsigned char bin_literal<bytes<Bytes...>, Chars...>::data[1] = {}; + +// Literal processor that converts hexadecimal literals to an array of bytes. + +template <typename Bytes, char... Chars> +struct hex_literal; + +template <unsigned char... Bytes> +struct hex_literal<bytes<Bytes...>> +{ + static const std::size_t size = sizeof...(Bytes); + static const unsigned char data[sizeof...(Bytes)]; +}; + +template <unsigned char... Bytes> +const unsigned char hex_literal<bytes<Bytes...>>::data[sizeof...(Bytes)] + = { Bytes... }; + +template <unsigned char... Bytes, char Hi, char Lo, char... Chars> +struct hex_literal<bytes<Bytes...>, Hi, Lo, Chars...> : + hex_literal< + bytes<Bytes..., + static_cast<unsigned char>( + Lo >= 'A' && Lo <= 'F' ? Lo - 'A' + 10 : + (Lo >= 'a' && Lo <= 'f' ? Lo - 'a' + 10 : Lo - '0')) | + ((static_cast<unsigned char>( + Hi >= 'A' && Hi <= 'F' ? Hi - 'A' + 10 : + (Hi >= 'a' && Hi <= 'f' ? Hi - 'a' + 10 : Hi - '0'))) << 4) + >, Chars...> {}; + +template <unsigned char... Bytes, char Char> +struct hex_literal<bytes<Bytes...>, Char> +{ + static_assert(!Char, + "a hexadecimal buffer literal must have an even number of digits"); + + static const std::size_t size = 0; + static const unsigned char data[1]; +}; + +template <unsigned char... Bytes, char Char> +const unsigned char hex_literal<bytes<Bytes...>, Char>::data[1] = {}; + +// Helper template that removes digit separators and then passes the cleaned +// variadic pack of characters to the literal processor. + +template <template <typename, char...> class Literal, + typename Clean, char... Raw> +struct remove_separators; + +template <template <typename, char...> class Literal, + char... Clean, char... Raw> +struct remove_separators<Literal, chars<Clean...>, '\'', Raw...> : + remove_separators<Literal, chars<Clean...>, Raw...> {}; + +template <template <typename, char...> class Literal, + char... Clean, char C, char... Raw> +struct remove_separators<Literal, chars<Clean...>, C, Raw...> : + remove_separators<Literal, chars<Clean..., C>, Raw...> {}; + +template <template <typename, char...> class Literal, char... Clean> +struct remove_separators<Literal, chars<Clean...>> : + Literal<bytes<>, Clean...> {}; + +// Helper template to determine the literal type based on the prefix. + +template <char... Chars> +struct literal; + +template <char... Chars> +struct literal<'0', 'b', Chars...> : + remove_separators<bin_literal, chars<>, Chars...>{}; + +template <char... Chars> +struct literal<'0', 'B', Chars...> : + remove_separators<bin_literal, chars<>, Chars...>{}; + +template <char... Chars> +struct literal<'0', 'x', Chars...> : + remove_separators<hex_literal, chars<>, Chars...>{}; + +template <char... Chars> +struct literal<'0', 'X', Chars...> : + remove_separators<hex_literal, chars<>, Chars...>{}; + +} // namespace detail + +/// Literal operator for creating const_buffer objects from string literals. +inline ASIO_CONST_BUFFER operator ""_buf(const char* data, std::size_t n) +{ + return ASIO_CONST_BUFFER(data, n); +} + +/// Literal operator for creating const_buffer objects from unbounded binary or +/// hexadecimal integer literals. +template <char... Chars> +inline ASIO_CONST_BUFFER operator ""_buf() +{ + return ASIO_CONST_BUFFER( + +detail::literal<Chars...>::data, + detail::literal<Chars...>::size); +} + +} // namespace buffer_literals } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/buffer_registration.hpp b/3rdparty/asio/include/asio/buffer_registration.hpp new file mode 100644 index 00000000000..39897ba2450 --- /dev/null +++ b/3rdparty/asio/include/asio/buffer_registration.hpp @@ -0,0 +1,318 @@ +// +// buffer_registration.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_BUFFER_REGISTRATION_HPP +#define ASIO_BUFFER_REGISTRATION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <iterator> +#include <utility> +#include <vector> +#include "asio/detail/memory.hpp" +#include "asio/execution/context.hpp" +#include "asio/execution/executor.hpp" +#include "asio/execution_context.hpp" +#include "asio/is_executor.hpp" +#include "asio/query.hpp" +#include "asio/registered_buffer.hpp" + +#if defined(ASIO_HAS_IO_URING) +# include "asio/detail/scheduler.hpp" +# include "asio/detail/io_uring_service.hpp" +#endif // defined(ASIO_HAS_IO_URING) + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class buffer_registration_base +{ +protected: + static mutable_registered_buffer make_buffer(const mutable_buffer& b, + const void* scope, int index) noexcept + { + return mutable_registered_buffer(b, registered_buffer_id(scope, index)); + } +}; + +} // namespace detail + +/// Automatically registers and unregistered buffers with an execution context. +/** + * For portability, applications should assume that only one registration is + * permitted per execution context. + */ +template <typename MutableBufferSequence, + typename Allocator = std::allocator<void>> +class buffer_registration + : detail::buffer_registration_base +{ +public: + /// The allocator type used for allocating storage for the buffers container. + typedef Allocator allocator_type; + +#if defined(GENERATING_DOCUMENTATION) + /// The type of an iterator over the registered buffers. + typedef unspecified iterator; + + /// The type of a const iterator over the registered buffers. + typedef unspecified const_iterator; +#else // defined(GENERATING_DOCUMENTATION) + typedef std::vector<mutable_registered_buffer>::const_iterator iterator; + typedef std::vector<mutable_registered_buffer>::const_iterator const_iterator; +#endif // defined(GENERATING_DOCUMENTATION) + + /// Register buffers with an executor's execution context. + template <typename Executor> + buffer_registration(const Executor& ex, + const MutableBufferSequence& buffer_sequence, + const allocator_type& alloc = allocator_type(), + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + > = 0) + : buffer_sequence_(buffer_sequence), + buffers_( + ASIO_REBIND_ALLOC(allocator_type, + mutable_registered_buffer)(alloc)) + { + init_buffers(buffer_registration::get_context(ex), + asio::buffer_sequence_begin(buffer_sequence_), + asio::buffer_sequence_end(buffer_sequence_)); + } + + /// Register buffers with an execution context. + template <typename ExecutionContext> + buffer_registration(ExecutionContext& ctx, + const MutableBufferSequence& buffer_sequence, + const allocator_type& alloc = allocator_type(), + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) + : buffer_sequence_(buffer_sequence), + buffers_( + ASIO_REBIND_ALLOC(allocator_type, + mutable_registered_buffer)(alloc)) + { + init_buffers(ctx, + asio::buffer_sequence_begin(buffer_sequence_), + asio::buffer_sequence_end(buffer_sequence_)); + } + + /// Move constructor. + buffer_registration(buffer_registration&& other) noexcept + : buffer_sequence_(std::move(other.buffer_sequence_)), + buffers_(std::move(other.buffers_)) + { +#if defined(ASIO_HAS_IO_URING) + service_ = other.service_; + other.service_ = 0; +#endif // defined(ASIO_HAS_IO_URING) + } + + /// Unregisters the buffers. + ~buffer_registration() + { +#if defined(ASIO_HAS_IO_URING) + if (service_) + service_->unregister_buffers(); +#endif // defined(ASIO_HAS_IO_URING) + } + + /// Move assignment. + buffer_registration& operator=(buffer_registration&& other) noexcept + { + if (this != &other) + { + buffer_sequence_ = std::move(other.buffer_sequence_); + buffers_ = std::move(other.buffers_); +#if defined(ASIO_HAS_IO_URING) + if (service_) + service_->unregister_buffers(); + service_ = other.service_; + other.service_ = 0; +#endif // defined(ASIO_HAS_IO_URING) + } + return *this; + } + + /// Get the number of registered buffers. + std::size_t size() const noexcept + { + return buffers_.size(); + } + + /// Get the begin iterator for the sequence of registered buffers. + const_iterator begin() const noexcept + { + return buffers_.begin(); + } + + /// Get the begin iterator for the sequence of registered buffers. + const_iterator cbegin() const noexcept + { + return buffers_.cbegin(); + } + + /// Get the end iterator for the sequence of registered buffers. + const_iterator end() const noexcept + { + return buffers_.end(); + } + + /// Get the end iterator for the sequence of registered buffers. + const_iterator cend() const noexcept + { + return buffers_.cend(); + } + + /// Get the buffer at the specified index. + const mutable_registered_buffer& operator[](std::size_t i) noexcept + { + return buffers_[i]; + } + + /// Get the buffer at the specified index. + const mutable_registered_buffer& at(std::size_t i) noexcept + { + return buffers_.at(i); + } + +private: + // Disallow copying and assignment. + buffer_registration(const buffer_registration&) = delete; + buffer_registration& operator=(const buffer_registration&) = delete; + + // Helper function to get an executor's context. + template <typename T> + static execution_context& get_context(const T& t, + enable_if_t<execution::is_executor<T>::value>* = 0) + { + return asio::query(t, execution::context); + } + + // Helper function to get an executor's context. + template <typename T> + static execution_context& get_context(const T& t, + enable_if_t<!execution::is_executor<T>::value>* = 0) + { + return t.context(); + } + + // Helper function to initialise the container of buffers. + template <typename Iterator> + void init_buffers(execution_context& ctx, Iterator begin, Iterator end) + { + std::size_t n = std::distance(begin, end); + buffers_.resize(n); + +#if defined(ASIO_HAS_IO_URING) + service_ = &use_service<detail::io_uring_service>(ctx); + std::vector<iovec, + ASIO_REBIND_ALLOC(allocator_type, iovec)> iovecs(n, + ASIO_REBIND_ALLOC(allocator_type, iovec)( + buffers_.get_allocator())); +#endif // defined(ASIO_HAS_IO_URING) + + Iterator iter = begin; + for (int index = 0; iter != end; ++index, ++iter) + { + mutable_buffer b(*iter); + std::size_t i = static_cast<std::size_t>(index); + buffers_[i] = this->make_buffer(b, &ctx, index); + +#if defined(ASIO_HAS_IO_URING) + iovecs[i].iov_base = buffers_[i].data(); + iovecs[i].iov_len = buffers_[i].size(); +#endif // defined(ASIO_HAS_IO_URING) + } + +#if defined(ASIO_HAS_IO_URING) + if (n > 0) + { + service_->register_buffers(&iovecs[0], + static_cast<unsigned>(iovecs.size())); + } +#endif // defined(ASIO_HAS_IO_URING) + } + + MutableBufferSequence buffer_sequence_; + std::vector<mutable_registered_buffer, + ASIO_REBIND_ALLOC(allocator_type, + mutable_registered_buffer)> buffers_; +#if defined(ASIO_HAS_IO_URING) + detail::io_uring_service* service_; +#endif // defined(ASIO_HAS_IO_URING) +}; + +/// Register buffers with an execution context. +template <typename Executor, typename MutableBufferSequence> +ASIO_NODISCARD inline +buffer_registration<MutableBufferSequence> +register_buffers(const Executor& ex, + const MutableBufferSequence& buffer_sequence, + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + > = 0) +{ + return buffer_registration<MutableBufferSequence>(ex, buffer_sequence); +} + +/// Register buffers with an execution context. +template <typename Executor, typename MutableBufferSequence, typename Allocator> +ASIO_NODISCARD inline +buffer_registration<MutableBufferSequence, Allocator> +register_buffers(const Executor& ex, + const MutableBufferSequence& buffer_sequence, const Allocator& alloc, + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + > = 0) +{ + return buffer_registration<MutableBufferSequence, Allocator>( + ex, buffer_sequence, alloc); +} + +/// Register buffers with an execution context. +template <typename ExecutionContext, typename MutableBufferSequence> +ASIO_NODISCARD inline +buffer_registration<MutableBufferSequence> +register_buffers(ExecutionContext& ctx, + const MutableBufferSequence& buffer_sequence, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) +{ + return buffer_registration<MutableBufferSequence>(ctx, buffer_sequence); +} + +/// Register buffers with an execution context. +template <typename ExecutionContext, + typename MutableBufferSequence, typename Allocator> +ASIO_NODISCARD inline +buffer_registration<MutableBufferSequence, Allocator> +register_buffers(ExecutionContext& ctx, + const MutableBufferSequence& buffer_sequence, const Allocator& alloc, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) +{ + return buffer_registration<MutableBufferSequence, Allocator>( + ctx, buffer_sequence, alloc); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_BUFFER_REGISTRATION_HPP diff --git a/3rdparty/asio/include/asio/buffered_read_stream.hpp b/3rdparty/asio/include/asio/buffered_read_stream.hpp index 7ed91dc2e24..264f66c55d8 100644 --- a/3rdparty/asio/include/asio/buffered_read_stream.hpp +++ b/3rdparty/asio/include/asio/buffered_read_stream.hpp @@ -2,7 +2,7 @@ // buffered_read_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -30,6 +30,12 @@ #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { + +template <typename> class initiate_async_buffered_fill; +template <typename> class initiate_async_buffered_read_some; + +} // namespace detail /// Adds buffering to the read-related operations of a stream. /** @@ -49,7 +55,7 @@ class buffered_read_stream { public: /// The type of the next layer. - typedef typename remove_reference<Stream>::type next_layer_type; + typedef remove_reference_t<Stream> next_layer_type; /// The type of the lowest layer. typedef typename next_layer_type::lowest_layer_type lowest_layer_type; @@ -66,16 +72,17 @@ public: /// Construct, passing the specified argument to initialise the next layer. template <typename Arg> - explicit buffered_read_stream(Arg& a) - : next_layer_(a), + explicit buffered_read_stream(Arg&& a) + : next_layer_(static_cast<Arg&&>(a)), storage_(default_buffer_size) { } /// Construct, passing the specified argument to initialise the next layer. template <typename Arg> - buffered_read_stream(Arg& a, std::size_t buffer_size) - : next_layer_(a), + buffered_read_stream(Arg&& a, + std::size_t buffer_size) + : next_layer_(static_cast<Arg&&>(a)), storage_(buffer_size) { } @@ -99,7 +106,7 @@ public: } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + executor_type get_executor() noexcept { return next_layer_.lowest_layer().get_executor(); } @@ -136,18 +143,21 @@ public: /// Start an asynchronous write. The data being written must be valid for the /// lifetime of the asynchronous operation. + /** + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_write_some(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) WriteHandler = default_completion_token_t<executor_type>> + auto async_write_some(const ConstBufferSequence& buffers, + WriteHandler&& handler = default_completion_token_t<executor_type>()) + -> decltype( + declval<conditional_t<true, Stream&, WriteHandler>>().async_write_some( + buffers, static_cast<WriteHandler&&>(handler))) { return next_layer_.async_write_some(buffers, - ASIO_MOVE_CAST(WriteHandler)(handler)); + static_cast<WriteHandler&&>(handler)); } /// Fill the buffer with some data. Returns the number of bytes placed in the @@ -159,15 +169,20 @@ public: std::size_t fill(asio::error_code& ec); /// Start an asynchronous fill. + /** + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_fill( - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)); + std::size_t)) ReadHandler = default_completion_token_t<executor_type>> + auto async_fill( + ReadHandler&& handler = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadHandler, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_buffered_fill<Stream>>(), + handler, declval<detail::buffered_stream_storage*>())); /// Read some data from the stream. Returns the number of bytes read. Throws /// an exception on failure. @@ -182,15 +197,20 @@ public: /// Start an asynchronous read. The buffer into which the data will be read /// must be valid for the lifetime of the asynchronous operation. + /** + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_read_some(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)); + std::size_t)) ReadHandler = default_completion_token_t<executor_type>> + auto async_read_some(const MutableBufferSequence& buffers, + ReadHandler&& handler = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadHandler, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_buffered_read_some<Stream>>(), + handler, declval<detail::buffered_stream_storage*>(), buffers)); /// Peek at the incoming data on the stream. Returns the number of bytes read. /// Throws an exception on failure. diff --git a/3rdparty/asio/include/asio/buffered_read_stream_fwd.hpp b/3rdparty/asio/include/asio/buffered_read_stream_fwd.hpp index f189b27aadf..d98aa70483a 100644 --- a/3rdparty/asio/include/asio/buffered_read_stream_fwd.hpp +++ b/3rdparty/asio/include/asio/buffered_read_stream_fwd.hpp @@ -2,7 +2,7 @@ // buffered_read_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/buffered_stream.hpp b/3rdparty/asio/include/asio/buffered_stream.hpp index 5d71bf66105..e0e1b47b792 100644 --- a/3rdparty/asio/include/asio/buffered_stream.hpp +++ b/3rdparty/asio/include/asio/buffered_stream.hpp @@ -2,7 +2,7 @@ // buffered_stream.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -46,7 +46,7 @@ class buffered_stream { public: /// The type of the next layer. - typedef typename remove_reference<Stream>::type next_layer_type; + typedef remove_reference_t<Stream> next_layer_type; /// The type of the lowest layer. typedef typename next_layer_type::lowest_layer_type lowest_layer_type; @@ -56,17 +56,17 @@ public: /// Construct, passing the specified argument to initialise the next layer. template <typename Arg> - explicit buffered_stream(Arg& a) - : inner_stream_impl_(a), + explicit buffered_stream(Arg&& a) + : inner_stream_impl_(static_cast<Arg&&>(a)), stream_impl_(inner_stream_impl_) { } /// Construct, passing the specified argument to initialise the next layer. template <typename Arg> - explicit buffered_stream(Arg& a, std::size_t read_buffer_size, - std::size_t write_buffer_size) - : inner_stream_impl_(a, write_buffer_size), + explicit buffered_stream(Arg&& a, + std::size_t read_buffer_size, std::size_t write_buffer_size) + : inner_stream_impl_(static_cast<Arg&&>(a), write_buffer_size), stream_impl_(inner_stream_impl_, read_buffer_size) { } @@ -90,7 +90,7 @@ public: } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + executor_type get_executor() noexcept { return stream_impl_.lowest_layer().get_executor(); } @@ -125,18 +125,21 @@ public: } /// Start an asynchronous flush. + /** + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_flush( - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) WriteHandler = default_completion_token_t<executor_type>> + auto async_flush( + WriteHandler&& handler = default_completion_token_t<executor_type>()) + -> decltype( + declval<buffered_write_stream<Stream>&>().async_flush( + static_cast<WriteHandler&&>(handler))) { return stream_impl_.next_layer().async_flush( - ASIO_MOVE_CAST(WriteHandler)(handler)); + static_cast<WriteHandler&&>(handler)); } /// Write the given data to the stream. Returns the number of bytes written. @@ -158,18 +161,21 @@ public: /// Start an asynchronous write. The data being written must be valid for the /// lifetime of the asynchronous operation. + /** + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_write_some(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) WriteHandler = default_completion_token_t<executor_type>> + auto async_write_some(const ConstBufferSequence& buffers, + WriteHandler&& handler = default_completion_token_t<executor_type>()) + -> decltype( + declval<Stream&>().async_write_some(buffers, + static_cast<WriteHandler&&>(handler))) { return stream_impl_.async_write_some(buffers, - ASIO_MOVE_CAST(WriteHandler)(handler)); + static_cast<WriteHandler&&>(handler)); } /// Fill the buffer with some data. Returns the number of bytes placed in the @@ -187,17 +193,21 @@ public: } /// Start an asynchronous fill. + /** + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_fill( - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) ReadHandler = default_completion_token_t<executor_type>> + auto async_fill( + ReadHandler&& handler = default_completion_token_t<executor_type>()) + -> decltype( + declval<buffered_read_stream< + buffered_write_stream<Stream>>&>().async_fill( + static_cast<ReadHandler&&>(handler))) { - return stream_impl_.async_fill(ASIO_MOVE_CAST(ReadHandler)(handler)); + return stream_impl_.async_fill(static_cast<ReadHandler&&>(handler)); } /// Read some data from the stream. Returns the number of bytes read. Throws @@ -219,18 +229,21 @@ public: /// Start an asynchronous read. The buffer into which the data will be read /// must be valid for the lifetime of the asynchronous operation. + /** + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_read_some(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) ReadHandler = default_completion_token_t<executor_type>> + auto async_read_some(const MutableBufferSequence& buffers, + ReadHandler&& handler = default_completion_token_t<executor_type>()) + -> decltype( + declval<Stream&>().async_read_some(buffers, + static_cast<ReadHandler&&>(handler))) { return stream_impl_.async_read_some(buffers, - ASIO_MOVE_CAST(ReadHandler)(handler)); + static_cast<ReadHandler&&>(handler)); } /// Peek at the incoming data on the stream. Returns the number of bytes read. diff --git a/3rdparty/asio/include/asio/buffered_stream_fwd.hpp b/3rdparty/asio/include/asio/buffered_stream_fwd.hpp index d970cbba7a0..790c76269f9 100644 --- a/3rdparty/asio/include/asio/buffered_stream_fwd.hpp +++ b/3rdparty/asio/include/asio/buffered_stream_fwd.hpp @@ -2,7 +2,7 @@ // buffered_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/buffered_write_stream.hpp b/3rdparty/asio/include/asio/buffered_write_stream.hpp index 526cd602916..f8f0538dcea 100644 --- a/3rdparty/asio/include/asio/buffered_write_stream.hpp +++ b/3rdparty/asio/include/asio/buffered_write_stream.hpp @@ -2,7 +2,7 @@ // buffered_write_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -30,6 +30,12 @@ #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { + +template <typename> class initiate_async_buffered_flush; +template <typename> class initiate_async_buffered_write_some; + +} // namespace detail /// Adds buffering to the write-related operations of a stream. /** @@ -49,7 +55,7 @@ class buffered_write_stream { public: /// The type of the next layer. - typedef typename remove_reference<Stream>::type next_layer_type; + typedef remove_reference_t<Stream> next_layer_type; /// The type of the lowest layer. typedef typename next_layer_type::lowest_layer_type lowest_layer_type; @@ -66,16 +72,17 @@ public: /// Construct, passing the specified argument to initialise the next layer. template <typename Arg> - explicit buffered_write_stream(Arg& a) - : next_layer_(a), + explicit buffered_write_stream(Arg&& a) + : next_layer_(static_cast<Arg&&>(a)), storage_(default_buffer_size) { } /// Construct, passing the specified argument to initialise the next layer. template <typename Arg> - buffered_write_stream(Arg& a, std::size_t buffer_size) - : next_layer_(a), + buffered_write_stream(Arg&& a, + std::size_t buffer_size) + : next_layer_(static_cast<Arg&&>(a)), storage_(buffer_size) { } @@ -99,7 +106,7 @@ public: } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + executor_type get_executor() noexcept { return next_layer_.lowest_layer().get_executor(); } @@ -128,15 +135,20 @@ public: std::size_t flush(asio::error_code& ec); /// Start an asynchronous flush. + /** + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_flush( - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)); + std::size_t)) WriteHandler = default_completion_token_t<executor_type>> + auto async_flush( + WriteHandler&& handler = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteHandler, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_buffered_flush<Stream>>(), + handler, declval<detail::buffered_stream_storage*>())); /// Write the given data to the stream. Returns the number of bytes written. /// Throws an exception on failure. @@ -151,15 +163,20 @@ public: /// Start an asynchronous write. The data being written must be valid for the /// lifetime of the asynchronous operation. + /** + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_write_some(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)); + std::size_t)) WriteHandler = default_completion_token_t<executor_type>> + auto async_write_some(const ConstBufferSequence& buffers, + WriteHandler&& handler = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteHandler, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_buffered_write_some<Stream>>(), + handler, declval<detail::buffered_stream_storage*>(), buffers)); /// Read some data from the stream. Returns the number of bytes read. Throws /// an exception on failure. @@ -180,18 +197,21 @@ public: /// Start an asynchronous read. The buffer into which the data will be read /// must be valid for the lifetime of the asynchronous operation. + /** + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_read_some(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) ReadHandler = default_completion_token_t<executor_type>> + auto async_read_some(const MutableBufferSequence& buffers, + ReadHandler&& handler = default_completion_token_t<executor_type>()) + -> decltype( + declval<conditional_t<true, Stream&, ReadHandler>>().async_read_some( + buffers, static_cast<ReadHandler&&>(handler))) { return next_layer_.async_read_some(buffers, - ASIO_MOVE_CAST(ReadHandler)(handler)); + static_cast<ReadHandler&&>(handler)); } /// Peek at the incoming data on the stream. Returns the number of bytes read. diff --git a/3rdparty/asio/include/asio/buffered_write_stream_fwd.hpp b/3rdparty/asio/include/asio/buffered_write_stream_fwd.hpp index 8999d9e4c21..809f44af03d 100644 --- a/3rdparty/asio/include/asio/buffered_write_stream_fwd.hpp +++ b/3rdparty/asio/include/asio/buffered_write_stream_fwd.hpp @@ -2,7 +2,7 @@ // buffered_write_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/buffers_iterator.hpp b/3rdparty/asio/include/asio/buffers_iterator.hpp index 76b734a6448..2c6d720787c 100644 --- a/3rdparty/asio/include/asio/buffers_iterator.hpp +++ b/3rdparty/asio/include/asio/buffers_iterator.hpp @@ -2,7 +2,7 @@ // buffers_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -38,7 +38,7 @@ namespace detail template <typename ByteType> struct byte_type { - typedef typename add_const<ByteType>::type type; + typedef add_const_t<ByteType> type; }; }; @@ -80,7 +80,7 @@ namespace detail struct buffers_iterator_types<const_buffer, ByteType> { typedef const_buffer buffer_type; - typedef typename add_const<ByteType>::type byte_type; + typedef add_const_t<ByteType> byte_type; typedef const const_buffer* const_iterator; }; @@ -98,7 +98,7 @@ namespace detail struct buffers_iterator_types<const_buffers_1, ByteType> { typedef const_buffer buffer_type; - typedef typename add_const<ByteType>::type byte_type; + typedef add_const_t<ByteType> byte_type; typedef const const_buffer* const_iterator; }; diff --git a/3rdparty/asio/include/asio/cancellation_signal.hpp b/3rdparty/asio/include/asio/cancellation_signal.hpp index afbaecdaf40..43540ac3b08 100644 --- a/3rdparty/asio/include/asio/cancellation_signal.hpp +++ b/3rdparty/asio/include/asio/cancellation_signal.hpp @@ -2,7 +2,7 @@ // cancellation_signal.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -21,10 +21,7 @@ #include <utility> #include "asio/cancellation_type.hpp" #include "asio/detail/cstddef.hpp" -#include "asio/detail/thread_context.hpp" -#include "asio/detail/thread_info_base.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" #include "asio/detail/push_options.hpp" @@ -35,7 +32,7 @@ class cancellation_handler_base { public: virtual void call(cancellation_type_t) = 0; - virtual std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT = 0; + virtual std::pair<void*, std::size_t> destroy() noexcept = 0; protected: ~cancellation_handler_base() {} @@ -46,45 +43,26 @@ class cancellation_handler : public cancellation_handler_base { public: -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename... Args> - cancellation_handler(std::size_t size, ASIO_MOVE_ARG(Args)... args) - : handler_(ASIO_MOVE_CAST(Args)(args)...), + cancellation_handler(std::size_t size, Args&&... args) + : handler_(static_cast<Args&&>(args)...), size_(size) { } -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - cancellation_handler(std::size_t size) - : handler_(), - size_(size) - { - } - -#define ASIO_PRIVATE_HANDLER_CTOR_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - cancellation_handler(std::size_t size, ASIO_VARIADIC_MOVE_PARAMS(n)) \ - : handler_(ASIO_VARIADIC_MOVE_ARGS(n)), \ - size_(size) \ - { \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_CTOR_DEF) -#undef ASIO_PRIVATE_HANDLER_CTOR_DEF -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) void call(cancellation_type_t type) { handler_(type); } - std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT + std::pair<void*, std::size_t> destroy() noexcept { std::pair<void*, std::size_t> mem(this, size_); this->cancellation_handler::~cancellation_handler(); return mem; } - Handler& handler() ASIO_NOEXCEPT + Handler& handler() noexcept { return handler_; } @@ -106,22 +84,12 @@ class cancellation_slot; class cancellation_signal { public: - ASIO_CONSTEXPR cancellation_signal() + constexpr cancellation_signal() : handler_(0) { } - ~cancellation_signal() - { - if (handler_) - { - std::pair<void*, std::size_t> mem = handler_->destroy(); - detail::thread_info_base::deallocate( - detail::thread_info_base::cancellation_signal_tag(), - detail::thread_context::top_of_thread_call_stack(), - mem.first, mem.second); - } - } + ASIO_DECL ~cancellation_signal(); /// Emits the signal and causes invocation of the slot's handler, if any. void emit(cancellation_type_t type) @@ -135,11 +103,11 @@ public: * The signal object must remain valid for as long the slot may be used. * Destruction of the signal invalidates the slot. */ - cancellation_slot slot() ASIO_NOEXCEPT; + cancellation_slot slot() noexcept; private: - cancellation_signal(const cancellation_signal&) ASIO_DELETED; - cancellation_signal& operator=(const cancellation_signal&) ASIO_DELETED; + cancellation_signal(const cancellation_signal&) = delete; + cancellation_signal& operator=(const cancellation_signal&) = delete; detail::cancellation_handler_base* handler_; }; @@ -149,13 +117,11 @@ class cancellation_slot { public: /// Creates a slot that is not connected to any cancellation signal. - ASIO_CONSTEXPR cancellation_slot() + constexpr cancellation_slot() : handler_(0) { } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \ - || defined(GENERATING_DOCUMENTATION) /// Installs a handler into the slot, constructing the new object directly. /** * Destroys any existing handler in the slot, then installs the new handler, @@ -174,58 +140,21 @@ public: * be copy constructible or move constructible. */ template <typename CancellationHandler, typename... Args> - CancellationHandler& emplace(ASIO_MOVE_ARG(Args)... args) + CancellationHandler& emplace(Args&&... args) { typedef detail::cancellation_handler<CancellationHandler> cancellation_handler_type; auto_delete_helper del = { prepare_memory( sizeof(cancellation_handler_type), - ASIO_ALIGNOF(CancellationHandler)) }; + alignof(CancellationHandler)) }; cancellation_handler_type* handler_obj = new (del.mem.first) cancellation_handler_type( - del.mem.second, ASIO_MOVE_CAST(Args)(args)...); - del.mem.first = 0; - *handler_ = handler_obj; - return handler_obj->handler(); - } -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - template <typename CancellationHandler> - CancellationHandler& emplace() - { - typedef detail::cancellation_handler<CancellationHandler> - cancellation_handler_type; - auto_delete_helper del = { prepare_memory( - sizeof(cancellation_handler_type), - ASIO_ALIGNOF(CancellationHandler)) }; - cancellation_handler_type* handler_obj = - new (del.mem.first) cancellation_handler_type(del.mem.second); + del.mem.second, static_cast<Args&&>(args)...); del.mem.first = 0; *handler_ = handler_obj; return handler_obj->handler(); } -#define ASIO_PRIVATE_HANDLER_EMPLACE_DEF(n) \ - template <typename CancellationHandler, ASIO_VARIADIC_TPARAMS(n)> \ - CancellationHandler& emplace(ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - typedef detail::cancellation_handler<CancellationHandler> \ - cancellation_handler_type; \ - auto_delete_helper del = { prepare_memory( \ - sizeof(cancellation_handler_type), \ - ASIO_ALIGNOF(CancellationHandler)) }; \ - cancellation_handler_type* handler_obj = \ - new (del.mem.first) cancellation_handler_type( \ - del.mem.second, ASIO_VARIADIC_MOVE_ARGS(n)); \ - del.mem.first = 0; \ - *handler_ = handler_obj; \ - return handler_obj->handler(); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_EMPLACE_DEF) -#undef ASIO_PRIVATE_HANDLER_EMPLACE_DEF -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - /// Installs a handler into the slot. /** * Destroys any existing handler in the slot, then installs the new handler, @@ -240,52 +169,40 @@ public: * @returns A reference to the newly installed handler. */ template <typename CancellationHandler> - typename decay<CancellationHandler>::type& assign( - ASIO_MOVE_ARG(CancellationHandler) handler) + decay_t<CancellationHandler>& assign(CancellationHandler&& handler) { - return this->emplace<typename decay<CancellationHandler>::type>( - ASIO_MOVE_CAST(CancellationHandler)(handler)); + return this->emplace<decay_t<CancellationHandler>>( + static_cast<CancellationHandler&&>(handler)); } /// Clears the slot. /** * Destroys any existing handler in the slot. */ - void clear() - { - if (handler_ != 0 && *handler_ != 0) - { - std::pair<void*, std::size_t> mem = (*handler_)->destroy(); - detail::thread_info_base::deallocate( - detail::thread_info_base::cancellation_signal_tag(), - detail::thread_context::top_of_thread_call_stack(), - mem.first, mem.second); - *handler_ = 0; - } - } + ASIO_DECL void clear(); /// Returns whether the slot is connected to a signal. - ASIO_CONSTEXPR bool is_connected() const ASIO_NOEXCEPT + constexpr bool is_connected() const noexcept { return handler_ != 0; } /// Returns whether the slot is connected and has an installed handler. - ASIO_CONSTEXPR bool has_handler() const ASIO_NOEXCEPT + constexpr bool has_handler() const noexcept { return handler_ != 0 && *handler_ != 0; } /// Compare two slots for equality. - friend ASIO_CONSTEXPR bool operator==(const cancellation_slot& lhs, - const cancellation_slot& rhs) ASIO_NOEXCEPT + friend constexpr bool operator==(const cancellation_slot& lhs, + const cancellation_slot& rhs) noexcept { return lhs.handler_ == rhs.handler_; } /// Compare two slots for inequality. - friend ASIO_CONSTEXPR bool operator!=(const cancellation_slot& lhs, - const cancellation_slot& rhs) ASIO_NOEXCEPT + friend constexpr bool operator!=(const cancellation_slot& lhs, + const cancellation_slot& rhs) noexcept { return lhs.handler_ != rhs.handler_; } @@ -293,61 +210,26 @@ public: private: friend class cancellation_signal; - ASIO_CONSTEXPR cancellation_slot(int, + constexpr cancellation_slot(int, detail::cancellation_handler_base** handler) : handler_(handler) { } - std::pair<void*, std::size_t> prepare_memory( - std::size_t size, std::size_t align) - { - assert(handler_); - std::pair<void*, std::size_t> mem; - if (*handler_) - { - mem = (*handler_)->destroy(); - *handler_ = 0; - } - if (size > mem.second - || reinterpret_cast<std::size_t>(mem.first) % align != 0) - { - if (mem.first) - { - detail::thread_info_base::deallocate( - detail::thread_info_base::cancellation_signal_tag(), - detail::thread_context::top_of_thread_call_stack(), - mem.first, mem.second); - } - mem.first = detail::thread_info_base::allocate( - detail::thread_info_base::cancellation_signal_tag(), - detail::thread_context::top_of_thread_call_stack(), - size, align); - mem.second = size; - } - return mem; - } + ASIO_DECL std::pair<void*, std::size_t> prepare_memory( + std::size_t size, std::size_t align); struct auto_delete_helper { std::pair<void*, std::size_t> mem; - ~auto_delete_helper() - { - if (mem.first) - { - detail::thread_info_base::deallocate( - detail::thread_info_base::cancellation_signal_tag(), - detail::thread_context::top_of_thread_call_stack(), - mem.first, mem.second); - } - } + ASIO_DECL ~auto_delete_helper(); }; detail::cancellation_handler_base** handler_; }; -inline cancellation_slot cancellation_signal::slot() ASIO_NOEXCEPT +inline cancellation_slot cancellation_signal::slot() noexcept { return cancellation_slot(0, &handler_); } @@ -356,4 +238,8 @@ inline cancellation_slot cancellation_signal::slot() ASIO_NOEXCEPT #include "asio/detail/pop_options.hpp" +#if defined(ASIO_HEADER_ONLY) +# include "asio/impl/cancellation_signal.ipp" +#endif // defined(ASIO_HEADER_ONLY) + #endif // ASIO_CANCELLATION_SIGNAL_HPP diff --git a/3rdparty/asio/include/asio/cancellation_state.hpp b/3rdparty/asio/include/asio/cancellation_state.hpp index 868d8d678cc..3c13edcab94 100644 --- a/3rdparty/asio/include/asio/cancellation_state.hpp +++ b/3rdparty/asio/include/asio/cancellation_state.hpp @@ -2,7 +2,7 @@ // cancellation_state.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -32,7 +32,7 @@ struct cancellation_filter { /// Returns <tt>type & Mask</tt>. cancellation_type_t operator()( - cancellation_type_t type) const ASIO_NOEXCEPT + cancellation_type_t type) const noexcept { return type & Mask; } @@ -80,7 +80,7 @@ class cancellation_state { public: /// Construct a disconnected cancellation state. - ASIO_CONSTEXPR cancellation_state() ASIO_NOEXCEPT + constexpr cancellation_state() noexcept : impl_(0) { } @@ -95,8 +95,8 @@ public: * attached. */ template <typename CancellationSlot> - ASIO_CONSTEXPR explicit cancellation_state(CancellationSlot slot) - : impl_(slot.is_connected() ? &slot.template emplace<impl<> >() : 0) + constexpr explicit cancellation_state(CancellationSlot slot) + : impl_(slot.is_connected() ? &slot.template emplace<impl<>>() : 0) { } @@ -119,9 +119,9 @@ public: * @li asio::enable_total_cancellation */ template <typename CancellationSlot, typename Filter> - ASIO_CONSTEXPR cancellation_state(CancellationSlot slot, Filter filter) + constexpr cancellation_state(CancellationSlot slot, Filter filter) : impl_(slot.is_connected() - ? &slot.template emplace<impl<Filter, Filter> >(filter, filter) + ? &slot.template emplace<impl<Filter, Filter>>(filter, filter) : 0) { } @@ -151,12 +151,12 @@ public: * @li asio::enable_total_cancellation */ template <typename CancellationSlot, typename InFilter, typename OutFilter> - ASIO_CONSTEXPR cancellation_state(CancellationSlot slot, + constexpr cancellation_state(CancellationSlot slot, InFilter in_filter, OutFilter out_filter) : impl_(slot.is_connected() - ? &slot.template emplace<impl<InFilter, OutFilter> >( - ASIO_MOVE_CAST(InFilter)(in_filter), - ASIO_MOVE_CAST(OutFilter)(out_filter)) + ? &slot.template emplace<impl<InFilter, OutFilter>>( + static_cast<InFilter&&>(in_filter), + static_cast<OutFilter&&>(out_filter)) : 0) { } @@ -165,20 +165,20 @@ public: /** * This sub-slot is used with the operations that are being composed. */ - ASIO_CONSTEXPR cancellation_slot slot() const ASIO_NOEXCEPT + constexpr cancellation_slot slot() const noexcept { return impl_ ? impl_->signal_.slot() : cancellation_slot(); } /// Returns the cancellation types that have been triggered. - cancellation_type_t cancelled() const ASIO_NOEXCEPT + cancellation_type_t cancelled() const noexcept { return impl_ ? impl_->cancelled_ : cancellation_type_t(); } /// Clears the specified cancellation types, if they have been triggered. void clear(cancellation_type_t mask = cancellation_type::all) - ASIO_NOEXCEPT + noexcept { if (impl_) impl_->cancelled_ &= ~mask; @@ -208,8 +208,8 @@ private: } impl(InFilter in_filter, OutFilter out_filter) - : in_filter_(ASIO_MOVE_CAST(InFilter)(in_filter)), - out_filter_(ASIO_MOVE_CAST(OutFilter)(out_filter)) + : in_filter_(static_cast<InFilter&&>(in_filter)), + out_filter_(static_cast<OutFilter&&>(out_filter)) { } diff --git a/3rdparty/asio/include/asio/cancellation_type.hpp b/3rdparty/asio/include/asio/cancellation_type.hpp index 9eff047b63d..ec4a4d2458a 100644 --- a/3rdparty/asio/include/asio/cancellation_type.hpp +++ b/3rdparty/asio/include/asio/cancellation_type.hpp @@ -2,7 +2,7 @@ // cancellation_type.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -51,7 +51,7 @@ enum cancellation_type /// Portability typedef. typedef cancellation_type cancellation_type_t; -#elif defined(ASIO_HAS_ENUM_CLASS) +#else // defined(GENERATING_DOCUMENTATION) enum class cancellation_type : unsigned int { @@ -64,30 +64,13 @@ enum class cancellation_type : unsigned int typedef cancellation_type cancellation_type_t; -#else // defined(ASIO_HAS_ENUM_CLASS) - -namespace cancellation_type { - -enum cancellation_type_t -{ - none = 0, - terminal = 1, - partial = 2, - total = 4, - all = 0xFFFFFFFF -}; - -} // namespace cancellation_type - -typedef cancellation_type::cancellation_type_t cancellation_type_t; - -#endif // defined(ASIO_HAS_ENUM_CLASS) +#endif // defined(GENERATING_DOCUMENTATION) /// Negation operator. /** * @relates cancellation_type */ -inline ASIO_CONSTEXPR bool operator!(cancellation_type_t x) +inline constexpr bool operator!(cancellation_type_t x) { return static_cast<unsigned int>(x) == 0; } @@ -96,7 +79,7 @@ inline ASIO_CONSTEXPR bool operator!(cancellation_type_t x) /** * @relates cancellation_type */ -inline ASIO_CONSTEXPR cancellation_type_t operator&( +inline constexpr cancellation_type_t operator&( cancellation_type_t x, cancellation_type_t y) { return static_cast<cancellation_type_t>( @@ -107,7 +90,7 @@ inline ASIO_CONSTEXPR cancellation_type_t operator&( /** * @relates cancellation_type */ -inline ASIO_CONSTEXPR cancellation_type_t operator|( +inline constexpr cancellation_type_t operator|( cancellation_type_t x, cancellation_type_t y) { return static_cast<cancellation_type_t>( @@ -118,7 +101,7 @@ inline ASIO_CONSTEXPR cancellation_type_t operator|( /** * @relates cancellation_type */ -inline ASIO_CONSTEXPR cancellation_type_t operator^( +inline constexpr cancellation_type_t operator^( cancellation_type_t x, cancellation_type_t y) { return static_cast<cancellation_type_t>( @@ -129,7 +112,7 @@ inline ASIO_CONSTEXPR cancellation_type_t operator^( /** * @relates cancellation_type */ -inline ASIO_CONSTEXPR cancellation_type_t operator~(cancellation_type_t x) +inline constexpr cancellation_type_t operator~(cancellation_type_t x) { return static_cast<cancellation_type_t>(~static_cast<unsigned int>(x)); } diff --git a/3rdparty/asio/include/asio/co_spawn.hpp b/3rdparty/asio/include/asio/co_spawn.hpp index d65593d69f4..26988f47da0 100644 --- a/3rdparty/asio/include/asio/co_spawn.hpp +++ b/3rdparty/asio/include/asio/co_spawn.hpp @@ -2,7 +2,7 @@ // co_spawn.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -54,11 +54,14 @@ struct awaitable_signature<awaitable<void, Executor>> * @param a The asio::awaitable object that is the result of calling the * coroutine's entry point function. * - * @param token The completion token that will handle the notification that + * @param token The @ref completion_token that will handle the notification that * the thread of execution has completed. The function signature of the * completion handler must be: * @code void handler(std::exception_ptr, T); @endcode * + * @par Completion Signature + * @code void(std::exception_ptr, T) @endcode + * * @par Example * @code * asio::awaitable<std::size_t> echo(tcp::socket socket) @@ -110,10 +113,10 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE( co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN(Executor), - typename constraint< + constraint_t< (is_executor<Executor>::value || execution::is_executor<Executor>::value) && is_convertible<Executor, AwaitableExecutor>::value - >::type = 0); + > = 0); /// Spawn a new coroutined-based thread of execution. /** @@ -123,11 +126,14 @@ co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a, * @param a The asio::awaitable object that is the result of calling the * coroutine's entry point function. * - * @param token The completion token that will handle the notification that + * @param token The @ref completion_token that will handle the notification that * the thread of execution has completed. The function signature of the * completion handler must be: * @code void handler(std::exception_ptr); @endcode * + * @par Completion Signature + * @code void(std::exception_ptr) @endcode + * * @par Example * @code * asio::awaitable<void> echo(tcp::socket socket) @@ -171,10 +177,10 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE( co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN(Executor), - typename constraint< + constraint_t< (is_executor<Executor>::value || execution::is_executor<Executor>::value) && is_convertible<Executor, AwaitableExecutor>::value - >::type = 0); + > = 0); /// Spawn a new coroutined-based thread of execution. /** @@ -184,11 +190,14 @@ co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a, * @param a The asio::awaitable object that is the result of calling the * coroutine's entry point function. * - * @param token The completion token that will handle the notification that + * @param token The @ref completion_token that will handle the notification that * the thread of execution has completed. The function signature of the * completion handler must be: * @code void handler(std::exception_ptr); @endcode * + * @par Completion Signature + * @code void(std::exception_ptr, T) @endcode + * * @par Example * @code * asio::awaitable<std::size_t> echo(tcp::socket socket) @@ -242,11 +251,11 @@ co_spawn(ExecutionContext& ctx, awaitable<T, AwaitableExecutor> a, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type), - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value && is_convertible<typename ExecutionContext::executor_type, AwaitableExecutor>::value - >::type = 0); + > = 0); /// Spawn a new coroutined-based thread of execution. /** @@ -256,11 +265,14 @@ co_spawn(ExecutionContext& ctx, awaitable<T, AwaitableExecutor> a, * @param a The asio::awaitable object that is the result of calling the * coroutine's entry point function. * - * @param token The completion token that will handle the notification that + * @param token The @ref completion_token that will handle the notification that * the thread of execution has completed. The function signature of the * completion handler must be: * @code void handler(std::exception_ptr); @endcode * + * @par Completion Signature + * @code void(std::exception_ptr) @endcode + * * @par Example * @code * asio::awaitable<void> echo(tcp::socket socket) @@ -306,11 +318,11 @@ co_spawn(ExecutionContext& ctx, awaitable<void, AwaitableExecutor> a, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type), - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value && is_convertible<typename ExecutionContext::executor_type, AwaitableExecutor>::value - >::type = 0); + > = 0); /// Spawn a new coroutined-based thread of execution. /** @@ -321,14 +333,20 @@ co_spawn(ExecutionContext& ctx, awaitable<void, AwaitableExecutor> a, * @c asio::awaitable<R,E> that will be used as the coroutine's entry * point. * - * @param token The completion token that will handle the notification that the - * thread of execution has completed. If @c R is @c void, the function + * @param token The @ref completion_token that will handle the notification + * that the thread of execution has completed. If @c R is @c void, the function * signature of the completion handler must be: * * @code void handler(std::exception_ptr); @endcode * Otherwise, the function signature of the completion handler must be: * @code void handler(std::exception_ptr, R); @endcode * + * @par Completion Signature + * @code void(std::exception_ptr, R) @endcode + * where @c R is the first template argument to the @c awaitable returned by the + * supplied function object @c F: + * @code asio::awaitable<R, AwaitableExecutor> F() @endcode + * * @par Example * @code * asio::awaitable<std::size_t> echo(tcp::socket socket) @@ -388,16 +406,16 @@ co_spawn(ExecutionContext& ctx, awaitable<void, AwaitableExecutor> a, */ template <typename Executor, typename F, ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature< - typename result_of<F()>::type>::type) CompletionToken + result_of_t<F()>>::type) CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, - typename detail::awaitable_signature<typename result_of<F()>::type>::type) + typename detail::awaitable_signature<result_of_t<F()>>::type) co_spawn(const Executor& ex, F&& f, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN(Executor), - typename constraint< + constraint_t< is_executor<Executor>::value || execution::is_executor<Executor>::value - >::type = 0); + > = 0); /// Spawn a new coroutined-based thread of execution. /** @@ -408,14 +426,20 @@ co_spawn(const Executor& ex, F&& f, * @c asio::awaitable<R,E> that will be used as the coroutine's entry * point. * - * @param token The completion token that will handle the notification that the - * thread of execution has completed. If @c R is @c void, the function + * @param token The @ref completion_token that will handle the notification + * that the thread of execution has completed. If @c R is @c void, the function * signature of the completion handler must be: * * @code void handler(std::exception_ptr); @endcode * Otherwise, the function signature of the completion handler must be: * @code void handler(std::exception_ptr, R); @endcode * + * @par Completion Signature + * @code void(std::exception_ptr, R) @endcode + * where @c R is the first template argument to the @c awaitable returned by the + * supplied function object @c F: + * @code asio::awaitable<R, AwaitableExecutor> F() @endcode + * * @par Example * @code * asio::awaitable<std::size_t> echo(tcp::socket socket) @@ -475,18 +499,18 @@ co_spawn(const Executor& ex, F&& f, */ template <typename ExecutionContext, typename F, ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature< - typename result_of<F()>::type>::type) CompletionToken + result_of_t<F()>>::type) CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( typename ExecutionContext::executor_type)> ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, - typename detail::awaitable_signature<typename result_of<F()>::type>::type) + typename detail::awaitable_signature<result_of_t<F()>>::type) co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token ASIO_DEFAULT_COMPLETION_TOKEN( typename ExecutionContext::executor_type), - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0); + > = 0); } // namespace asio diff --git a/3rdparty/asio/include/asio/completion_condition.hpp b/3rdparty/asio/include/asio/completion_condition.hpp index cf8c7c2bc92..3fe774f1ef1 100644 --- a/3rdparty/asio/include/asio/completion_condition.hpp +++ b/3rdparty/asio/include/asio/completion_condition.hpp @@ -2,7 +2,7 @@ // completion_condition.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/compose.hpp b/3rdparty/asio/include/asio/compose.hpp index 3f6f1b88978..abb438e3da7 100644 --- a/3rdparty/asio/include/asio/compose.hpp +++ b/3rdparty/asio/include/asio/compose.hpp @@ -2,7 +2,7 @@ // compose.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,14 +16,196 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" +#include "asio/associated_executor.hpp" #include "asio/async_result.hpp" +#include "asio/detail/base_from_cancellation_state.hpp" +#include "asio/detail/composed_work.hpp" +#include "asio/detail/handler_cont_helpers.hpp" +#include "asio/detail/type_traits.hpp" #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \ - || defined(GENERATING_DOCUMENTATION) +template <typename Impl, typename Work, typename Handler, typename Signature> +class composed_op; + +template <typename Impl, typename Work, typename Handler, + typename R, typename... Args> +class composed_op<Impl, Work, Handler, R(Args...)> + : public base_from_cancellation_state<Handler> +{ +public: + template <typename I, typename W, typename H> + composed_op(I&& impl, + W&& work, + H&& handler) + : base_from_cancellation_state<Handler>( + handler, enable_terminal_cancellation()), + impl_(static_cast<I&&>(impl)), + work_(static_cast<W&&>(work)), + handler_(static_cast<H&&>(handler)), + invocations_(0) + { + } + + composed_op(composed_op&& other) + : base_from_cancellation_state<Handler>( + static_cast<base_from_cancellation_state<Handler>&&>(other)), + impl_(static_cast<Impl&&>(other.impl_)), + work_(static_cast<Work&&>(other.work_)), + handler_(static_cast<Handler&&>(other.handler_)), + invocations_(other.invocations_) + { + } + + typedef typename composed_work_guard< + typename Work::head_type>::executor_type io_executor_type; + + io_executor_type get_io_executor() const noexcept + { + return work_.head_.get_executor(); + } + + typedef associated_executor_t<Handler, io_executor_type> executor_type; + + executor_type get_executor() const noexcept + { + return (get_associated_executor)(handler_, work_.head_.get_executor()); + } + + typedef associated_allocator_t<Handler, std::allocator<void>> allocator_type; + + allocator_type get_allocator() const noexcept + { + return (get_associated_allocator)(handler_, std::allocator<void>()); + } + + template<typename... T> + void operator()(T&&... t) + { + if (invocations_ < ~0u) + ++invocations_; + this->get_cancellation_state().slot().clear(); + impl_(*this, static_cast<T&&>(t)...); + } + + void complete(Args... args) + { + this->work_.reset(); + static_cast<Handler&&>(this->handler_)(static_cast<Args&&>(args)...); + } + + void reset_cancellation_state() + { + base_from_cancellation_state<Handler>::reset_cancellation_state(handler_); + } + + template <typename Filter> + void reset_cancellation_state(Filter&& filter) + { + base_from_cancellation_state<Handler>::reset_cancellation_state(handler_, + static_cast<Filter&&>(filter)); + } + + template <typename InFilter, typename OutFilter> + void reset_cancellation_state(InFilter&& in_filter, + OutFilter&& out_filter) + { + base_from_cancellation_state<Handler>::reset_cancellation_state(handler_, + static_cast<InFilter&&>(in_filter), + static_cast<OutFilter&&>(out_filter)); + } + + cancellation_type_t cancelled() const noexcept + { + return base_from_cancellation_state<Handler>::cancelled(); + } + +//private: + Impl impl_; + Work work_; + Handler handler_; + unsigned invocations_; +}; + +template <typename Impl, typename Work, typename Handler, typename Signature> +inline bool asio_handler_is_continuation( + composed_op<Impl, Work, Handler, Signature>* this_handler) +{ + return this_handler->invocations_ > 1 ? true + : asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Signature, typename Executors> +class initiate_composed_op +{ +public: + typedef typename composed_io_executors<Executors>::head_type executor_type; + + template <typename T> + explicit initiate_composed_op(int, T&& executors) + : executors_(static_cast<T&&>(executors)) + { + } + + executor_type get_executor() const noexcept + { + return executors_.head_; + } + + template <typename Handler, typename Impl> + void operator()(Handler&& handler, + Impl&& impl) const + { + composed_op<decay_t<Impl>, composed_work<Executors>, + decay_t<Handler>, Signature>( + static_cast<Impl&&>(impl), + composed_work<Executors>(executors_), + static_cast<Handler&&>(handler))(); + } + +private: + composed_io_executors<Executors> executors_; +}; + +template <typename Signature, typename Executors> +inline initiate_composed_op<Signature, Executors> make_initiate_composed_op( + composed_io_executors<Executors>&& executors) +{ + return initiate_composed_op<Signature, Executors>(0, + static_cast<composed_io_executors<Executors>&&>(executors)); +} + +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <template <typename, typename> class Associator, + typename Impl, typename Work, typename Handler, + typename Signature, typename DefaultCandidate> +struct associator<Associator, + detail::composed_op<Impl, Work, Handler, Signature>, + DefaultCandidate> + : Associator<Handler, DefaultCandidate> +{ + static typename Associator<Handler, DefaultCandidate>::type get( + const detail::composed_op<Impl, Work, Handler, Signature>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::composed_op<Impl, Work, Handler, Signature>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) + { + return Associator<Handler, DefaultCandidate>::get(h.handler_, c); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) /// Launch an asynchronous operation with a stateful implementation. /** @@ -37,12 +219,19 @@ namespace asio { * handler. The remaining arguments are any arguments that originate from the * completion handlers of any asynchronous operations performed by the * implementation. - + * * @param token The completion token. * * @param io_objects_or_executors Zero or more I/O objects or I/O executors for * which outstanding work must be maintained. * + * @par Per-Operation Cancellation + * By default, terminal per-operation cancellation is enabled for + * composed operations that are implemented using @c async_compose. To + * disable cancellation for the composed operation, or to alter its + * supported cancellation types, call the @c self object's @c + * reset_cancellation_state function. + * * @par Example: * * @code struct async_echo_implementation @@ -87,9 +276,11 @@ namespace asio { * auto async_echo(tcp::socket& socket, * asio::mutable_buffer buffer, * CompletionToken&& token) -> - * typename asio::async_result< - * typename std::decay<CompletionToken>::type, - * void(asio::error_code, std::size_t)>::return_type + * decltype( + * asio::async_compose<CompletionToken, + * void(asio::error_code, std::size_t)>( + * std::declval<async_echo_implementation>(), + * token, socket)) * { * return asio::async_compose<CompletionToken, * void(asio::error_code, std::size_t)>( @@ -100,37 +291,29 @@ namespace asio { */ template <typename CompletionToken, typename Signature, typename Implementation, typename... IoObjectsOrExecutors> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) -async_compose(ASIO_MOVE_ARG(Implementation) implementation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, - ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors); - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - -template <typename CompletionToken, typename Signature, typename Implementation> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) -async_compose(ASIO_MOVE_ARG(Implementation) implementation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token); - -#define ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \ - template <typename CompletionToken, typename Signature, \ - typename Implementation, ASIO_VARIADIC_TPARAMS(n)> \ - ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) \ - async_compose(ASIO_MOVE_ARG(Implementation) implementation, \ - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)); - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_COMPOSE_DEF) -#undef ASIO_PRIVATE_ASYNC_COMPOSE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) +auto async_compose(Implementation&& implementation, + type_identity_t<CompletionToken>& token, + IoObjectsOrExecutors&&... io_objects_or_executors) + -> decltype( + async_initiate<CompletionToken, Signature>( + detail::make_initiate_composed_op<Signature>( + detail::make_composed_io_executors( + detail::get_composed_io_executor( + static_cast<IoObjectsOrExecutors&&>( + io_objects_or_executors))...)), + token, static_cast<Implementation&&>(implementation))) +{ + return async_initiate<CompletionToken, Signature>( + detail::make_initiate_composed_op<Signature>( + detail::make_composed_io_executors( + detail::get_composed_io_executor( + static_cast<IoObjectsOrExecutors&&>( + io_objects_or_executors))...)), + token, static_cast<Implementation&&>(implementation)); +} } // namespace asio #include "asio/detail/pop_options.hpp" -#include "asio/impl/compose.hpp" - #endif // ASIO_COMPOSE_HPP diff --git a/3rdparty/asio/include/asio/connect.hpp b/3rdparty/asio/include/asio/connect.hpp index ff22a670b17..d2916675455 100644 --- a/3rdparty/asio/include/asio/connect.hpp +++ b/3rdparty/asio/include/asio/connect.hpp @@ -2,7 +2,7 @@ // connect.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -27,6 +27,10 @@ namespace asio { namespace detail { + struct default_connect_condition; + template <typename, typename> class initiate_async_range_connect; + template <typename, typename> class initiate_async_iterator_connect; + char (&has_iterator_helper(...))[2]; template <typename T> @@ -90,8 +94,7 @@ struct is_endpoint_sequence template <typename Protocol, typename Executor, typename EndpointSequence> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type = 0); + constraint_t<is_endpoint_sequence<EndpointSequence>::value> = 0); /// Establishes a socket connection by trying each endpoint in a sequence. /** @@ -126,8 +129,7 @@ typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, template <typename Protocol, typename Executor, typename EndpointSequence> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, asio::error_code& ec, - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type = 0); + constraint_t<is_endpoint_sequence<EndpointSequence>::value> = 0); #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Establishes a socket connection by trying @@ -156,7 +158,7 @@ typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, */ template <typename Protocol, typename Executor, typename Iterator> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, - typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); + constraint_t<!is_endpoint_sequence<Iterator>::value> = 0); /// (Deprecated: Use range overload.) Establishes a socket connection by trying /// each endpoint in a sequence. @@ -185,7 +187,7 @@ Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, template <typename Protocol, typename Executor, typename Iterator> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, asio::error_code& ec, - typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); + constraint_t<!is_endpoint_sequence<Iterator>::value> = 0); #endif // !defined(ASIO_NO_DEPRECATED) /// Establishes a socket connection by trying each endpoint in a sequence. @@ -311,8 +313,7 @@ template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type = 0); + constraint_t<is_endpoint_sequence<EndpointSequence>::value> = 0); /// Establishes a socket connection by trying each endpoint in a sequence. /** @@ -379,8 +380,7 @@ template <typename Protocol, typename Executor, typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, asio::error_code& ec, - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type = 0); + constraint_t<is_endpoint_sequence<EndpointSequence>::value> = 0); #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Establishes a socket connection by trying @@ -422,7 +422,7 @@ template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition, - typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); + constraint_t<!is_endpoint_sequence<Iterator>::value> = 0); /// (Deprecated: Use range overload.) Establishes a socket connection by trying /// each endpoint in a sequence. @@ -463,7 +463,7 @@ template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition, asio::error_code& ec, - typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); + constraint_t<!is_endpoint_sequence<Iterator>::value> = 0); #endif // !defined(ASIO_NO_DEPRECATED) /// Establishes a socket connection by trying each endpoint in a sequence. @@ -610,16 +610,19 @@ Iterator connect(basic_socket<Protocol, Executor>& s, * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection - * is successfully established. + * is successfully established. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed. * * @param endpoints A sequence of endpoints. * - * @param handler The handler to be called when the connect operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the connect completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the @@ -631,10 +634,13 @@ Iterator connect(basic_socket<Protocol, Executor>& s, * const typename Protocol::endpoint& endpoint * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, typename Protocol::endpoint) @endcode + * * @par Example * @code tcp::resolver r(my_context); * tcp::resolver::query q("host", "service"); @@ -677,16 +683,17 @@ Iterator connect(basic_socket<Protocol, Executor>& s, */ template <typename Protocol, typename Executor, typename EndpointSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - typename Protocol::endpoint)) RangeConnectHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> -ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler, - void (asio::error_code, typename Protocol::endpoint)) -async_connect(basic_socket<Protocol, Executor>& s, + typename Protocol::endpoint)) RangeConnectToken + = default_completion_token_t<Executor>> +auto async_connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, - ASIO_MOVE_ARG(RangeConnectHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(Executor), - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type = 0); + RangeConnectToken&& token = default_completion_token_t<Executor>(), + constraint_t<is_endpoint_sequence<EndpointSequence>::value> = 0) + -> decltype( + async_initiate<RangeConnectToken, + void (asio::error_code, typename Protocol::endpoint)>( + declval<detail::initiate_async_range_connect<Protocol, Executor>>(), + token, endpoints, declval<detail::default_connect_condition>())); #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Asynchronously establishes a socket @@ -695,16 +702,19 @@ async_connect(basic_socket<Protocol, Executor>& s, * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection - * is successfully established. + * is successfully established. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed. * * @param begin An iterator pointing to the start of a sequence of endpoints. * - * @param handler The handler to be called when the connect operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the connect completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the @@ -716,10 +726,13 @@ async_connect(basic_socket<Protocol, Executor>& s, * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, Iterator) @endcode + * * @note This overload assumes that a default constructed object of type @c * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c asio::ip::tcp::resolver::iterator. @@ -736,14 +749,16 @@ async_connect(basic_socket<Protocol, Executor>& s, */ template <typename Protocol, typename Executor, typename Iterator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - Iterator)) IteratorConnectHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> -ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, - void (asio::error_code, Iterator)) -async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, - ASIO_MOVE_ARG(IteratorConnectHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(Executor), - typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); + Iterator)) IteratorConnectToken = default_completion_token_t<Executor>> +auto async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, + IteratorConnectToken&& token = default_completion_token_t<Executor>(), + constraint_t<!is_endpoint_sequence<Iterator>::value> = 0) + -> decltype( + async_initiate<IteratorConnectToken, + void (asio::error_code, Iterator)>( + declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), + token, begin, Iterator(), + declval<detail::default_connect_condition>())); #endif // !defined(ASIO_NO_DEPRECATED) /// Asynchronously establishes a socket connection by trying each endpoint in a @@ -752,7 +767,8 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection - * is successfully established. + * is successfully established. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed. @@ -761,9 +777,11 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, * * @param end An iterator pointing to the end of a sequence of endpoints. * - * @param handler The handler to be called when the connect operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the connect completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the @@ -775,10 +793,13 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, Iterator) @endcode + * * @par Example * @code std::vector<tcp::endpoint> endpoints = ...; * tcp::socket s(my_context); @@ -807,13 +828,15 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, */ template <typename Protocol, typename Executor, typename Iterator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - Iterator)) IteratorConnectHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> -ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, - void (asio::error_code, Iterator)) -async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, - ASIO_MOVE_ARG(IteratorConnectHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(Executor)); + Iterator)) IteratorConnectToken = default_completion_token_t<Executor>> +auto async_connect( + basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, + IteratorConnectToken&& token = default_completion_token_t<Executor>()) + -> decltype( + async_initiate<IteratorConnectToken, + void (asio::error_code, Iterator)>( + declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), + token, begin, end, declval<detail::default_connect_condition>())); /// Asynchronously establishes a socket connection by trying each endpoint in a /// sequence. @@ -821,7 +844,8 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection - * is successfully established. + * is successfully established. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed. @@ -839,9 +863,11 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, * The function object should return true if the next endpoint should be tried, * and false if it should be skipped. * - * @param handler The handler to be called when the connect operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the connect completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the @@ -853,10 +879,13 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, typename Protocol::endpoint) @endcode + * * @par Example * The following connect condition function object can be used to output * information about the individual connection attempts: @@ -923,16 +952,17 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - typename Protocol::endpoint)) RangeConnectHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> -ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler, - void (asio::error_code, typename Protocol::endpoint)) -async_connect(basic_socket<Protocol, Executor>& s, + typename Protocol::endpoint)) RangeConnectToken + = default_completion_token_t<Executor>> +auto async_connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, - ASIO_MOVE_ARG(RangeConnectHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(Executor), - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type = 0); + RangeConnectToken&& token = default_completion_token_t<Executor>(), + constraint_t<is_endpoint_sequence<EndpointSequence>::value> = 0) + -> decltype( + async_initiate<RangeConnectToken, + void (asio::error_code, typename Protocol::endpoint)>( + declval<detail::initiate_async_range_connect<Protocol, Executor>>(), + token, endpoints, connect_condition)); #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Asynchronously establishes a socket @@ -941,7 +971,8 @@ async_connect(basic_socket<Protocol, Executor>& s, * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection - * is successfully established. + * is successfully established. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed. @@ -959,9 +990,11 @@ async_connect(basic_socket<Protocol, Executor>& s, * The function object should return true if the next endpoint should be tried, * and false if it should be skipped. * - * @param handler The handler to be called when the connect operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the connect completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the @@ -973,10 +1006,13 @@ async_connect(basic_socket<Protocol, Executor>& s, * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, Iterator) @endcode + * * @note This overload assumes that a default constructed object of type @c * Iterator represents the end of the sequence. This is a valid assumption for * iterator types such as @c asio::ip::tcp::resolver::iterator. @@ -994,15 +1030,16 @@ async_connect(basic_socket<Protocol, Executor>& s, template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - Iterator)) IteratorConnectHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> -ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, - void (asio::error_code, Iterator)) -async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, - ConnectCondition connect_condition, - ASIO_MOVE_ARG(IteratorConnectHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(Executor), - typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); + Iterator)) IteratorConnectToken = default_completion_token_t<Executor>> +auto async_connect(basic_socket<Protocol, Executor>& s, + Iterator begin, ConnectCondition connect_condition, + IteratorConnectToken&& token = default_completion_token_t<Executor>(), + constraint_t<!is_endpoint_sequence<Iterator>::value> = 0) + -> decltype( + async_initiate<IteratorConnectToken, + void (asio::error_code, Iterator)>( + declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), + token, begin, Iterator(), connect_condition)); #endif // !defined(ASIO_NO_DEPRECATED) /// Asynchronously establishes a socket connection by trying each endpoint in a @@ -1011,7 +1048,8 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, * This function attempts to connect a socket to one of a sequence of * endpoints. It does this by repeated calls to the socket's @c async_connect * member function, once for each endpoint in the sequence, until a connection - * is successfully established. + * is successfully established. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param s The socket to be connected. If the socket is already open, it will * be closed. @@ -1031,9 +1069,11 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, * The function object should return true if the next endpoint should be tried, * and false if it should be skipped. * - * @param handler The handler to be called when the connect operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the connect completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. if the sequence is empty, set to * // asio::error::not_found. Otherwise, contains the @@ -1045,10 +1085,13 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, * Iterator iterator * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, Iterator) @endcode + * * @par Example * The following connect condition function object can be used to output * information about the individual connection attempts: @@ -1116,14 +1159,15 @@ async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - Iterator)) IteratorConnectHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> -ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, - void (asio::error_code, Iterator)) -async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, - Iterator end, ConnectCondition connect_condition, - ASIO_MOVE_ARG(IteratorConnectHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(Executor)); + Iterator)) IteratorConnectToken = default_completion_token_t<Executor>> +auto async_connect(basic_socket<Protocol, Executor>& s, + Iterator begin, Iterator end, ConnectCondition connect_condition, + IteratorConnectToken&& token = default_completion_token_t<Executor>()) + -> decltype( + async_initiate<IteratorConnectToken, + void (asio::error_code, Iterator)>( + declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), + token, begin, end, connect_condition)); /*@}*/ diff --git a/3rdparty/asio/include/asio/connect_pipe.hpp b/3rdparty/asio/include/asio/connect_pipe.hpp new file mode 100644 index 00000000000..1c9eb79383f --- /dev/null +++ b/3rdparty/asio/include/asio/connect_pipe.hpp @@ -0,0 +1,83 @@ +// +// connect_pipe.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_CONNECT_PIPE_HPP +#define ASIO_CONNECT_PIPE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PIPE) \ + || defined(GENERATING_DOCUMENTATION) + +#include "asio/basic_readable_pipe.hpp" +#include "asio/basic_writable_pipe.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +#if defined(ASIO_HAS_IOCP) +typedef HANDLE native_pipe_handle; +#else // defined(ASIO_HAS_IOCP) +typedef int native_pipe_handle; +#endif // defined(ASIO_HAS_IOCP) + +ASIO_DECL void create_pipe(native_pipe_handle p[2], + asio::error_code& ec); + +ASIO_DECL void close_pipe(native_pipe_handle p); + +} // namespace detail + +/// Connect two pipe ends using an anonymous pipe. +/** + * @param read_end The read end of the pipe. + * + * @param write_end The write end of the pipe. + * + * @throws asio::system_error Thrown on failure. + */ +template <typename Executor1, typename Executor2> +void connect_pipe(basic_readable_pipe<Executor1>& read_end, + basic_writable_pipe<Executor2>& write_end); + +/// Connect two pipe ends using an anonymous pipe. +/** + * @param read_end The read end of the pipe. + * + * @param write_end The write end of the pipe. + * + * @throws asio::system_error Thrown on failure. + * + * @param ec Set to indicate what error occurred, if any. + */ +template <typename Executor1, typename Executor2> +ASIO_SYNC_OP_VOID connect_pipe(basic_readable_pipe<Executor1>& read_end, + basic_writable_pipe<Executor2>& write_end, asio::error_code& ec); + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/impl/connect_pipe.hpp" +#if defined(ASIO_HEADER_ONLY) +# include "asio/impl/connect_pipe.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +#endif // defined(ASIO_HAS_PIPE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_CONNECT_PIPE_HPP diff --git a/3rdparty/asio/include/asio/consign.hpp b/3rdparty/asio/include/asio/consign.hpp new file mode 100644 index 00000000000..4b0bc431309 --- /dev/null +++ b/3rdparty/asio/include/asio/consign.hpp @@ -0,0 +1,75 @@ +// +// consign.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_CONSIGN_HPP +#define ASIO_CONSIGN_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <tuple> +#include "asio/detail/type_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Completion token type used to specify that the completion handler should +/// carry additional values along with it. +/** + * This completion token adapter is typically used to keep at least one copy of + * an object, such as a smart pointer, alive until the completion handler is + * called. + */ +template <typename CompletionToken, typename... Values> +class consign_t +{ +public: + /// Constructor. + template <typename T, typename... V> + constexpr explicit consign_t(T&& completion_token, V&&... values) + : token_(static_cast<T&&>(completion_token)), + values_(static_cast<V&&>(values)...) + { + } + +#if defined(GENERATING_DOCUMENTATION) +private: +#endif // defined(GENERATING_DOCUMENTATION) + CompletionToken token_; + std::tuple<Values...> values_; +}; + +/// Completion token adapter used to specify that the completion handler should +/// carry additional values along with it. +/** + * This completion token adapter is typically used to keep at least one copy of + * an object, such as a smart pointer, alive until the completion handler is + * called. + */ +template <typename CompletionToken, typename... Values> +ASIO_NODISCARD inline constexpr +consign_t<decay_t<CompletionToken>, decay_t<Values>...> +consign(CompletionToken&& completion_token, Values&&... values) +{ + return consign_t<decay_t<CompletionToken>, decay_t<Values>...>( + static_cast<CompletionToken&&>(completion_token), + static_cast<Values&&>(values)...); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/impl/consign.hpp" + +#endif // ASIO_CONSIGN_HPP diff --git a/3rdparty/asio/include/asio/coroutine.hpp b/3rdparty/asio/include/asio/coroutine.hpp index bb0bdba8451..036e5148ad0 100644 --- a/3rdparty/asio/include/asio/coroutine.hpp +++ b/3rdparty/asio/include/asio/coroutine.hpp @@ -2,7 +2,7 @@ // coroutine.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -266,6 +266,7 @@ class coroutine_ref public: coroutine_ref(coroutine& c) : value_(c.value_), modified_(false) {} coroutine_ref(coroutine* c) : value_(c->value_), modified_(false) {} + coroutine_ref(const coroutine_ref&) = default; ~coroutine_ref() { if (!modified_) value_ = -1; } operator int() const { return value_; } int& operator=(int v) { modified_ = true; return value_ = v; } diff --git a/3rdparty/asio/include/asio/deadline_timer.hpp b/3rdparty/asio/include/asio/deadline_timer.hpp index 73872c8d357..dfa0b9ca169 100644 --- a/3rdparty/asio/include/asio/deadline_timer.hpp +++ b/3rdparty/asio/include/asio/deadline_timer.hpp @@ -2,7 +2,7 @@ // deadline_timer.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/defer.hpp b/3rdparty/asio/include/asio/defer.hpp index b0829e83848..608debe4d91 100644 --- a/3rdparty/asio/include/asio/defer.hpp +++ b/3rdparty/asio/include/asio/defer.hpp @@ -2,7 +2,7 @@ // defer.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,10 +17,13 @@ #include "asio/detail/config.hpp" #include "asio/async_result.hpp" +#include "asio/detail/initiate_defer.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution_context.hpp" +#include "asio/execution/blocking.hpp" #include "asio/execution/executor.hpp" #include "asio/is_executor.hpp" +#include "asio/require.hpp" #include "asio/detail/push_options.hpp" @@ -37,27 +40,53 @@ namespace asio { * may allow the executor to optimise queueing for cases when the function * object represents a continuation of the current call context. * - * This function has the following effects: + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Constructs a function object handler of type @c Handler, initialized - * with <tt>handler(forward<CompletionToken>(token))</tt>. + * @returns This function returns <tt>async_initiate<NullaryToken, + * void()>(Init{}, token)</tt>, where @c Init is a function object type defined + * as: * - * @li Constructs an object @c result of type <tt>async_result<Handler></tt>, - * initializing the object as <tt>result(handler)</tt>. + * @code class Init + * { + * public: + * template <typename CompletionHandler> + * void operator()(CompletionHandler&& completion_handler) const; + * }; @endcode * - * @li Obtains the handler's associated executor object @c ex by performing - * <tt>get_associated_executor(handler)</tt>. + * The function call operator of @c Init: * - * @li Obtains the handler's associated allocator object @c alloc by performing - * <tt>get_associated_allocator(handler)</tt>. - * - * @li Performs <tt>ex.defer(std::move(handler), alloc)</tt>. + * @li Obtains the handler's associated executor object @c ex of type @c Ex by + * performing @code auto ex = get_associated_executor(handler); @endcode * - * @li Returns <tt>result.get()</tt>. + * @li Obtains the handler's associated allocator object @c alloc by performing + * @code auto alloc = get_associated_allocator(handler); @endcode + * + * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs + * @code prefer( + * require(ex, execution::blocking.never), + * execution::relationship.continuation, + * execution::allocator(alloc) + * ).execute(std::forward<CompletionHandler>(completion_handler)); @endcode + * + * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs + * @code ex.defer( + * std::forward<CompletionHandler>(completion_handler), + * alloc); @endcode + * + * @par Completion Signature + * @code void() @endcode */ -template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( - ASIO_MOVE_ARG(CompletionToken) token); +template <ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken> +auto defer(NullaryToken&& token) + -> decltype( + async_initiate<NullaryToken, void()>( + declval<detail::initiate_defer>(), token)) +{ + return async_initiate<NullaryToken, void()>( + detail::initiate_defer(), token); +} /// Submits a completion token or function object for execution. /** @@ -70,61 +99,120 @@ ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( * may allow the executor to optimise queueing for cases when the function * object represents a continuation of the current call context. * - * This function has the following effects: + * @param ex The target executor. * - * @li Constructs a function object handler of type @c Handler, initialized - * with <tt>handler(forward<CompletionToken>(token))</tt>. + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Constructs an object @c result of type <tt>async_result<Handler></tt>, - * initializing the object as <tt>result(handler)</tt>. + * @returns This function returns <tt>async_initiate<NullaryToken, + * void()>(Init{ex}, token)</tt>, where @c Init is a function object type + * defined as: * - * @li Obtains the handler's associated executor object @c ex1 by performing - * <tt>get_associated_executor(handler)</tt>. - * - * @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>. + * @code class Init + * { + * public: + * using executor_type = Executor; + * explicit Init(const Executor& ex) : ex_(ex) {} + * executor_type get_executor() const noexcept { return ex_; } + * template <typename CompletionHandler> + * void operator()(CompletionHandler&& completion_handler) const; + * private: + * Executor ex_; // exposition only + * }; @endcode * - * @li 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>. + * The function call operator of @c Init: * - * @li Performs <tt>Executor(ex).defer(std::move(f), alloc)</tt>. + * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by + * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode * - * @li Returns <tt>result.get()</tt>. + * @li Obtains the handler's associated allocator object @c alloc by performing + * @code auto alloc = get_associated_allocator(handler); @endcode + * + * @li If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a + * function object @c f with a member @c executor_ that is initialised with + * <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c + * handler_ that is a decay-copy of @c completion_handler, and a function call + * operator that performs: + * @code auto a = get_associated_allocator(handler_); + * prefer(executor_, execution::allocator(a)).execute(std::move(handler_)); + * @endcode + * + * @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a + * function object @c f with a member @c work_ that is initialised with + * <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of + * @c completion_handler, and a function call operator that performs: + * @code auto a = get_associated_allocator(handler_); + * work_.get_executor().dispatch(std::move(handler_), a); + * work_.reset(); @endcode + * + * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs + * @code prefer( + * require(ex, execution::blocking.never), + * execution::relationship.continuation, + * execution::allocator(alloc) + * ).execute(std::move(f)); @endcode + * + * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs + * @code ex.defer(std::move(f), alloc); @endcode + * + * @par Completion Signature + * @code void() @endcode */ template <typename Executor, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( - const Executor& ex, - ASIO_MOVE_ARG(CompletionToken) token - ASIO_DEFAULT_COMPLETION_TOKEN(Executor), - typename constraint< - execution::is_executor<Executor>::value || is_executor<Executor>::value - >::type = 0); + ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken + = default_completion_token_t<Executor>> +auto defer(const Executor& ex, + NullaryToken&& token + = default_completion_token_t<Executor>(), + constraint_t< + (execution::is_executor<Executor>::value + && can_require<Executor, execution::blocking_t::never_t>::value) + || is_executor<Executor>::value + > = 0) + -> decltype( + async_initiate<NullaryToken, void()>( + declval<detail::initiate_defer_with_executor<Executor>>(), token)) +{ + return async_initiate<NullaryToken, void()>( + detail::initiate_defer_with_executor<Executor>(ex), token); +} /// Submits a completion token or function object for execution. /** - * @returns <tt>defer(ctx.get_executor(), forward<CompletionToken>(token))</tt>. + * @param ctx An execution context, from which the target executor is obtained. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode + * + * @returns <tt>defer(ctx.get_executor(), forward<NullaryToken>(token))</tt>. + * + * @par Completion Signature + * @code void() @endcode */ template <typename ExecutionContext, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename ExecutionContext::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( - ExecutionContext& ctx, - ASIO_MOVE_ARG(CompletionToken) token - ASIO_DEFAULT_COMPLETION_TOKEN( - typename ExecutionContext::executor_type), - typename constraint<is_convertible< - ExecutionContext&, execution_context&>::value>::type = 0); + ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken + = default_completion_token_t<typename ExecutionContext::executor_type>> +auto defer(ExecutionContext& ctx, + NullaryToken&& token + = default_completion_token_t<typename ExecutionContext::executor_type>(), + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) + -> decltype( + async_initiate<NullaryToken, void()>( + declval<detail::initiate_defer_with_executor< + typename ExecutionContext::executor_type>>(), token)) +{ + return async_initiate<NullaryToken, void()>( + detail::initiate_defer_with_executor< + typename ExecutionContext::executor_type>( + ctx.get_executor()), token); +} } // namespace asio #include "asio/detail/pop_options.hpp" -#include "asio/impl/defer.hpp" - #endif // ASIO_DEFER_HPP diff --git a/3rdparty/asio/include/asio/deferred.hpp b/3rdparty/asio/include/asio/deferred.hpp new file mode 100644 index 00000000000..b919f249553 --- /dev/null +++ b/3rdparty/asio/include/asio/deferred.hpp @@ -0,0 +1,715 @@ +// +// deferred.hpp +// ~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DEFERRED_HPP +#define ASIO_DEFERRED_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <tuple> +#include "asio/associator.hpp" +#include "asio/async_result.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/detail/utility.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Trait for detecting objects that are usable as deferred operations. +template <typename T> +struct is_deferred : false_type +{ +}; + +/// Helper type to wrap multiple completion signatures. +template <typename... Signatures> +struct deferred_signatures +{ +}; + +namespace detail { + +// Helper trait for getting the completion signatures of the tail in a sequence +// when invoked with the specified arguments. + +template <typename Tail, typename... Signatures> +struct deferred_sequence_signatures; + +template <typename Tail, typename R, typename... Args, typename... Signatures> +struct deferred_sequence_signatures<Tail, R(Args...), Signatures...> + : completion_signature_of<decltype(declval<Tail>()(declval<Args>()...))> +{ + static_assert( + !is_same<decltype(declval<Tail>()(declval<Args>()...)), void>::value, + "deferred functions must produce a deferred return type"); +}; + +// Completion handler for the head component of a deferred sequence. +template <typename Handler, typename Tail> +class deferred_sequence_handler +{ +public: + template <typename H, typename T> + explicit deferred_sequence_handler(H&& handler, T&& tail) + : handler_(static_cast<H&&>(handler)), + tail_(static_cast<T&&>(tail)) + { + } + + template <typename... Args> + void operator()(Args&&... args) + { + static_cast<Tail&&>(tail_)( + static_cast<Args&&>(args)...)( + static_cast<Handler&&>(handler_)); + } + +//private: + Handler handler_; + Tail tail_; +}; + +template <typename Head, typename Tail, typename... Signatures> +class deferred_sequence_base +{ +private: + struct initiate + { + template <typename Handler> + void operator()(Handler&& handler, Head head, Tail&& tail) + { + static_cast<Head&&>(head)( + deferred_sequence_handler<decay_t<Handler>, decay_t<Tail>>( + static_cast<Handler&&>(handler), static_cast<Tail&&>(tail))); + } + }; + + Head head_; + Tail tail_; + +public: + template <typename H, typename T> + constexpr explicit deferred_sequence_base(H&& head, T&& tail) + : head_(static_cast<H&&>(head)), + tail_(static_cast<T&&>(tail)) + { + } + + template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken> + auto operator()(CompletionToken&& token) && + -> decltype( + async_initiate<CompletionToken, Signatures...>( + initiate(), token, static_cast<Head&&>(this->head_), + static_cast<Tail&&>(this->tail_))) + { + return async_initiate<CompletionToken, Signatures...>(initiate(), + token, static_cast<Head&&>(head_), static_cast<Tail&&>(tail_)); + } + + template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken> + auto operator()(CompletionToken&& token) const & + -> decltype( + async_initiate<CompletionToken, Signatures...>( + initiate(), token, this->head_, this->tail_)) + { + return async_initiate<CompletionToken, Signatures...>( + initiate(), token, head_, tail_); + } +}; + +// Two-step application of variadic Signatures to determine correct base type. + +template <typename Head, typename Tail> +struct deferred_sequence_types +{ + template <typename... Signatures> + struct op1 + { + typedef deferred_sequence_base<Head, Tail, Signatures...> type; + }; + + template <typename... Signatures> + struct op2 + { + typedef typename deferred_sequence_signatures<Tail, Signatures...>::template + apply<op1>::type::type type; + }; + + typedef typename completion_signature_of<Head>::template + apply<op2>::type::type base; +}; + +} // namespace detail + +/// Used to represent an empty deferred action. +struct deferred_noop +{ + /// No effect. + template <typename... Args> + void operator()(Args&&...) && + { + } + + /// No effect. + template <typename... Args> + void operator()(Args&&...) const & + { + } +}; + +#if !defined(GENERATING_DOCUMENTATION) +template <> +struct is_deferred<deferred_noop> : true_type +{ +}; +#endif // !defined(GENERATING_DOCUMENTATION) + +/// Tag type to disambiguate deferred constructors. +struct deferred_init_tag {}; + +/// Wraps a function object so that it may be used as an element in a deferred +/// composition. +template <typename Function> +class deferred_function +{ +public: + /// Constructor. + template <typename F> + constexpr explicit deferred_function(deferred_init_tag, F&& function) + : function_(static_cast<F&&>(function)) + { + } + +//private: + Function function_; + +public: + template <typename... Args> + auto operator()(Args&&... args) && + -> decltype( + static_cast<Function&&>(this->function_)(static_cast<Args&&>(args)...)) + { + return static_cast<Function&&>(function_)(static_cast<Args&&>(args)...); + } + + template <typename... Args> + auto operator()(Args&&... args) const & + -> decltype(Function(function_)(static_cast<Args&&>(args)...)) + { + return Function(function_)(static_cast<Args&&>(args)...); + } +}; + +#if !defined(GENERATING_DOCUMENTATION) +template <typename Function> +struct is_deferred<deferred_function<Function>> : true_type +{ +}; +#endif // !defined(GENERATING_DOCUMENTATION) + +/// Encapsulates deferred values. +template <typename... Values> +class ASIO_NODISCARD deferred_values +{ +private: + std::tuple<Values...> values_; + + struct initiate + { + template <typename Handler, typename... V> + void operator()(Handler handler, V&&... values) + { + static_cast<Handler&&>(handler)(static_cast<V&&>(values)...); + } + }; + + template <typename CompletionToken, std::size_t... I> + auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>) + -> decltype( + async_initiate<CompletionToken, void(Values...)>(initiate(), token, + std::get<I>(static_cast<std::tuple<Values...>&&>(this->values_))...)) + { + return async_initiate<CompletionToken, void(Values...)>(initiate(), token, + std::get<I>(static_cast<std::tuple<Values...>&&>(values_))...); + } + + template <typename CompletionToken, std::size_t... I> + auto const_invoke_helper(CompletionToken&& token, + detail::index_sequence<I...>) + -> decltype( + async_initiate<CompletionToken, void(Values...)>( + initiate(), token, std::get<I>(values_)...)) + { + return async_initiate<CompletionToken, void(Values...)>( + initiate(), token, std::get<I>(values_)...); + } + +public: + /// Construct a deferred asynchronous operation from the arguments to an + /// initiation function object. + template <typename... V> + constexpr explicit deferred_values( + deferred_init_tag, V&&... values) + : values_(static_cast<V&&>(values)...) + { + } + + /// Initiate the deferred operation using the supplied completion token. + template <ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken> + auto operator()(CompletionToken&& token) && + -> decltype( + this->invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<Values...>())) + { + return this->invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<Values...>()); + } + + template <ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken> + auto operator()(CompletionToken&& token) const & + -> decltype( + this->const_invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<Values...>())) + { + return this->const_invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<Values...>()); + } +}; + +#if !defined(GENERATING_DOCUMENTATION) +template <typename... Values> +struct is_deferred<deferred_values<Values...>> : true_type +{ +}; +#endif // !defined(GENERATING_DOCUMENTATION) + +/// Encapsulates a deferred asynchronous operation. +template <typename Signature, typename Initiation, typename... InitArgs> +class ASIO_NODISCARD deferred_async_operation +{ +private: + typedef decay_t<Initiation> initiation_t; + initiation_t initiation_; + typedef std::tuple<decay_t<InitArgs>...> init_args_t; + init_args_t init_args_; + + template <typename CompletionToken, std::size_t... I> + auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>) + -> decltype( + async_initiate<CompletionToken, Signature>( + static_cast<initiation_t&&>(initiation_), token, + std::get<I>(static_cast<init_args_t&&>(init_args_))...)) + { + return async_initiate<CompletionToken, Signature>( + static_cast<initiation_t&&>(initiation_), token, + std::get<I>(static_cast<init_args_t&&>(init_args_))...); + } + + template <typename CompletionToken, std::size_t... I> + auto const_invoke_helper(CompletionToken&& token, + detail::index_sequence<I...>) const & + -> decltype( + async_initiate<CompletionToken, Signature>( + initiation_t(initiation_), token, std::get<I>(init_args_)...)) + { + return async_initiate<CompletionToken, Signature>( + initiation_t(initiation_), token, std::get<I>(init_args_)...); + } + +public: + /// Construct a deferred asynchronous operation from the arguments to an + /// initiation function object. + template <typename I, typename... A> + constexpr explicit deferred_async_operation( + deferred_init_tag, I&& initiation, A&&... init_args) + : initiation_(static_cast<I&&>(initiation)), + init_args_(static_cast<A&&>(init_args)...) + { + } + + /// Initiate the asynchronous operation using the supplied completion token. + template <ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken> + auto operator()(CompletionToken&& token) && + -> decltype( + this->invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<InitArgs...>())) + { + return this->invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<InitArgs...>()); + } + + template <ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken> + auto operator()(CompletionToken&& token) const & + -> decltype( + this->const_invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<InitArgs...>())) + { + return this->const_invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<InitArgs...>()); + } +}; + +/// Encapsulates a deferred asynchronous operation thas has multiple completion +/// signatures. +template <typename... Signatures, typename Initiation, typename... InitArgs> +class ASIO_NODISCARD deferred_async_operation< + deferred_signatures<Signatures...>, Initiation, InitArgs...> +{ +private: + typedef decay_t<Initiation> initiation_t; + initiation_t initiation_; + typedef std::tuple<decay_t<InitArgs>...> init_args_t; + init_args_t init_args_; + + template <typename CompletionToken, std::size_t... I> + auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>) + -> decltype( + async_initiate<CompletionToken, Signatures...>( + static_cast<initiation_t&&>(initiation_), token, + std::get<I>(static_cast<init_args_t&&>(init_args_))...)) + { + return async_initiate<CompletionToken, Signatures...>( + static_cast<initiation_t&&>(initiation_), token, + std::get<I>(static_cast<init_args_t&&>(init_args_))...); + } + + template <typename CompletionToken, std::size_t... I> + auto const_invoke_helper(CompletionToken&& token, + detail::index_sequence<I...>) const & + -> decltype( + async_initiate<CompletionToken, Signatures...>( + initiation_t(initiation_), token, std::get<I>(init_args_)...)) + { + return async_initiate<CompletionToken, Signatures...>( + initiation_t(initiation_), token, std::get<I>(init_args_)...); + } + +public: + /// Construct a deferred asynchronous operation from the arguments to an + /// initiation function object. + template <typename I, typename... A> + constexpr explicit deferred_async_operation( + deferred_init_tag, I&& initiation, A&&... init_args) + : initiation_(static_cast<I&&>(initiation)), + init_args_(static_cast<A&&>(init_args)...) + { + } + + /// Initiate the asynchronous operation using the supplied completion token. + template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken> + auto operator()(CompletionToken&& token) && + -> decltype( + this->invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<InitArgs...>())) + { + return this->invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<InitArgs...>()); + } + + template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken> + auto operator()(CompletionToken&& token) const & + -> decltype( + this->const_invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<InitArgs...>())) + { + return this->const_invoke_helper( + static_cast<CompletionToken&&>(token), + detail::index_sequence_for<InitArgs...>()); + } +}; + +#if !defined(GENERATING_DOCUMENTATION) +template <typename Signature, typename Initiation, typename... InitArgs> +struct is_deferred< + deferred_async_operation<Signature, Initiation, InitArgs...>> : true_type +{ +}; +#endif // !defined(GENERATING_DOCUMENTATION) + +/// Defines a link between two consecutive operations in a sequence. +template <typename Head, typename Tail> +class ASIO_NODISCARD deferred_sequence : + public detail::deferred_sequence_types<Head, Tail>::base +{ +public: + template <typename H, typename T> + constexpr explicit deferred_sequence(deferred_init_tag, H&& head, T&& tail) + : detail::deferred_sequence_types<Head, Tail>::base( + static_cast<H&&>(head), static_cast<T&&>(tail)) + { + } + +#if defined(GENERATING_DOCUMENTATION) + template <typename CompletionToken> + auto operator()(CompletionToken&& token) &&; + + template <typename CompletionToken> + auto operator()(CompletionToken&& token) const &; +#endif // defined(GENERATING_DOCUMENTATION) +}; + +#if !defined(GENERATING_DOCUMENTATION) +template <typename Head, typename Tail> +struct is_deferred<deferred_sequence<Head, Tail>> : true_type +{ +}; +#endif // !defined(GENERATING_DOCUMENTATION) + +/// Used to represent a deferred conditional branch. +template <typename OnTrue = deferred_noop, typename OnFalse = deferred_noop> +class ASIO_NODISCARD deferred_conditional +{ +private: + template <typename T, typename F> friend class deferred_conditional; + + // Helper constructor. + template <typename T, typename F> + explicit deferred_conditional(bool b, T&& on_true, F&& on_false) + : on_true_(static_cast<T&&>(on_true)), + on_false_(static_cast<F&&>(on_false)), + bool_(b) + { + } + + OnTrue on_true_; + OnFalse on_false_; + bool bool_; + +public: + /// Construct a deferred conditional with the value to determine which branch + /// will be executed. + constexpr explicit deferred_conditional(bool b) + : on_true_(), + on_false_(), + bool_(b) + { + } + + /// Invoke the conditional branch bsaed on the stored value. + template <typename... Args> + auto operator()(Args&&... args) && + -> decltype(static_cast<OnTrue&&>(on_true_)(static_cast<Args&&>(args)...)) + { + if (bool_) + { + return static_cast<OnTrue&&>(on_true_)(static_cast<Args&&>(args)...); + } + else + { + return static_cast<OnFalse&&>(on_false_)(static_cast<Args&&>(args)...); + } + } + + template <typename... Args> + auto operator()(Args&&... args) const & + -> decltype(on_true_(static_cast<Args&&>(args)...)) + { + if (bool_) + { + return on_true_(static_cast<Args&&>(args)...); + } + else + { + return on_false_(static_cast<Args&&>(args)...); + } + } + + /// Set the true branch of the conditional. + template <typename T> + deferred_conditional<T, OnFalse> then(T on_true, + constraint_t< + is_deferred<T>::value + >* = 0, + constraint_t< + is_same< + conditional_t<true, OnTrue, T>, + deferred_noop + >::value + >* = 0) && + { + return deferred_conditional<T, OnFalse>( + bool_, static_cast<T&&>(on_true), + static_cast<OnFalse&&>(on_false_)); + } + + /// Set the false branch of the conditional. + template <typename T> + deferred_conditional<OnTrue, T> otherwise(T on_false, + constraint_t< + is_deferred<T>::value + >* = 0, + constraint_t< + !is_same< + conditional_t<true, OnTrue, T>, + deferred_noop + >::value + >* = 0, + constraint_t< + is_same< + conditional_t<true, OnFalse, T>, + deferred_noop + >::value + >* = 0) && + { + return deferred_conditional<OnTrue, T>( + bool_, static_cast<OnTrue&&>(on_true_), + static_cast<T&&>(on_false)); + } +}; + +#if !defined(GENERATING_DOCUMENTATION) +template <typename OnTrue, typename OnFalse> +struct is_deferred<deferred_conditional<OnTrue, OnFalse>> : true_type +{ +}; +#endif // !defined(GENERATING_DOCUMENTATION) + +/// Class used to specify that an asynchronous operation should return a +/// function object to lazily launch the operation. +/** + * The deferred_t class is used to indicate that an asynchronous operation + * should return a function object which is itself an initiation function. A + * deferred_t object may be passed as a completion token to an asynchronous + * operation, typically using the special value @c asio::deferred. For + * example: + * + * @code auto my_deferred_op + * = my_socket.async_read_some(my_buffer, + * asio::deferred); @endcode + * + * The initiating function (async_read_some in the above example) returns a + * function object that will lazily initiate the operation. + */ +class deferred_t +{ +public: + /// Default constructor. + constexpr deferred_t() + { + } + + /// Adapts an executor to add the @c deferred_t completion token as the + /// default. + template <typename InnerExecutor> + struct executor_with_default : InnerExecutor + { + /// Specify @c deferred_t as the default completion token type. + typedef deferred_t default_completion_token_type; + + /// Construct the adapted executor from the inner executor type. + template <typename InnerExecutor1> + executor_with_default(const InnerExecutor1& ex, + constraint_t< + conditional_t< + !is_same<InnerExecutor1, executor_with_default>::value, + is_convertible<InnerExecutor1, InnerExecutor>, + false_type + >::value + > = 0) noexcept + : InnerExecutor(ex) + { + } + }; + + /// Type alias to adapt an I/O object to use @c deferred_t as its + /// default completion token type. + template <typename T> + using as_default_on_t = typename T::template rebind_executor< + executor_with_default<typename T::executor_type>>::other; + + /// Function helper to adapt an I/O object to use @c deferred_t as its + /// default completion token type. + template <typename T> + static typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> + >::other + as_default_on(T&& object) + { + return typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> + >::other(static_cast<T&&>(object)); + } + + /// Creates a new deferred from a function. + template <typename Function> + constraint_t< + !is_deferred<decay_t<Function>>::value, + deferred_function<decay_t<Function>> + > operator()(Function&& function) const + { + return deferred_function<decay_t<Function>>( + deferred_init_tag{}, static_cast<Function&&>(function)); + } + + /// Passes through anything that is already deferred. + template <typename T> + constraint_t< + is_deferred<decay_t<T>>::value, + decay_t<T> + > operator()(T&& t) const + { + return static_cast<T&&>(t); + } + + /// Returns a deferred operation that returns the provided values. + template <typename... Args> + static constexpr deferred_values<decay_t<Args>...> values(Args&&... args) + { + return deferred_values<decay_t<Args>...>( + deferred_init_tag{}, static_cast<Args&&>(args)...); + } + + /// Creates a conditional object for branching deferred operations. + static constexpr deferred_conditional<> when(bool b) + { + return deferred_conditional<>(b); + } +}; + +/// Pipe operator used to chain deferred operations. +template <typename Head, typename Tail> +inline auto operator|(Head head, Tail&& tail) + -> constraint_t< + is_deferred<Head>::value, + decltype(static_cast<Head&&>(head)(static_cast<Tail&&>(tail))) + > +{ + return static_cast<Head&&>(head)(static_cast<Tail&&>(tail)); +} + +/// A @ref completion_token object used to specify that an asynchronous +/// operation should return a function object to lazily launch the operation. +/** + * See the documentation for asio::deferred_t for a usage example. + */ +constexpr deferred_t deferred; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/impl/deferred.hpp" + +#endif // ASIO_DEFERRED_HPP diff --git a/3rdparty/asio/include/asio/detached.hpp b/3rdparty/asio/include/asio/detached.hpp index e99875e36d7..b71bd9d978b 100644 --- a/3rdparty/asio/include/asio/detached.hpp +++ b/3rdparty/asio/include/asio/detached.hpp @@ -2,7 +2,7 @@ // detached.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,15 +23,15 @@ namespace asio { -/// Class used to specify that an asynchronous operation is detached. +/// A @ref completion_token type used to specify that an asynchronous operation +/// is detached. /** - * The detached_t class is used to indicate that an asynchronous operation is * detached. That is, there is no completion handler waiting for the * operation's result. A detached_t object may be passed as a handler to an * asynchronous operation, typically using the special value * @c asio::detached. For example: - + * * @code my_socket.async_send(my_buffer, asio::detached); * @endcode */ @@ -39,7 +39,7 @@ class detached_t { public: /// Constructor. - ASIO_CONSTEXPR detached_t() + constexpr detached_t() { } @@ -52,7 +52,7 @@ public: typedef detached_t default_completion_token_type; /// Construct the adapted executor from the inner executor type. - executor_with_default(const InnerExecutor& ex) ASIO_NOEXCEPT + executor_with_default(const InnerExecutor& ex) noexcept : InnerExecutor(ex) { } @@ -61,9 +61,9 @@ public: /// that to construct the adapted executor. template <typename OtherExecutor> executor_with_default(const OtherExecutor& ex, - typename constraint< + constraint_t< is_convertible<OtherExecutor, InnerExecutor>::value - >::type = 0) ASIO_NOEXCEPT + > = 0) noexcept : InnerExecutor(ex) { } @@ -71,37 +71,30 @@ public: /// Type alias to adapt an I/O object to use @c detached_t as its /// default completion token type. -#if defined(ASIO_HAS_ALIAS_TEMPLATES) \ - || defined(GENERATING_DOCUMENTATION) template <typename T> using as_default_on_t = typename T::template rebind_executor< - executor_with_default<typename T::executor_type> >::other; -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) + executor_with_default<typename T::executor_type>>::other; /// Function helper to adapt an I/O object to use @c detached_t as its /// default completion token type. template <typename T> - static typename decay<T>::type::template rebind_executor< - executor_with_default<typename decay<T>::type::executor_type> + static typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> >::other - as_default_on(ASIO_MOVE_ARG(T) object) + as_default_on(T&& object) { - return typename decay<T>::type::template rebind_executor< - executor_with_default<typename decay<T>::type::executor_type> - >::other(ASIO_MOVE_CAST(T)(object)); + return typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> + >::other(static_cast<T&&>(object)); } }; -/// A special value, similar to std::nothrow. +/// A @ref completion_token object used to specify that an asynchronous +/// operation is detached. /** * See the documentation for asio::detached_t for a usage example. */ -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr detached_t detached; -#elif defined(ASIO_MSVC) -__declspec(selectany) detached_t detached; -#endif } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/array.hpp b/3rdparty/asio/include/asio/detail/array.hpp index ef230c321ca..f2015c7919b 100644 --- a/3rdparty/asio/include/asio/detail/array.hpp +++ b/3rdparty/asio/include/asio/detail/array.hpp @@ -2,7 +2,7 @@ // detail/array.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,20 +17,12 @@ #include "asio/detail/config.hpp" -#if defined(ASIO_HAS_STD_ARRAY) -# include <array> -#else // defined(ASIO_HAS_STD_ARRAY) -# include <boost/array.hpp> -#endif // defined(ASIO_HAS_STD_ARRAY) +#include <array> namespace asio { namespace detail { -#if defined(ASIO_HAS_STD_ARRAY) using std::array; -#else // defined(ASIO_HAS_STD_ARRAY) -using boost::array; -#endif // defined(ASIO_HAS_STD_ARRAY) } // namespace detail } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/array_fwd.hpp b/3rdparty/asio/include/asio/detail/array_fwd.hpp index fb81dba5ce2..79491348a69 100644 --- a/3rdparty/asio/include/asio/detail/array_fwd.hpp +++ b/3rdparty/asio/include/asio/detail/array_fwd.hpp @@ -2,7 +2,7 @@ // detail/array_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -27,8 +27,6 @@ class array; // Standard library components can't be forward declared, so we'll have to // include the array header. Fortunately, it's fairly lightweight and doesn't // add significantly to the compile time. -#if defined(ASIO_HAS_STD_ARRAY) -# include <array> -#endif // defined(ASIO_HAS_STD_ARRAY) +#include <array> #endif // ASIO_DETAIL_ARRAY_FWD_HPP diff --git a/3rdparty/asio/include/asio/detail/assert.hpp b/3rdparty/asio/include/asio/detail/assert.hpp index 8eaf59530bc..b53774d9aff 100644 --- a/3rdparty/asio/include/asio/detail/assert.hpp +++ b/3rdparty/asio/include/asio/detail/assert.hpp @@ -2,7 +2,7 @@ // detail/assert.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/atomic_count.hpp b/3rdparty/asio/include/asio/detail/atomic_count.hpp index 8409298a9af..6116279c89e 100644 --- a/3rdparty/asio/include/asio/detail/atomic_count.hpp +++ b/3rdparty/asio/include/asio/detail/atomic_count.hpp @@ -2,7 +2,7 @@ // detail/atomic_count.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,11 +19,9 @@ #if !defined(ASIO_HAS_THREADS) // Nothing to include. -#elif defined(ASIO_HAS_STD_ATOMIC) +#else // !defined(ASIO_HAS_THREADS) # include <atomic> -#else // defined(ASIO_HAS_STD_ATOMIC) -# include <boost/detail/atomic_count.hpp> -#endif // defined(ASIO_HAS_STD_ATOMIC) +#endif // !defined(ASIO_HAS_THREADS) namespace asio { namespace detail { @@ -31,11 +29,13 @@ namespace detail { #if !defined(ASIO_HAS_THREADS) typedef long atomic_count; inline void increment(atomic_count& a, long b) { a += b; } +inline void decrement(atomic_count& a, long b) { a -= b; } inline void ref_count_up(atomic_count& a) { ++a; } inline bool ref_count_down(atomic_count& a) { return --a == 0; } -#elif defined(ASIO_HAS_STD_ATOMIC) +#else // !defined(ASIO_HAS_THREADS) typedef std::atomic<long> atomic_count; inline void increment(atomic_count& a, long b) { a += b; } +inline void decrement(atomic_count& a, long b) { a -= b; } inline void ref_count_up(atomic_count& a) { @@ -51,12 +51,7 @@ inline bool ref_count_down(atomic_count& a) } return false; } -#else // defined(ASIO_HAS_STD_ATOMIC) -typedef boost::detail::atomic_count atomic_count; -inline void increment(atomic_count& a, long b) { while (b > 0) ++a, --b; } -inline void ref_count_up(atomic_count& a) { ++a; } -inline bool ref_count_down(atomic_count& a) { return --a == 0; } -#endif // defined(ASIO_HAS_STD_ATOMIC) +#endif // !defined(ASIO_HAS_THREADS) } // namespace detail } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/base_from_cancellation_state.hpp b/3rdparty/asio/include/asio/detail/base_from_cancellation_state.hpp index ae8db1764b1..3ce7dcf0b7f 100644 --- a/3rdparty/asio/include/asio/detail/base_from_cancellation_state.hpp +++ b/3rdparty/asio/include/asio/detail/base_from_cancellation_state.hpp @@ -2,7 +2,7 @@ // detail/base_from_cancellation_state.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -31,12 +31,12 @@ class base_from_cancellation_state public: typedef cancellation_slot cancellation_slot_type; - cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT + cancellation_slot_type get_cancellation_slot() const noexcept { return cancellation_state_.slot(); } - cancellation_state get_cancellation_state() const ASIO_NOEXCEPT + cancellation_state get_cancellation_state() const noexcept { return cancellation_state_; } @@ -57,12 +57,12 @@ protected: template <typename InFilter, typename OutFilter> base_from_cancellation_state(const Handler& handler, - ASIO_MOVE_ARG(InFilter) in_filter, - ASIO_MOVE_ARG(OutFilter) out_filter) + InFilter&& in_filter, + OutFilter&& out_filter) : cancellation_state_( asio::get_associated_cancellation_slot(handler), - ASIO_MOVE_CAST(InFilter)(in_filter), - ASIO_MOVE_CAST(OutFilter)(out_filter)) + static_cast<InFilter&&>(in_filter), + static_cast<OutFilter&&>(out_filter)) { } @@ -81,16 +81,16 @@ protected: template <typename InFilter, typename OutFilter> void reset_cancellation_state(const Handler& handler, - ASIO_MOVE_ARG(InFilter) in_filter, - ASIO_MOVE_ARG(OutFilter) out_filter) + InFilter&& in_filter, + OutFilter&& out_filter) { cancellation_state_ = cancellation_state( asio::get_associated_cancellation_slot(handler), - ASIO_MOVE_CAST(InFilter)(in_filter), - ASIO_MOVE_CAST(OutFilter)(out_filter)); + static_cast<InFilter&&>(in_filter), + static_cast<OutFilter&&>(out_filter)); } - cancellation_type_t cancelled() const ASIO_NOEXCEPT + cancellation_type_t cancelled() const noexcept { return cancellation_state_.cancelled(); } @@ -101,17 +101,18 @@ private: template <typename Handler> class base_from_cancellation_state<Handler, - typename enable_if< + enable_if_t< is_same< typename associated_cancellation_slot< Handler, cancellation_slot >::asio_associated_cancellation_slot_is_unspecialised, void >::value - >::type> + > + > { public: - cancellation_state get_cancellation_state() const ASIO_NOEXCEPT + cancellation_state get_cancellation_state() const noexcept { return cancellation_state(); } @@ -128,8 +129,8 @@ protected: template <typename InFilter, typename OutFilter> base_from_cancellation_state(const Handler&, - ASIO_MOVE_ARG(InFilter), - ASIO_MOVE_ARG(OutFilter)) + InFilter&&, + OutFilter&&) { } @@ -144,12 +145,12 @@ protected: template <typename InFilter, typename OutFilter> void reset_cancellation_state(const Handler&, - ASIO_MOVE_ARG(InFilter), - ASIO_MOVE_ARG(OutFilter)) + InFilter&&, + OutFilter&&) { } - ASIO_CONSTEXPR cancellation_type_t cancelled() const ASIO_NOEXCEPT + constexpr cancellation_type_t cancelled() const noexcept { return cancellation_type::none; } diff --git a/3rdparty/asio/include/asio/detail/base_from_completion_cond.hpp b/3rdparty/asio/include/asio/detail/base_from_completion_cond.hpp index 0139d261237..ba0cc879602 100644 --- a/3rdparty/asio/include/asio/detail/base_from_completion_cond.hpp +++ b/3rdparty/asio/include/asio/detail/base_from_completion_cond.hpp @@ -2,7 +2,7 @@ // detail/base_from_completion_cond.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -29,7 +29,7 @@ class base_from_completion_cond protected: explicit base_from_completion_cond(CompletionCondition& completion_condition) : completion_condition_( - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)) + static_cast<CompletionCondition&&>(completion_condition)) { } diff --git a/3rdparty/asio/include/asio/detail/bind_handler.hpp b/3rdparty/asio/include/asio/detail/bind_handler.hpp index 40f30f14ff4..3c16b13a458 100644 --- a/3rdparty/asio/include/asio/detail/bind_handler.hpp +++ b/3rdparty/asio/include/asio/detail/bind_handler.hpp @@ -2,7 +2,7 @@ // detail/bind_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,9 +17,7 @@ #include "asio/detail/config.hpp" #include "asio/associator.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/type_traits.hpp" #include "asio/detail/push_options.hpp" @@ -32,31 +30,29 @@ class binder0 { public: template <typename T> - binder0(int, ASIO_MOVE_ARG(T) handler) - : handler_(ASIO_MOVE_CAST(T)(handler)) + binder0(int, T&& handler) + : handler_(static_cast<T&&>(handler)) { } binder0(Handler& handler) - : handler_(ASIO_MOVE_CAST(Handler)(handler)) + : handler_(static_cast<Handler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) binder0(const binder0& other) : handler_(other.handler_) { } binder0(binder0&& other) - : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)) + : handler_(static_cast<Handler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()() { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)(); + static_cast<Handler&&>(handler_)(); } void operator()() const @@ -69,32 +65,6 @@ public: }; template <typename Handler> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - binder0<Handler>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - binder0<Handler>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> inline bool asio_handler_is_continuation( binder0<Handler>* this_handler) { @@ -102,36 +72,12 @@ inline bool asio_handler_is_continuation( this_handler->handler_); } -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - binder0<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - binder0<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - template <typename Handler> -inline binder0<typename decay<Handler>::type> bind_handler( - ASIO_MOVE_ARG(Handler) handler) +inline binder0<decay_t<Handler>> bind_handler( + Handler&& handler) { - return binder0<typename decay<Handler>::type>( - 0, ASIO_MOVE_CAST(Handler)(handler)); + return binder0<decay_t<Handler>>( + 0, static_cast<Handler&&>(handler)); } template <typename Handler, typename Arg1> @@ -139,19 +85,18 @@ class binder1 { public: template <typename T> - binder1(int, ASIO_MOVE_ARG(T) handler, const Arg1& arg1) - : handler_(ASIO_MOVE_CAST(T)(handler)), + binder1(int, T&& handler, const Arg1& arg1) + : handler_(static_cast<T&&>(handler)), arg1_(arg1) { } binder1(Handler& handler, const Arg1& arg1) - : handler_(ASIO_MOVE_CAST(Handler)(handler)), + : handler_(static_cast<Handler&&>(handler)), arg1_(arg1) { } -#if defined(ASIO_HAS_MOVE) binder1(const binder1& other) : handler_(other.handler_), arg1_(other.arg1_) @@ -159,15 +104,14 @@ public: } binder1(binder1&& other) - : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)), - arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)) + : handler_(static_cast<Handler&&>(other.handler_)), + arg1_(static_cast<Arg1&&>(other.arg1_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()() { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( + static_cast<Handler&&>(handler_)( static_cast<const Arg1&>(arg1_)); } @@ -182,32 +126,6 @@ public: }; template <typename Handler, typename Arg1> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - binder1<Handler, Arg1>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - binder1<Handler, Arg1>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1> inline bool asio_handler_is_continuation( binder1<Handler, Arg1>* this_handler) { @@ -215,36 +133,12 @@ inline bool asio_handler_is_continuation( this_handler->handler_); } -template <typename Function, typename Handler, typename Arg1> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - binder1<Handler, Arg1>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler, typename Arg1> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - binder1<Handler, Arg1>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - template <typename Handler, typename Arg1> -inline binder1<typename decay<Handler>::type, Arg1> bind_handler( - ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1) +inline binder1<decay_t<Handler>, Arg1> bind_handler( + Handler&& handler, const Arg1& arg1) { - return binder1<typename decay<Handler>::type, Arg1>(0, - ASIO_MOVE_CAST(Handler)(handler), arg1); + return binder1<decay_t<Handler>, Arg1>(0, + static_cast<Handler&&>(handler), arg1); } template <typename Handler, typename Arg1, typename Arg2> @@ -252,22 +146,21 @@ class binder2 { public: template <typename T> - binder2(int, ASIO_MOVE_ARG(T) handler, + binder2(int, T&& handler, const Arg1& arg1, const Arg2& arg2) - : handler_(ASIO_MOVE_CAST(T)(handler)), + : handler_(static_cast<T&&>(handler)), arg1_(arg1), arg2_(arg2) { } binder2(Handler& handler, const Arg1& arg1, const Arg2& arg2) - : handler_(ASIO_MOVE_CAST(Handler)(handler)), + : handler_(static_cast<Handler&&>(handler)), arg1_(arg1), arg2_(arg2) { } -#if defined(ASIO_HAS_MOVE) binder2(const binder2& other) : handler_(other.handler_), arg1_(other.arg1_), @@ -276,16 +169,15 @@ public: } binder2(binder2&& other) - : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)), - arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)), - arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_)) + : handler_(static_cast<Handler&&>(other.handler_)), + arg1_(static_cast<Arg1&&>(other.arg1_)), + arg2_(static_cast<Arg2&&>(other.arg2_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()() { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( + static_cast<Handler&&>(handler_)( static_cast<const Arg1&>(arg1_), static_cast<const Arg2&>(arg2_)); } @@ -302,32 +194,6 @@ public: }; template <typename Handler, typename Arg1, typename Arg2> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - binder2<Handler, Arg1, Arg2>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1, typename Arg2> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - binder2<Handler, Arg1, Arg2>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1, typename Arg2> inline bool asio_handler_is_continuation( binder2<Handler, Arg1, Arg2>* this_handler) { @@ -335,36 +201,12 @@ inline bool asio_handler_is_continuation( this_handler->handler_); } -template <typename Function, typename Handler, typename Arg1, typename Arg2> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - binder2<Handler, Arg1, Arg2>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler, typename Arg1, typename Arg2> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - binder2<Handler, Arg1, Arg2>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - template <typename Handler, typename Arg1, typename Arg2> -inline binder2<typename decay<Handler>::type, Arg1, Arg2> bind_handler( - ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1, const Arg2& arg2) +inline binder2<decay_t<Handler>, Arg1, Arg2> bind_handler( + Handler&& handler, const Arg1& arg1, const Arg2& arg2) { - return binder2<typename decay<Handler>::type, Arg1, Arg2>(0, - ASIO_MOVE_CAST(Handler)(handler), arg1, arg2); + return binder2<decay_t<Handler>, Arg1, Arg2>(0, + static_cast<Handler&&>(handler), arg1, arg2); } template <typename Handler, typename Arg1, typename Arg2, typename Arg3> @@ -372,9 +214,9 @@ class binder3 { public: template <typename T> - binder3(int, ASIO_MOVE_ARG(T) handler, const Arg1& arg1, + binder3(int, T&& handler, const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) - : handler_(ASIO_MOVE_CAST(T)(handler)), + : handler_(static_cast<T&&>(handler)), arg1_(arg1), arg2_(arg2), arg3_(arg3) @@ -383,14 +225,13 @@ public: binder3(Handler& handler, const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) - : handler_(ASIO_MOVE_CAST(Handler)(handler)), + : handler_(static_cast<Handler&&>(handler)), arg1_(arg1), arg2_(arg2), arg3_(arg3) { } -#if defined(ASIO_HAS_MOVE) binder3(const binder3& other) : handler_(other.handler_), arg1_(other.arg1_), @@ -400,17 +241,16 @@ public: } binder3(binder3&& other) - : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)), - arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)), - arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_)), - arg3_(ASIO_MOVE_CAST(Arg3)(other.arg3_)) + : handler_(static_cast<Handler&&>(other.handler_)), + arg1_(static_cast<Arg1&&>(other.arg1_)), + arg2_(static_cast<Arg2&&>(other.arg2_)), + arg3_(static_cast<Arg3&&>(other.arg3_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()() { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( + static_cast<Handler&&>(handler_)( static_cast<const Arg1&>(arg1_), static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_)); @@ -429,32 +269,6 @@ public: }; template <typename Handler, typename Arg1, typename Arg2, typename Arg3> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - binder3<Handler, Arg1, Arg2, Arg3>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1, typename Arg2, typename Arg3> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - binder3<Handler, Arg1, Arg2, Arg3>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1, typename Arg2, typename Arg3> inline bool asio_handler_is_continuation( binder3<Handler, Arg1, Arg2, Arg3>* this_handler) { @@ -462,39 +276,13 @@ inline bool asio_handler_is_continuation( this_handler->handler_); } -template <typename Function, typename Handler, - typename Arg1, typename Arg2, typename Arg3> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - binder3<Handler, Arg1, Arg2, Arg3>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler, - typename Arg1, typename Arg2, typename Arg3> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - binder3<Handler, Arg1, Arg2, Arg3>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - template <typename Handler, typename Arg1, typename Arg2, typename Arg3> -inline binder3<typename decay<Handler>::type, Arg1, Arg2, Arg3> bind_handler( - ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1, const Arg2& arg2, +inline binder3<decay_t<Handler>, Arg1, Arg2, Arg3> bind_handler( + Handler&& handler, const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) { - return binder3<typename decay<Handler>::type, Arg1, Arg2, Arg3>(0, - ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3); + return binder3<decay_t<Handler>, Arg1, Arg2, Arg3>(0, + static_cast<Handler&&>(handler), arg1, arg2, arg3); } template <typename Handler, typename Arg1, @@ -503,9 +291,9 @@ class binder4 { public: template <typename T> - binder4(int, ASIO_MOVE_ARG(T) handler, const Arg1& arg1, + binder4(int, T&& handler, const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4) - : handler_(ASIO_MOVE_CAST(T)(handler)), + : handler_(static_cast<T&&>(handler)), arg1_(arg1), arg2_(arg2), arg3_(arg3), @@ -515,7 +303,7 @@ public: binder4(Handler& handler, const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4) - : handler_(ASIO_MOVE_CAST(Handler)(handler)), + : handler_(static_cast<Handler&&>(handler)), arg1_(arg1), arg2_(arg2), arg3_(arg3), @@ -523,7 +311,6 @@ public: { } -#if defined(ASIO_HAS_MOVE) binder4(const binder4& other) : handler_(other.handler_), arg1_(other.arg1_), @@ -534,18 +321,17 @@ public: } binder4(binder4&& other) - : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)), - arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)), - arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_)), - arg3_(ASIO_MOVE_CAST(Arg3)(other.arg3_)), - arg4_(ASIO_MOVE_CAST(Arg4)(other.arg4_)) + : handler_(static_cast<Handler&&>(other.handler_)), + arg1_(static_cast<Arg1&&>(other.arg1_)), + arg2_(static_cast<Arg2&&>(other.arg2_)), + arg3_(static_cast<Arg3&&>(other.arg3_)), + arg4_(static_cast<Arg4&&>(other.arg4_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()() { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( + static_cast<Handler&&>(handler_)( static_cast<const Arg1&>(arg1_), static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_), @@ -567,34 +353,6 @@ public: template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1, - typename Arg2, typename Arg3, typename Arg4> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1, - typename Arg2, typename Arg3, typename Arg4> inline bool asio_handler_is_continuation( binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) { @@ -602,40 +360,14 @@ inline bool asio_handler_is_continuation( this_handler->handler_); } -template <typename Function, typename Handler, typename Arg1, - typename Arg2, typename Arg3, typename Arg4> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler, typename Arg1, - typename Arg2, typename Arg3, typename Arg4> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4> -inline binder4<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4> -bind_handler(ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1, +inline binder4<decay_t<Handler>, Arg1, Arg2, Arg3, Arg4> +bind_handler(Handler&& handler, const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4) { - return binder4<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4>(0, - ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3, arg4); + return binder4<decay_t<Handler>, Arg1, Arg2, Arg3, Arg4>(0, + static_cast<Handler&&>(handler), arg1, arg2, arg3, arg4); } template <typename Handler, typename Arg1, typename Arg2, @@ -644,9 +376,9 @@ class binder5 { public: template <typename T> - binder5(int, ASIO_MOVE_ARG(T) handler, const Arg1& arg1, + binder5(int, T&& handler, const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) - : handler_(ASIO_MOVE_CAST(T)(handler)), + : handler_(static_cast<T&&>(handler)), arg1_(arg1), arg2_(arg2), arg3_(arg3), @@ -657,7 +389,7 @@ public: binder5(Handler& handler, const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, const Arg5& arg5) - : handler_(ASIO_MOVE_CAST(Handler)(handler)), + : handler_(static_cast<Handler&&>(handler)), arg1_(arg1), arg2_(arg2), arg3_(arg3), @@ -666,7 +398,6 @@ public: { } -#if defined(ASIO_HAS_MOVE) binder5(const binder5& other) : handler_(other.handler_), arg1_(other.arg1_), @@ -678,19 +409,18 @@ public: } binder5(binder5&& other) - : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)), - arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)), - arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_)), - arg3_(ASIO_MOVE_CAST(Arg3)(other.arg3_)), - arg4_(ASIO_MOVE_CAST(Arg4)(other.arg4_)), - arg5_(ASIO_MOVE_CAST(Arg5)(other.arg5_)) + : handler_(static_cast<Handler&&>(other.handler_)), + arg1_(static_cast<Arg1&&>(other.arg1_)), + arg2_(static_cast<Arg2&&>(other.arg2_)), + arg3_(static_cast<Arg3&&>(other.arg3_)), + arg4_(static_cast<Arg4&&>(other.arg4_)), + arg5_(static_cast<Arg5&&>(other.arg5_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()() { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( + static_cast<Handler&&>(handler_)( static_cast<const Arg1&>(arg1_), static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_), @@ -714,34 +444,6 @@ public: template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1, typename Arg2, - typename Arg3, typename Arg4, typename Arg5> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1, typename Arg2, - typename Arg3, typename Arg4, typename Arg5> inline bool asio_handler_is_continuation( binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) { @@ -749,65 +451,37 @@ inline bool asio_handler_is_continuation( this_handler->handler_); } -template <typename Function, typename Handler, typename Arg1, - typename Arg2, typename Arg3, typename Arg4, typename Arg5> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler, typename Arg1, - typename Arg2, typename Arg3, typename Arg4, typename Arg5> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - template <typename Handler, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> -inline binder5<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4, Arg5> -bind_handler(ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1, +inline binder5<decay_t<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) { - return binder5<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4, Arg5>(0, - ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3, arg4, arg5); + return binder5<decay_t<Handler>, Arg1, Arg2, Arg3, Arg4, Arg5>(0, + static_cast<Handler&&>(handler), arg1, arg2, arg3, arg4, arg5); } -#if defined(ASIO_HAS_MOVE) - template <typename Handler, typename Arg1> class move_binder1 { public: - move_binder1(int, ASIO_MOVE_ARG(Handler) handler, - ASIO_MOVE_ARG(Arg1) arg1) - : handler_(ASIO_MOVE_CAST(Handler)(handler)), - arg1_(ASIO_MOVE_CAST(Arg1)(arg1)) + move_binder1(int, Handler&& handler, + Arg1&& arg1) + : handler_(static_cast<Handler&&>(handler)), + arg1_(static_cast<Arg1&&>(arg1)) { } move_binder1(move_binder1&& other) - : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)), - arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)) + : handler_(static_cast<Handler&&>(other.handler_)), + arg1_(static_cast<Arg1&&>(other.arg1_)) { } void operator()() { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( - ASIO_MOVE_CAST(Arg1)(arg1_)); + static_cast<Handler&&>(handler_)( + static_cast<Arg1&&>(arg1_)); } //private: @@ -816,32 +490,6 @@ public: }; template <typename Handler, typename Arg1> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - move_binder1<Handler, Arg1>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - move_binder1<Handler, Arg1>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1> inline bool asio_handler_is_continuation( move_binder1<Handler, Arg1>* this_handler) { @@ -849,42 +497,30 @@ inline bool asio_handler_is_continuation( this_handler->handler_); } -template <typename Function, typename Handler, typename Arg1> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(ASIO_MOVE_ARG(Function) function, - move_binder1<Handler, Arg1>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - ASIO_MOVE_CAST(Function)(function), this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - template <typename Handler, typename Arg1, typename Arg2> class move_binder2 { public: - move_binder2(int, ASIO_MOVE_ARG(Handler) handler, - const Arg1& arg1, ASIO_MOVE_ARG(Arg2) arg2) - : handler_(ASIO_MOVE_CAST(Handler)(handler)), + move_binder2(int, Handler&& handler, + const Arg1& arg1, Arg2&& arg2) + : handler_(static_cast<Handler&&>(handler)), arg1_(arg1), - arg2_(ASIO_MOVE_CAST(Arg2)(arg2)) + arg2_(static_cast<Arg2&&>(arg2)) { } move_binder2(move_binder2&& other) - : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)), - arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)), - arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_)) + : handler_(static_cast<Handler&&>(other.handler_)), + arg1_(static_cast<Arg1&&>(other.arg1_)), + arg2_(static_cast<Arg2&&>(other.arg2_)) { } void operator()() { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( + static_cast<Handler&&>(handler_)( static_cast<const Arg1&>(arg1_), - ASIO_MOVE_CAST(Arg2)(arg2_)); + static_cast<Arg2&&>(arg2_)); } //private: @@ -894,32 +530,6 @@ public: }; template <typename Handler, typename Arg1, typename Arg2> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - move_binder2<Handler, Arg1, Arg2>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1, typename Arg2> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - move_binder2<Handler, Arg1, Arg2>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Arg1, typename Arg2> inline bool asio_handler_is_continuation( move_binder2<Handler, Arg1, Arg2>* this_handler) { @@ -927,20 +537,6 @@ inline bool asio_handler_is_continuation( this_handler->handler_); } -template <typename Function, typename Handler, typename Arg1, typename Arg2> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(ASIO_MOVE_ARG(Function) function, - move_binder2<Handler, Arg1, Arg2>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - ASIO_MOVE_CAST(Function)(function), this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -#endif // defined(ASIO_HAS_MOVE) - } // namespace detail template <template <typename, typename> class Associator, @@ -950,8 +546,14 @@ struct associator<Associator, : Associator<Handler, DefaultCandidate> { static typename Associator<Handler, DefaultCandidate>::type get( - const detail::binder0<Handler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::binder0<Handler>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::binder0<Handler>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } @@ -964,8 +566,14 @@ struct associator<Associator, : Associator<Handler, DefaultCandidate> { static typename Associator<Handler, DefaultCandidate>::type get( - const detail::binder1<Handler, Arg1>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::binder1<Handler, Arg1>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::binder1<Handler, Arg1>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } @@ -979,8 +587,14 @@ struct associator<Associator, : Associator<Handler, DefaultCandidate> { static typename Associator<Handler, DefaultCandidate>::type get( - const detail::binder2<Handler, Arg1, Arg2>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::binder2<Handler, Arg1, Arg2>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::binder2<Handler, Arg1, Arg2>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } @@ -994,8 +608,14 @@ struct associator<Associator, : Associator<Handler, DefaultCandidate> { static typename Associator<Handler, DefaultCandidate>::type get( - const detail::binder3<Handler, Arg1, Arg2, Arg3>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::binder3<Handler, Arg1, Arg2, Arg3>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::binder3<Handler, Arg1, Arg2, Arg3>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } @@ -1009,8 +629,14 @@ struct associator<Associator, : Associator<Handler, DefaultCandidate> { static typename Associator<Handler, DefaultCandidate>::type get( - const detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } @@ -1024,15 +650,20 @@ struct associator<Associator, : Associator<Handler, DefaultCandidate> { static typename Associator<Handler, DefaultCandidate>::type get( + const detail::binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get( const detail::binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } }; -#if defined(ASIO_HAS_MOVE) - template <template <typename, typename> class Associator, typename Handler, typename Arg1, typename DefaultCandidate> struct associator<Associator, @@ -1040,30 +671,39 @@ struct associator<Associator, : Associator<Handler, DefaultCandidate> { static typename Associator<Handler, DefaultCandidate>::type get( - const detail::move_binder1<Handler, Arg1>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::move_binder1<Handler, Arg1>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::move_binder1<Handler, Arg1>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } }; template <template <typename, typename> class Associator, - typename Handler, typename Arg1, typename Arg2, - typename DefaultCandidate> + typename Handler, typename Arg1, typename Arg2, typename DefaultCandidate> struct associator<Associator, detail::move_binder2<Handler, Arg1, Arg2>, DefaultCandidate> : Associator<Handler, DefaultCandidate> { static typename Associator<Handler, DefaultCandidate>::type get( - const detail::move_binder2<Handler, Arg1, Arg2>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::move_binder2<Handler, Arg1, Arg2>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::move_binder2<Handler, Arg1, Arg2>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } }; -#endif // defined(ASIO_HAS_MOVE) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/detail/blocking_executor_op.hpp b/3rdparty/asio/include/asio/detail/blocking_executor_op.hpp index d58df20d787..c70e562f403 100644 --- a/3rdparty/asio/include/asio/detail/blocking_executor_op.hpp +++ b/3rdparty/asio/include/asio/detail/blocking_executor_op.hpp @@ -2,7 +2,7 @@ // detail/blocking_executor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,7 +18,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/event.hpp" #include "asio/detail/fenced_block.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/mutex.hpp" #include "asio/detail/scheduler_operation.hpp" @@ -77,6 +76,7 @@ public: const asio::error_code& /*ec*/, std::size_t /*bytes_transferred*/) { + ASIO_ASSUME(base != 0); blocking_executor_op* o(static_cast<blocking_executor_op*>(base)); typename blocking_executor_op_base<Operation>::do_complete_cleanup @@ -90,7 +90,7 @@ public: { fenced_block b(fenced_block::half); ASIO_HANDLER_INVOCATION_BEGIN(()); - asio_handler_invoke_helpers::invoke(o->handler_, o->handler_); + static_cast<Handler&&>(o->handler_)(); ASIO_HANDLER_INVOCATION_END; } } diff --git a/3rdparty/asio/include/asio/detail/buffer_resize_guard.hpp b/3rdparty/asio/include/asio/detail/buffer_resize_guard.hpp index 00f4aa34c1c..1a78307aaae 100644 --- a/3rdparty/asio/include/asio/detail/buffer_resize_guard.hpp +++ b/3rdparty/asio/include/asio/detail/buffer_resize_guard.hpp @@ -2,7 +2,7 @@ // detail/buffer_resize_guard.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/buffer_sequence_adapter.hpp b/3rdparty/asio/include/asio/detail/buffer_sequence_adapter.hpp index 89b05ce37ed..8ea904e7023 100644 --- a/3rdparty/asio/include/asio/detail/buffer_sequence_adapter.hpp +++ b/3rdparty/asio/include/asio/detail/buffer_sequence_adapter.hpp @@ -2,7 +2,7 @@ // detail/buffer_sequence_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,6 +19,7 @@ #include "asio/buffer.hpp" #include "asio/detail/array_fwd.hpp" #include "asio/detail/socket_types.hpp" +#include "asio/registered_buffer.hpp" #include "asio/detail/push_options.hpp" @@ -105,6 +106,7 @@ class buffer_sequence_adapter { public: enum { is_single_buffer = false }; + enum { is_registered_buffer = false }; explicit buffer_sequence_adapter(const Buffers& buffer_sequence) : count_(0), total_buffer_size_(0) @@ -129,6 +131,11 @@ public: return total_buffer_size_; } + registered_buffer_id registered_id() const + { + return registered_buffer_id(); + } + bool all_empty() const { return total_buffer_size_ == 0; @@ -248,6 +255,7 @@ class buffer_sequence_adapter<Buffer, asio::mutable_buffer> { public: enum { is_single_buffer = true }; + enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const asio::mutable_buffer& buffer_sequence) @@ -271,6 +279,11 @@ public: return total_buffer_size_; } + registered_buffer_id registered_id() const + { + return registered_buffer_id(); + } + bool all_empty() const { return total_buffer_size_ == 0; @@ -310,6 +323,7 @@ class buffer_sequence_adapter<Buffer, asio::const_buffer> { public: enum { is_single_buffer = true }; + enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const asio::const_buffer& buffer_sequence) @@ -333,6 +347,11 @@ public: return total_buffer_size_; } + registered_buffer_id registered_id() const + { + return registered_buffer_id(); + } + bool all_empty() const { return total_buffer_size_ == 0; @@ -374,6 +393,7 @@ class buffer_sequence_adapter<Buffer, asio::mutable_buffers_1> { public: enum { is_single_buffer = true }; + enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const asio::mutable_buffers_1& buffer_sequence) @@ -397,6 +417,11 @@ public: return total_buffer_size_; } + registered_buffer_id registered_id() const + { + return registered_buffer_id(); + } + bool all_empty() const { return total_buffer_size_ == 0; @@ -436,6 +461,7 @@ class buffer_sequence_adapter<Buffer, asio::const_buffers_1> { public: enum { is_single_buffer = true }; + enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const asio::const_buffers_1& buffer_sequence) @@ -459,6 +485,11 @@ public: return total_buffer_size_; } + registered_buffer_id registered_id() const + { + return registered_buffer_id(); + } + bool all_empty() const { return total_buffer_size_ == 0; @@ -494,12 +525,161 @@ private: #endif // !defined(ASIO_NO_DEPRECATED) +template <typename Buffer> +class buffer_sequence_adapter<Buffer, asio::mutable_registered_buffer> + : buffer_sequence_adapter_base +{ +public: + enum { is_single_buffer = true }; + enum { is_registered_buffer = true }; + + explicit buffer_sequence_adapter( + const asio::mutable_registered_buffer& buffer_sequence) + { + init_native_buffer(buffer_, buffer_sequence.buffer()); + total_buffer_size_ = buffer_sequence.size(); + registered_id_ = buffer_sequence.id(); + } + + native_buffer_type* buffers() + { + return &buffer_; + } + + std::size_t count() const + { + return 1; + } + + std::size_t total_size() const + { + return total_buffer_size_; + } + + registered_buffer_id registered_id() const + { + return registered_id_; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty( + const asio::mutable_registered_buffer& buffer_sequence) + { + return buffer_sequence.size() == 0; + } + + static void validate( + const asio::mutable_registered_buffer& buffer_sequence) + { + buffer_sequence.data(); + } + + static Buffer first( + const asio::mutable_registered_buffer& buffer_sequence) + { + return Buffer(buffer_sequence.buffer()); + } + + enum { linearisation_storage_size = 1 }; + + static Buffer linearise( + const asio::mutable_registered_buffer& buffer_sequence, + const Buffer&) + { + return Buffer(buffer_sequence.buffer()); + } + +private: + native_buffer_type buffer_; + std::size_t total_buffer_size_; + registered_buffer_id registered_id_; +}; + +template <typename Buffer> +class buffer_sequence_adapter<Buffer, asio::const_registered_buffer> + : buffer_sequence_adapter_base +{ +public: + enum { is_single_buffer = true }; + enum { is_registered_buffer = true }; + + explicit buffer_sequence_adapter( + const asio::const_registered_buffer& buffer_sequence) + { + init_native_buffer(buffer_, buffer_sequence.buffer()); + total_buffer_size_ = buffer_sequence.size(); + registered_id_ = buffer_sequence.id(); + } + + native_buffer_type* buffers() + { + return &buffer_; + } + + std::size_t count() const + { + return 1; + } + + std::size_t total_size() const + { + return total_buffer_size_; + } + + registered_buffer_id registered_id() const + { + return registered_id_; + } + + bool all_empty() const + { + return total_buffer_size_ == 0; + } + + static bool all_empty( + const asio::const_registered_buffer& buffer_sequence) + { + return buffer_sequence.size() == 0; + } + + static void validate( + const asio::const_registered_buffer& buffer_sequence) + { + buffer_sequence.data(); + } + + static Buffer first( + const asio::const_registered_buffer& buffer_sequence) + { + return Buffer(buffer_sequence.buffer()); + } + + enum { linearisation_storage_size = 1 }; + + static Buffer linearise( + const asio::const_registered_buffer& buffer_sequence, + const Buffer&) + { + return Buffer(buffer_sequence.buffer()); + } + +private: + native_buffer_type buffer_; + std::size_t total_buffer_size_; + registered_buffer_id registered_id_; +}; + template <typename Buffer, typename Elem> -class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> > +class buffer_sequence_adapter<Buffer, boost::array<Elem, 2>> : buffer_sequence_adapter_base { public: enum { is_single_buffer = false }; + enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const boost::array<Elem, 2>& buffer_sequence) @@ -524,6 +704,11 @@ public: return total_buffer_size_; } + registered_buffer_id registered_id() const + { + return registered_buffer_id(); + } + bool all_empty() const { return total_buffer_size_ == 0; @@ -564,14 +749,13 @@ private: std::size_t total_buffer_size_; }; -#if defined(ASIO_HAS_STD_ARRAY) - template <typename Buffer, typename Elem> -class buffer_sequence_adapter<Buffer, std::array<Elem, 2> > +class buffer_sequence_adapter<Buffer, std::array<Elem, 2>> : buffer_sequence_adapter_base { public: enum { is_single_buffer = false }; + enum { is_registered_buffer = false }; explicit buffer_sequence_adapter( const std::array<Elem, 2>& buffer_sequence) @@ -596,6 +780,11 @@ public: return total_buffer_size_; } + registered_buffer_id registered_id() const + { + return registered_buffer_id(); + } + bool all_empty() const { return total_buffer_size_ == 0; @@ -636,8 +825,6 @@ private: std::size_t total_buffer_size_; }; -#endif // defined(ASIO_HAS_STD_ARRAY) - } // namespace detail } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/buffered_stream_storage.hpp b/3rdparty/asio/include/asio/detail/buffered_stream_storage.hpp index 04cef8250d9..afe5cadffda 100644 --- a/3rdparty/asio/include/asio/detail/buffered_stream_storage.hpp +++ b/3rdparty/asio/include/asio/detail/buffered_stream_storage.hpp @@ -2,7 +2,7 @@ // detail/buffered_stream_storage.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/bulk_executor_op.hpp b/3rdparty/asio/include/asio/detail/bulk_executor_op.hpp deleted file mode 100644 index 8f6921b9f80..00000000000 --- a/3rdparty/asio/include/asio/detail/bulk_executor_op.hpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// detail/bulk_executor_op.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_BULK_EXECUTOR_OP_HPP -#define ASIO_DETAIL_BULK_EXECUTOR_OP_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/bind_handler.hpp" -#include "asio/detail/fenced_block.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/scheduler_operation.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -template <typename Handler, typename Alloc, - typename Operation = scheduler_operation> -class bulk_executor_op : public Operation -{ -public: - ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(bulk_executor_op); - - template <typename H> - bulk_executor_op(ASIO_MOVE_ARG(H) h, - const Alloc& allocator, std::size_t i) - : Operation(&bulk_executor_op::do_complete), - handler_(ASIO_MOVE_CAST(H)(h)), - allocator_(allocator), - index_(i) - { - } - - static void do_complete(void* owner, Operation* base, - const asio::error_code& /*ec*/, - std::size_t /*bytes_transferred*/) - { - // Take ownership of the handler object. - bulk_executor_op* o(static_cast<bulk_executor_op*>(base)); - Alloc allocator(o->allocator_); - ptr p = { detail::addressof(allocator), o, o }; - - 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, std::size_t> handler(o->handler_, o->index_); - p.reset(); - - // Make the upcall if required. - if (owner) - { - fenced_block b(fenced_block::half); - ASIO_HANDLER_INVOCATION_BEGIN(()); - asio_handler_invoke_helpers::invoke(handler, handler.handler_); - ASIO_HANDLER_INVOCATION_END; - } - } - -private: - Handler handler_; - Alloc allocator_; - std::size_t index_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_BULK_EXECUTOR_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/call_stack.hpp b/3rdparty/asio/include/asio/detail/call_stack.hpp index 40f762d4406..c287c57e2c6 100644 --- a/3rdparty/asio/include/asio/detail/call_stack.hpp +++ b/3rdparty/asio/include/asio/detail/call_stack.hpp @@ -2,7 +2,7 @@ // detail/call_stack.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/chrono.hpp b/3rdparty/asio/include/asio/detail/chrono.hpp index 0abae1cd96b..45490dde02e 100644 --- a/3rdparty/asio/include/asio/detail/chrono.hpp +++ b/3rdparty/asio/include/asio/detail/chrono.hpp @@ -2,7 +2,7 @@ // detail/chrono.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,17 +16,11 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_STD_CHRONO) -# include <chrono> -#elif defined(ASIO_HAS_BOOST_CHRONO) -# include <boost/chrono/system_clocks.hpp> -#endif // defined(ASIO_HAS_BOOST_CHRONO) +#include <chrono> namespace asio { namespace chrono { -#if defined(ASIO_HAS_STD_CHRONO) using std::chrono::duration; using std::chrono::time_point; using std::chrono::duration_cast; @@ -44,21 +38,6 @@ using std::chrono::steady_clock; #endif // defined(ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK) using std::chrono::system_clock; using std::chrono::high_resolution_clock; -#elif defined(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(ASIO_HAS_BOOST_CHRONO) } // namespace chrono } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/chrono_time_traits.hpp b/3rdparty/asio/include/asio/detail/chrono_time_traits.hpp index 17b9645cc0d..de7b7d69929 100644 --- a/3rdparty/asio/include/asio/detail/chrono_time_traits.hpp +++ b/3rdparty/asio/include/asio/detail/chrono_time_traits.hpp @@ -2,7 +2,7 @@ // detail/chrono_time_traits.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/completion_handler.hpp b/3rdparty/asio/include/asio/detail/completion_handler.hpp index 5c24fa42a8b..c6f98b36c38 100644 --- a/3rdparty/asio/include/asio/detail/completion_handler.hpp +++ b/3rdparty/asio/include/asio/detail/completion_handler.hpp @@ -2,7 +2,7 @@ // detail/completion_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -35,7 +35,7 @@ public: completion_handler(Handler& h, const IoExecutor& io_ex) : operation(&completion_handler::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(h)), + handler_(static_cast<Handler&&>(h)), work_(handler_, io_ex) { } @@ -52,7 +52,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( h->work_)); // Make a copy of the handler so that the memory can be deallocated before @@ -61,7 +61,7 @@ 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. - Handler handler(ASIO_MOVE_CAST(Handler)(h->handler_)); + Handler handler(static_cast<Handler&&>(h->handler_)); p.h = asio::detail::addressof(handler); p.reset(); diff --git a/3rdparty/asio/include/asio/detail/composed_work.hpp b/3rdparty/asio/include/asio/detail/composed_work.hpp new file mode 100644 index 00000000000..8076f8508d6 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/composed_work.hpp @@ -0,0 +1,252 @@ +// +// detail/composed_work.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_COMPOSED_WORK_HPP +#define ASIO_DETAIL_COMPOSED_WORK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/execution/executor.hpp" +#include "asio/execution/outstanding_work.hpp" +#include "asio/executor_work_guard.hpp" +#include "asio/is_executor.hpp" +#include "asio/system_executor.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Executor, typename = void> +class composed_work_guard +{ +public: + typedef decay_t< + prefer_result_t<Executor, execution::outstanding_work_t::tracked_t> + > executor_type; + + composed_work_guard(const Executor& ex) + : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) + { + } + + void reset() + { + } + + executor_type get_executor() const noexcept + { + return executor_; + } + +private: + executor_type executor_; +}; + +template <> +struct composed_work_guard<system_executor> +{ +public: + typedef system_executor executor_type; + + composed_work_guard(const system_executor&) + { + } + + void reset() + { + } + + executor_type get_executor() const noexcept + { + return system_executor(); + } +}; + +#if !defined(ASIO_NO_TS_EXECUTORS) + +template <typename Executor> +struct composed_work_guard<Executor, + enable_if_t< + !execution::is_executor<Executor>::value + > + > : executor_work_guard<Executor> +{ + composed_work_guard(const Executor& ex) + : executor_work_guard<Executor>(ex) + { + } +}; + +#endif // !defined(ASIO_NO_TS_EXECUTORS) + +template <typename> +struct composed_io_executors; + +template <> +struct composed_io_executors<void()> +{ + composed_io_executors() noexcept + : head_(system_executor()) + { + } + + typedef system_executor head_type; + system_executor head_; +}; + +inline composed_io_executors<void()> make_composed_io_executors() +{ + return composed_io_executors<void()>(); +} + +template <typename Head> +struct composed_io_executors<void(Head)> +{ + explicit composed_io_executors(const Head& ex) noexcept + : head_(ex) + { + } + + typedef Head head_type; + Head head_; +}; + +template <typename Head> +inline composed_io_executors<void(Head)> +make_composed_io_executors(const Head& head) +{ + return composed_io_executors<void(Head)>(head); +} + +template <typename Head, typename... Tail> +struct composed_io_executors<void(Head, Tail...)> +{ + explicit composed_io_executors(const Head& head, + const Tail&... tail) noexcept + : head_(head), + tail_(tail...) + { + } + + void reset() + { + head_.reset(); + tail_.reset(); + } + + typedef Head head_type; + Head head_; + composed_io_executors<void(Tail...)> tail_; +}; + +template <typename Head, typename... Tail> +inline composed_io_executors<void(Head, Tail...)> +make_composed_io_executors(const Head& head, const Tail&... tail) +{ + return composed_io_executors<void(Head, Tail...)>(head, tail...); +} + +template <typename> +struct composed_work; + +template <> +struct composed_work<void()> +{ + typedef composed_io_executors<void()> executors_type; + + composed_work(const executors_type&) noexcept + : head_(system_executor()) + { + } + + void reset() + { + head_.reset(); + } + + typedef system_executor head_type; + composed_work_guard<system_executor> head_; +}; + +template <typename Head> +struct composed_work<void(Head)> +{ + typedef composed_io_executors<void(Head)> executors_type; + + explicit composed_work(const executors_type& ex) noexcept + : head_(ex.head_) + { + } + + void reset() + { + head_.reset(); + } + + typedef Head head_type; + composed_work_guard<Head> head_; +}; + +template <typename Head, typename... Tail> +struct composed_work<void(Head, Tail...)> +{ + typedef composed_io_executors<void(Head, Tail...)> executors_type; + + explicit composed_work(const executors_type& ex) noexcept + : head_(ex.head_), + tail_(ex.tail_) + { + } + + void reset() + { + head_.reset(); + tail_.reset(); + } + + typedef Head head_type; + composed_work_guard<Head> head_; + composed_work<void(Tail...)> tail_; +}; + +template <typename IoObject> +inline typename IoObject::executor_type +get_composed_io_executor(IoObject& io_object, + enable_if_t< + !is_executor<IoObject>::value + >* = 0, + enable_if_t< + !execution::is_executor<IoObject>::value + >* = 0) +{ + return io_object.get_executor(); +} + +template <typename Executor> +inline const Executor& get_composed_io_executor(const Executor& ex, + enable_if_t< + is_executor<Executor>::value + || execution::is_executor<Executor>::value + >* = 0) +{ + return ex; +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_COMPOSED_WORK_HPP diff --git a/3rdparty/asio/include/asio/detail/concurrency_hint.hpp b/3rdparty/asio/include/asio/detail/concurrency_hint.hpp index 60ab2a8cd3f..43e81a4c22d 100644 --- a/3rdparty/asio/include/asio/detail/concurrency_hint.hpp +++ b/3rdparty/asio/include/asio/detail/concurrency_hint.hpp @@ -2,7 +2,7 @@ // detail/concurrency_hint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/conditionally_enabled_event.hpp b/3rdparty/asio/include/asio/detail/conditionally_enabled_event.hpp index bb5c524b0c7..af68dde32c0 100644 --- a/3rdparty/asio/include/asio/detail/conditionally_enabled_event.hpp +++ b/3rdparty/asio/include/asio/detail/conditionally_enabled_event.hpp @@ -2,7 +2,7 @@ // detail/conditionally_enabled_event.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/conditionally_enabled_mutex.hpp b/3rdparty/asio/include/asio/detail/conditionally_enabled_mutex.hpp index 4f354ea5b8d..27fc30ecbb2 100644 --- a/3rdparty/asio/include/asio/detail/conditionally_enabled_mutex.hpp +++ b/3rdparty/asio/include/asio/detail/conditionally_enabled_mutex.hpp @@ -2,7 +2,7 @@ // detail/conditionally_enabled_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/config.hpp b/3rdparty/asio/include/asio/detail/config.hpp index be350c4e6d0..cd345eac2cd 100644 --- a/3rdparty/asio/include/asio/detail/config.hpp +++ b/3rdparty/asio/include/asio/detail/config.hpp @@ -2,7 +2,7 @@ // detail/config.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -24,6 +24,17 @@ # endif // !defined(ASIO_ENABLE_BOOST) #endif // !defined(ASIO_STANDALONE) +// Make standard library feature macros available. +#if defined(__has_include) +# if __has_include(<version>) +# include <version> +# else // __has_include(<version>) +# include <cstddef> +# endif // __has_include(<version>) +#else // defined(__has_include) +# include <cstddef> +#endif // defined(__has_include) + // boostify: non-boost code ends here #if defined(ASIO_STANDALONE) # define ASIO_DISABLE_BOOST_ALIGN 1 @@ -38,6 +49,7 @@ # define ASIO_DISABLE_BOOST_THROW_EXCEPTION 1 # define ASIO_DISABLE_BOOST_WORKAROUND 1 #else // defined(ASIO_STANDALONE) +// Boost.Config library is available. # include <boost/config.hpp> # include <boost/version.hpp> # define ASIO_HAS_BOOST_CONFIG 1 @@ -106,244 +118,85 @@ # include <android/api-level.h> #endif // defined(__ANDROID__) -// Support move construction and assignment on compilers known to allow it. -#if !defined(ASIO_HAS_MOVE) -# if !defined(ASIO_DISABLE_MOVE) -# if defined(__clang__) -# if __has_feature(__cxx_rvalue_references__) -# define ASIO_HAS_MOVE 1 -# endif // __has_feature(__cxx_rvalue_references__) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_MOVE 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_MOVE 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# if defined(__INTEL_CXX11_MODE__) -# if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500) -# define ASIO_HAS_MOVE 1 -# endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500) -# if defined(__ICL) && (__ICL >= 1500) -# define ASIO_HAS_MOVE 1 -# endif // defined(__ICL) && (__ICL >= 1500) -# endif // defined(__INTEL_CXX11_MODE__) -# endif // !defined(ASIO_DISABLE_MOVE) -#endif // !defined(ASIO_HAS_MOVE) - -// If ASIO_MOVE_CAST isn't defined, and move support is available, define -// * ASIO_MOVE_ARG, -// * ASIO_NONDEDUCED_MOVE_ARG, and -// * ASIO_MOVE_CAST -// to take advantage of rvalue references and perfect forwarding. -#if defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST) +// Always enabled. Retained for backwards compatibility in user code. +#if !defined(ASIO_DISABLE_CXX11_MACROS) +# define ASIO_HAS_MOVE 1 # define ASIO_MOVE_ARG(type) type&& # define ASIO_MOVE_ARG2(type1, type2) type1, type2&& # define ASIO_NONDEDUCED_MOVE_ARG(type) type& # define ASIO_MOVE_CAST(type) static_cast<type&&> # define ASIO_MOVE_CAST2(type1, type2) static_cast<type1, type2&&> # define ASIO_MOVE_OR_LVALUE(type) static_cast<type&&> +# define ASIO_MOVE_OR_LVALUE_ARG(type) type&& # define ASIO_MOVE_OR_LVALUE_TYPE(type) type -#endif // defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST) - -// If ASIO_MOVE_CAST still isn't defined, default to a C++03-compatible -// implementation. Note that older g++ and MSVC versions don't like it when you -// pass a non-member function through a const reference, so for most compilers -// we'll play it safe and stick with the old approach of passing the handler by -// value. -#if !defined(ASIO_MOVE_CAST) -# if defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) -# define ASIO_MOVE_ARG(type) const type& -# else // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) -# define ASIO_MOVE_ARG(type) type -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4) -# elif defined(ASIO_MSVC) -# if (_MSC_VER >= 1400) -# define ASIO_MOVE_ARG(type) const type& -# else // (_MSC_VER >= 1400) -# define ASIO_MOVE_ARG(type) type -# endif // (_MSC_VER >= 1400) -# else -# define ASIO_MOVE_ARG(type) type -# endif -# define ASIO_NONDEDUCED_MOVE_ARG(type) const type& -# define ASIO_MOVE_CAST(type) static_cast<const type&> -# define ASIO_MOVE_CAST2(type1, type2) static_cast<const type1, type2&> -# define ASIO_MOVE_OR_LVALUE(type) -# define ASIO_MOVE_OR_LVALUE_TYPE(type) type& -#endif // !defined(ASIO_MOVE_CAST) - -// Support variadic templates on compilers known to allow it. -#if !defined(ASIO_HAS_VARIADIC_TEMPLATES) -# if !defined(ASIO_DISABLE_VARIADIC_TEMPLATES) -# if defined(__clang__) -# if __has_feature(__cxx_variadic_templates__) -# define ASIO_HAS_VARIADIC_TEMPLATES 1 -# endif // __has_feature(__cxx_variadic_templates__) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_VARIADIC_TEMPLATES 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1900) -# define ASIO_HAS_VARIADIC_TEMPLATES 1 -# endif // (_MSC_VER >= 1900) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_VARIADIC_TEMPLATES) -#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES) -#if !defined(ASIO_ELLIPSIS) -# if defined(ASIO_HAS_VARIADIC_TEMPLATES) -# define ASIO_ELLIPSIS ... -# else // defined(ASIO_HAS_VARIADIC_TEMPLATES) -# define ASIO_ELLIPSIS -# endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) -#endif // !defined(ASIO_ELLIPSIS) - -// Support deleted functions on compilers known to allow it. -#if !defined(ASIO_DELETED) -# if defined(__clang__) -# if __has_feature(__cxx_deleted_functions__) -# define ASIO_DELETED = delete -# endif // __has_feature(__cxx_deleted_functions__) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_DELETED = delete -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1900) -# define ASIO_DELETED = delete -# endif // (_MSC_VER >= 1900) -# endif // defined(ASIO_MSVC) -# if !defined(ASIO_DELETED) -# define ASIO_DELETED -# endif // !defined(ASIO_DELETED) -#endif // !defined(ASIO_DELETED) - -// Support constexpr on compilers known to allow it. -#if !defined(ASIO_HAS_CONSTEXPR) -# if !defined(ASIO_DISABLE_CONSTEXPR) -# if defined(__clang__) -# if __has_feature(__cxx_constexpr__) -# define ASIO_HAS_CONSTEXPR 1 -# endif // __has_feature(__cxx_constexpr__) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_CONSTEXPR 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1900) -# define ASIO_HAS_CONSTEXPR 1 -# endif // (_MSC_VER >= 1900) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_CONSTEXPR) -#endif // !defined(ASIO_HAS_CONSTEXPR) -#if !defined(ASIO_CONSTEXPR) -# if defined(ASIO_HAS_CONSTEXPR) -# define ASIO_CONSTEXPR constexpr -# else // defined(ASIO_HAS_CONSTEXPR) -# define ASIO_CONSTEXPR -# endif // defined(ASIO_HAS_CONSTEXPR) -#endif // !defined(ASIO_CONSTEXPR) -#if !defined(ASIO_STATIC_CONSTEXPR) -# if defined(ASIO_HAS_CONSTEXPR) -# define ASIO_STATIC_CONSTEXPR(type, assignment) \ - static constexpr type assignment -# else // defined(ASIO_HAS_CONSTEXPR) -# define ASIO_STATIC_CONSTEXPR(type, assignment) \ - static const type assignment -# endif // defined(ASIO_HAS_CONSTEXPR) -#endif // !defined(ASIO_STATIC_CONSTEXPR) +# define ASIO_DELETED = delete +# define ASIO_HAS_VARIADIC_TEMPLATES 1 +# define ASIO_HAS_CONSTEXPR 1 +# define ASIO_STATIC_CONSTEXPR(type, assignment) \ + static constexpr type assignment +# define ASIO_HAS_NOEXCEPT 1 +# define ASIO_NOEXCEPT noexcept(true) +# define ASIO_NOEXCEPT_OR_NOTHROW noexcept(true) +# define ASIO_NOEXCEPT_IF(c) noexcept(c) +# define ASIO_HAS_DECLTYPE 1 +# define ASIO_AUTO_RETURN_TYPE_PREFIX(t) auto +# define ASIO_AUTO_RETURN_TYPE_PREFIX2(t0, t1) auto +# define ASIO_AUTO_RETURN_TYPE_PREFIX3(t0, t1, t2) auto +# define ASIO_AUTO_RETURN_TYPE_SUFFIX(expr) -> decltype expr +# define ASIO_HAS_ALIAS_TEMPLATES 1 +# define ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS 1 +# define ASIO_HAS_ENUM_CLASS 1 +# define ASIO_HAS_REF_QUALIFIED_FUNCTIONS 1 +# define ASIO_LVALUE_REF_QUAL & +# define ASIO_RVALUE_REF_QUAL && +# define ASIO_HAS_USER_DEFINED_LITERALS 1 +# define ASIO_HAS_ALIGNOF 1 +# define ASIO_ALIGNOF(T) alignof(T) +# define ASIO_HAS_STD_ALIGN 1 +# define ASIO_HAS_STD_SYSTEM_ERROR 1 +# define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true) +# define ASIO_HAS_STD_ARRAY 1 +# define ASIO_HAS_STD_SHARED_PTR 1 +# define ASIO_HAS_STD_ALLOCATOR_ARG 1 +# define ASIO_HAS_STD_ATOMIC 1 +# define ASIO_HAS_STD_CHRONO 1 +# define ASIO_HAS_STD_ADDRESSOF 1 +# define ASIO_HAS_STD_FUNCTION 1 +# define ASIO_HAS_STD_REFERENCE_WRAPPER 1 +# define ASIO_HAS_STD_TYPE_TRAITS 1 +# define ASIO_HAS_NULLPTR 1 +# define ASIO_HAS_CXX11_ALLOCATORS 1 +# define ASIO_HAS_CSTDINT 1 +# define ASIO_HAS_STD_THREAD 1 +# define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 +# define ASIO_HAS_STD_CALL_ONCE 1 +# define ASIO_HAS_STD_FUTURE 1 +# define ASIO_HAS_STD_TUPLE 1 +# define ASIO_HAS_STD_IOSTREAM_MOVE 1 +# define ASIO_HAS_STD_EXCEPTION_PTR 1 +# define ASIO_HAS_STD_NESTED_EXCEPTION 1 +# define ASIO_HAS_STD_HASH 1 +#endif // !defined(ASIO_DISABLE_CXX11_MACROS) + +// Support for static constexpr with default initialisation. #if !defined(ASIO_STATIC_CONSTEXPR_DEFAULT_INIT) -# if defined(ASIO_HAS_CONSTEXPR) -# if defined(__GNUC__) -# if (__GNUC__ >= 8) -# define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \ - static constexpr const type name{} -# else // (__GNUC__ >= 8) -# define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \ - static const type name -# endif // (__GNUC__ >= 8) -# elif defined(ASIO_MSVC) -# define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \ - static const type name -# else // defined(ASIO_MSVC) +# if defined(__GNUC__) +# if (__GNUC__ >= 8) # define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \ static constexpr const type name{} -# endif // defined(ASIO_MSVC) -# else // defined(ASIO_HAS_CONSTEXPR) +# else // (__GNUC__ >= 8) +# define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \ + static const type name +# endif // (__GNUC__ >= 8) +# elif defined(ASIO_MSVC) # define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \ static const type name -# endif // defined(ASIO_HAS_CONSTEXPR) +# else // defined(ASIO_MSVC) +# define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \ + static constexpr const type name{} +# endif // defined(ASIO_MSVC) #endif // !defined(ASIO_STATIC_CONSTEXPR_DEFAULT_INIT) -// Support noexcept on compilers known to allow it. -#if !defined(ASIO_HAS_NOEXCEPT) -# if !defined(ASIO_DISABLE_NOEXCEPT) -# if defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 105300) -# if !defined(BOOST_NO_NOEXCEPT) -# define ASIO_HAS_NOEXCEPT 1 -# endif // !defined(BOOST_NO_NOEXCEPT) -# define ASIO_NOEXCEPT BOOST_NOEXCEPT -# define ASIO_NOEXCEPT_OR_NOTHROW BOOST_NOEXCEPT_OR_NOTHROW -# define ASIO_NOEXCEPT_IF(c) BOOST_NOEXCEPT_IF(c) -# elif defined(__clang__) -# if __has_feature(__cxx_noexcept__) -# define ASIO_HAS_NOEXCEPT 1 -# endif // __has_feature(__cxx_noexcept__) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_NOEXCEPT 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# elif defined(ASIO_MSVC) -# if (_MSC_VER >= 1900) -# define ASIO_HAS_NOEXCEPT 1 -# endif // (_MSC_VER >= 1900) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_NOEXCEPT) -# if !defined(ASIO_NOEXCEPT) -# endif // !defined(ASIO_NOEXCEPT) -# if !defined(ASIO_NOEXCEPT_OR_NOTHROW) -# endif // !defined(ASIO_NOEXCEPT_OR_NOTHROW) -#endif // !defined(ASIO_HAS_NOEXCEPT) -#if !defined(ASIO_NOEXCEPT) -# if defined(ASIO_HAS_NOEXCEPT) -# define ASIO_NOEXCEPT noexcept(true) -# else // defined(ASIO_HAS_NOEXCEPT) -# define ASIO_NOEXCEPT -# endif // defined(ASIO_HAS_NOEXCEPT) -#endif // !defined(ASIO_NOEXCEPT) -#if !defined(ASIO_NOEXCEPT_OR_NOTHROW) -# if defined(ASIO_HAS_NOEXCEPT) -# define ASIO_NOEXCEPT_OR_NOTHROW noexcept(true) -# else // defined(ASIO_HAS_NOEXCEPT) -# define ASIO_NOEXCEPT_OR_NOTHROW throw() -# endif // defined(ASIO_HAS_NOEXCEPT) -#endif // !defined(ASIO_NOEXCEPT_OR_NOTHROW) -#if !defined(ASIO_NOEXCEPT_IF) -# if defined(ASIO_HAS_NOEXCEPT) -# define ASIO_NOEXCEPT_IF(c) noexcept(c) -# else // defined(ASIO_HAS_NOEXCEPT) -# define ASIO_NOEXCEPT_IF(c) -# endif // defined(ASIO_HAS_NOEXCEPT) -#endif // !defined(ASIO_NOEXCEPT_IF) - // Support noexcept on function types on compilers known to allow it. #if !defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) # if !defined(ASIO_DISABLE_NOEXCEPT_FUNCTION_TYPE) @@ -363,50 +216,6 @@ # endif // !defined(ASIO_DISABLE_NOEXCEPT_FUNCTION_TYPE) #endif // !defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) -// Support automatic type deduction on compilers known to support it. -#if !defined(ASIO_HAS_DECLTYPE) -# if !defined(ASIO_DISABLE_DECLTYPE) -# if defined(__clang__) -# if __has_feature(__cxx_decltype__) -# define ASIO_HAS_DECLTYPE 1 -# endif // __has_feature(__cxx_decltype__) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_DECLTYPE 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1800) -# define ASIO_HAS_DECLTYPE 1 -# endif // (_MSC_VER >= 1800) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_DECLTYPE) -#endif // !defined(ASIO_HAS_DECLTYPE) - -// Support alias templates on compilers known to allow it. -#if !defined(ASIO_HAS_ALIAS_TEMPLATES) -# if !defined(ASIO_DISABLE_ALIAS_TEMPLATES) -# if defined(__clang__) -# if __has_feature(__cxx_alias_templates__) -# define ASIO_HAS_ALIAS_TEMPLATES 1 -# endif // __has_feature(__cxx_alias_templates__) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_ALIAS_TEMPLATES 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1900) -# define ASIO_HAS_ALIAS_TEMPLATES 1 -# endif // (_MSC_VER >= 1900) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_ALIAS_TEMPLATES) -#endif // !defined(ASIO_HAS_ALIAS_TEMPLATES) - // Support return type deduction on compilers known to allow it. #if !defined(ASIO_HAS_RETURN_TYPE_DEDUCTION) # if !defined(ASIO_DISABLE_RETURN_TYPE_DEDUCTION) @@ -420,35 +229,13 @@ # if (__cpp_return_type_deduction >= 201304) # define ASIO_HAS_RETURN_TYPE_DEDUCTION 1 # endif // (__cpp_return_type_deduction >= 201304) -# endif // defined(__cpp_return_type_deduction) -# endif // !defined(ASIO_DISABLE_RETURN_TYPE_DEDUCTION) -#endif // !defined(ASIO_HAS_RETURN_TYPE_DEDUCTION) - -// Support default function template arguments on compilers known to allow it. -#if !defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) -# if !defined(ASIO_DISABLE_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) -# if (__cplusplus >= 201103) -# define ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS 1 -# elif defined(ASIO_MSVC) -# if (_MSC_VER >= 1900 && _MSVC_LANG >= 201103) -# define ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS 1 -# endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 201103) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) -#endif // !defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) - -// Support enum classes on compilers known to allow them. -#if !defined(ASIO_HAS_ENUM_CLASS) -# if !defined(ASIO_DISABLE_ENUM_CLASS) -# if (__cplusplus >= 201103) -# define ASIO_HAS_ENUM_CLASS 1 # elif defined(ASIO_MSVC) -# if (_MSC_VER >= 1900 && _MSVC_LANG >= 201103) -# define ASIO_HAS_ENUM_CLASS 1 -# endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 201103) +# if (_MSC_VER >= 1900 && _MSVC_LANG >= 201402) +# define ASIO_HAS_RETURN_TYPE_DEDUCTION 1 +# endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 201402) # endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_ENUM_CLASS) -#endif // !defined(ASIO_HAS_ENUM_CLASS) +# endif // !defined(ASIO_DISABLE_RETURN_TYPE_DEDUCTION) +#endif // !defined(ASIO_HAS_RETURN_TYPE_DEDUCTION) // Support concepts on compilers known to allow them. #if !defined(ASIO_HAS_CONCEPTS) @@ -464,6 +251,17 @@ # endif // !defined(ASIO_DISABLE_CONCEPTS) #endif // !defined(ASIO_HAS_CONCEPTS) +// Support concepts on compilers known to allow them. +#if !defined(ASIO_HAS_STD_CONCEPTS) +# if !defined(ASIO_DISABLE_STD_CONCEPTS) +# if defined(ASIO_HAS_CONCEPTS) +# if (__cpp_lib_concepts >= 202002L) +# define ASIO_HAS_STD_CONCEPTS 1 +# endif // (__cpp_concepts >= 202002L) +# endif // defined(ASIO_HAS_CONCEPTS) +# endif // !defined(ASIO_DISABLE_STD_CONCEPTS) +#endif // !defined(ASIO_HAS_STD_CONCEPTS) + // Support template variables on compilers known to allow it. #if !defined(ASIO_HAS_VARIABLE_TEMPLATES) # if !defined(ASIO_DISABLE_VARIABLE_TEMPLATES) @@ -549,67 +347,37 @@ # endif // !defined(ASIO_DISABLE_WORKING_EXPRESSION_SFINAE) #endif // !defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -// Support ref-qualified functions on compilers known to allow it. -#if !defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) -# if !defined(ASIO_DISABLE_REF_QUALIFIED_FUNCTIONS) -# if defined(__clang__) -# if __has_feature(__cxx_reference_qualified_functions__) -# define ASIO_HAS_REF_QUALIFIED_FUNCTIONS 1 -# endif // __has_feature(__cxx_reference_qualified_functions__) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_REF_QUALIFIED_FUNCTIONS 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1900) -# define ASIO_HAS_REF_QUALIFIED_FUNCTIONS 1 -# endif // (_MSC_VER >= 1900) +// Support for capturing parameter packs in lambdas. +#if !defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES) +# if !defined(ASIO_DISABLE_VARIADIC_LAMBDA_CAPTURES) +# if defined(__GNUC__) +# if (__GNUC__ >= 6) +# define ASIO_HAS_VARIADIC_LAMBDA_CAPTURES 1 +# endif // (__GNUC__ >= 6) +# elif defined(ASIO_MSVC) +# if (_MSVC_LANG >= 201103) +# define ASIO_HAS_VARIADIC_LAMBDA_CAPTURES 1 +# endif // (_MSC_LANG >= 201103) +# else // defined(ASIO_MSVC) +# if (__cplusplus >= 201103) +# define ASIO_HAS_VARIADIC_LAMBDA_CAPTURES 1 +# endif // (__cplusplus >= 201103) # endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_REF_QUALIFIED_FUNCTIONS) -#endif // !defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) -# if !defined(ASIO_LVALUE_REF_QUAL) -# define ASIO_LVALUE_REF_QUAL & -# endif // !defined(ASIO_LVALUE_REF_QUAL) -# if !defined(ASIO_RVALUE_REF_QUAL) -# define ASIO_RVALUE_REF_QUAL && -# endif // !defined(ASIO_RVALUE_REF_QUAL) -#else // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) -# if !defined(ASIO_LVALUE_REF_QUAL) -# define ASIO_LVALUE_REF_QUAL -# endif // !defined(ASIO_LVALUE_REF_QUAL) -# if !defined(ASIO_RVALUE_REF_QUAL) -# define ASIO_RVALUE_REF_QUAL -# endif // !defined(ASIO_RVALUE_REF_QUAL) -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -// Support for the alignof operator. -#if !defined(ASIO_HAS_ALIGNOF) -# if !defined(ASIO_DISABLE_ALIGNOF) -# if (__cplusplus >= 201103) -# define ASIO_HAS_ALIGNOF 1 -# endif // (__cplusplus >= 201103) -# endif // !defined(ASIO_DISABLE_ALIGNOF) -#endif // !defined(ASIO_HAS_ALIGNOF) +# endif // !defined(ASIO_DISABLE_VARIADIC_LAMBDA_CAPTURES) +#endif // !defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES) -#if defined(ASIO_HAS_ALIGNOF) -# define ASIO_ALIGNOF(T) alignof(T) -# if defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) -# define ASIO_DEFAULT_ALIGN alignof(std::max_align_t) -# else // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) -# define ASIO_DEFAULT_ALIGN alignof(max_align_t) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) -# else // defined(__GNUC__) +// Default alignment. +#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__) +# define ASIO_DEFAULT_ALIGN __STDCPP_DEFAULT_NEW_ALIGNMENT__ +#elif defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) # define ASIO_DEFAULT_ALIGN alignof(std::max_align_t) -# endif // defined(__GNUC__) -#else // defined(ASIO_HAS_ALIGNOF) -# define ASIO_ALIGNOF(T) 1 -# define ASIO_DEFAULT_ALIGN 1 -#endif // defined(ASIO_HAS_ALIGNOF) +# else // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) +# define ASIO_DEFAULT_ALIGN alignof(max_align_t) +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) +#else // defined(__GNUC__) +# define ASIO_DEFAULT_ALIGN alignof(std::max_align_t) +#endif // defined(__GNUC__) // Standard library support for aligned allocation. #if !defined(ASIO_HAS_STD_ALIGNED_ALLOC) @@ -617,208 +385,45 @@ # if (__cplusplus >= 201703) # if defined(__clang__) # if defined(ASIO_HAS_CLANG_LIBCXX) -# if (_LIBCPP_STD_VER > 14) && defined(_LIBCPP_HAS_ALIGNED_ALLOC) -# define ASIO_HAS_STD_ALIGNED_ALLOC 1 +# if (_LIBCPP_STD_VER > 14) && defined(_LIBCPP_HAS_ALIGNED_ALLOC) \ + && !defined(_LIBCPP_MSVCRT) && !defined(__MINGW32__) +# if defined(__APPLE__) +# if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) +# if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) +# define ASIO_HAS_STD_ALIGNED_ALLOC 1 +# endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) +# elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) +# if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 130000) +# define ASIO_HAS_STD_ALIGNED_ALLOC 1 +# endif // (__IPHONE_OS_VERSION_MIN_REQUIRED >= 130000) +# elif defined(__TV_OS_VERSION_MIN_REQUIRED) +# if (__TV_OS_VERSION_MIN_REQUIRED >= 130000) +# define ASIO_HAS_STD_ALIGNED_ALLOC 1 +# endif // (__TV_OS_VERSION_MIN_REQUIRED >= 130000) +# elif defined(__WATCH_OS_VERSION_MIN_REQUIRED) +# if (__WATCH_OS_VERSION_MIN_REQUIRED >= 60000) +# define ASIO_HAS_STD_ALIGNED_ALLOC 1 +# endif // (__WATCH_OS_VERSION_MIN_REQUIRED >= 60000) +# endif // defined(__WATCH_OS_X_VERSION_MIN_REQUIRED) +# else // defined(__APPLE__) +# define ASIO_HAS_STD_ALIGNED_ALLOC 1 +# endif // defined(__APPLE__) # endif // (_LIBCPP_STD_VER > 14) && defined(_LIBCPP_HAS_ALIGNED_ALLOC) + // && !defined(_LIBCPP_MSVCRT) && !defined(__MINGW32__) # elif defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) # define ASIO_HAS_STD_ALIGNED_ALLOC 1 # endif // defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) # elif defined(__GNUC__) -# if defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) -# define ASIO_HAS_STD_ALIGNED_ALLOC 1 -# endif // defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) +# if ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 7) +# if defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) +# define ASIO_HAS_STD_ALIGNED_ALLOC 1 +# endif // defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) +# endif // ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 7) # endif // defined(__GNUC__) # endif // (__cplusplus >= 201703) # endif // !defined(ASIO_DISABLE_STD_ALIGNED_ALLOC) #endif // !defined(ASIO_HAS_STD_ALIGNED_ALLOC) -// Standard library support for system errors. -#if !defined(ASIO_HAS_STD_SYSTEM_ERROR) -# if !defined(ASIO_DISABLE_STD_SYSTEM_ERROR) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_SYSTEM_ERROR 1 -# elif (__cplusplus >= 201103) -# if __has_include(<system_error>) -# define ASIO_HAS_STD_SYSTEM_ERROR 1 -# endif // __has_include(<system_error>) -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_SYSTEM_ERROR 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_SYSTEM_ERROR 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_SYSTEM_ERROR) -#endif // !defined(ASIO_HAS_STD_SYSTEM_ERROR) - -// Compliant C++11 compilers put noexcept specifiers on error_category members. -#if !defined(ASIO_ERROR_CATEGORY_NOEXCEPT) -# if defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 105300) -# define ASIO_ERROR_CATEGORY_NOEXCEPT BOOST_NOEXCEPT -# elif defined(__clang__) -# if __has_feature(__cxx_noexcept__) -# define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true) -# endif // __has_feature(__cxx_noexcept__) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true) -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# elif defined(ASIO_MSVC) -# if (_MSC_VER >= 1900) -# define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true) -# endif // (_MSC_VER >= 1900) -# endif // defined(ASIO_MSVC) -# if !defined(ASIO_ERROR_CATEGORY_NOEXCEPT) -# define ASIO_ERROR_CATEGORY_NOEXCEPT -# endif // !defined(ASIO_ERROR_CATEGORY_NOEXCEPT) -#endif // !defined(ASIO_ERROR_CATEGORY_NOEXCEPT) - -// Standard library support for arrays. -#if !defined(ASIO_HAS_STD_ARRAY) -# if !defined(ASIO_DISABLE_STD_ARRAY) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_ARRAY 1 -# elif (__cplusplus >= 201103) -# if __has_include(<array>) -# define ASIO_HAS_STD_ARRAY 1 -# endif // __has_include(<array>) -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_ARRAY 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1600) -# define ASIO_HAS_STD_ARRAY 1 -# endif // (_MSC_VER >= 1600) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_ARRAY) -#endif // !defined(ASIO_HAS_STD_ARRAY) - -// Standard library support for shared_ptr and weak_ptr. -#if !defined(ASIO_HAS_STD_SHARED_PTR) -# if !defined(ASIO_DISABLE_STD_SHARED_PTR) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_SHARED_PTR 1 -# elif (__cplusplus >= 201103) -# define ASIO_HAS_STD_SHARED_PTR 1 -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_SHARED_PTR 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1600) -# define ASIO_HAS_STD_SHARED_PTR 1 -# endif // (_MSC_VER >= 1600) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_SHARED_PTR) -#endif // !defined(ASIO_HAS_STD_SHARED_PTR) - -// Standard library support for allocator_arg_t. -#if !defined(ASIO_HAS_STD_ALLOCATOR_ARG) -# if !defined(ASIO_DISABLE_STD_ALLOCATOR_ARG) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_ALLOCATOR_ARG 1 -# elif (__cplusplus >= 201103) -# define ASIO_HAS_STD_ALLOCATOR_ARG 1 -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_ALLOCATOR_ARG 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1600) -# define ASIO_HAS_STD_ALLOCATOR_ARG 1 -# endif // (_MSC_VER >= 1600) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_ALLOCATOR_ARG) -#endif // !defined(ASIO_HAS_STD_ALLOCATOR_ARG) - -// Standard library support for atomic operations. -#if !defined(ASIO_HAS_STD_ATOMIC) -# if !defined(ASIO_DISABLE_STD_ATOMIC) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_ATOMIC 1 -# elif (__cplusplus >= 201103) -# if __has_include(<atomic>) -# define ASIO_HAS_STD_ATOMIC 1 -# endif // __has_include(<atomic>) -# elif defined(__apple_build_version__) && defined(_LIBCPP_VERSION) -# if (__clang_major__ >= 10) -# if __has_include(<atomic>) -# define ASIO_HAS_STD_ATOMIC 1 -# endif // __has_include(<atomic>) -# endif // (__clang_major__ >= 10) -# endif // defined(__apple_build_version__) && defined(_LIBCPP_VERSION) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_ATOMIC 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_ATOMIC 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_ATOMIC) -#endif // !defined(ASIO_HAS_STD_ATOMIC) - -// Standard library support for chrono. Some standard libraries (such as the -// libstdc++ shipped with gcc 4.6) provide monotonic_clock as per early C++0x -// drafts, rather than the eventually standardised name of steady_clock. -#if !defined(ASIO_HAS_STD_CHRONO) -# if !defined(ASIO_DISABLE_STD_CHRONO) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_CHRONO 1 -# elif (__cplusplus >= 201103) -# if __has_include(<chrono>) -# define ASIO_HAS_STD_CHRONO 1 -# endif // __has_include(<chrono>) -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_CHRONO 1 -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6)) -# define ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK 1 -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6)) -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_CHRONO 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_CHRONO) -#endif // !defined(ASIO_HAS_STD_CHRONO) - // Boost support for chrono. #if !defined(ASIO_HAS_BOOST_CHRONO) # if !defined(ASIO_DISABLE_BOOST_CHRONO) @@ -844,277 +449,34 @@ # endif // !defined(ASIO_DISABLE_BOOST_DATE_TIME) #endif // !defined(ASIO_HAS_BOOST_DATE_TIME) -// Standard library support for addressof. -#if !defined(ASIO_HAS_STD_ADDRESSOF) -# if !defined(ASIO_DISABLE_STD_ADDRESSOF) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_ADDRESSOF 1 -# elif (__cplusplus >= 201103) -# define ASIO_HAS_STD_ADDRESSOF 1 -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_ADDRESSOF 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_ADDRESSOF 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_ADDRESSOF) -#endif // !defined(ASIO_HAS_STD_ADDRESSOF) +// Boost support for the Coroutine library. +#if !defined(ASIO_HAS_BOOST_COROUTINE) +# if !defined(ASIO_DISABLE_BOOST_COROUTINE) +# define ASIO_HAS_BOOST_COROUTINE 1 +# endif // !defined(ASIO_DISABLE_BOOST_COROUTINE) +#endif // !defined(ASIO_HAS_BOOST_COROUTINE) -// Standard library support for the function class. -#if !defined(ASIO_HAS_STD_FUNCTION) -# if !defined(ASIO_DISABLE_STD_FUNCTION) +// Boost support for the Context library's fibers. +#if !defined(ASIO_HAS_BOOST_CONTEXT_FIBER) +# if !defined(ASIO_DISABLE_BOOST_CONTEXT_FIBER) # if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_FUNCTION 1 -# elif (__cplusplus >= 201103) -# define ASIO_HAS_STD_FUNCTION 1 -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_FUNCTION 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_FUNCTION 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_FUNCTION) -#endif // !defined(ASIO_HAS_STD_FUNCTION) - -// Standard library support for the reference_wrapper class. -#if !defined(ASIO_HAS_STD_REFERENCE_WRAPPER) -# if !defined(ASIO_DISABLE_STD_REFERENCE_WRAPPER) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_REFERENCE_WRAPPER 1 -# elif (__cplusplus >= 201103) -# define ASIO_HAS_STD_REFERENCE_WRAPPER 1 -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_REFERENCE_WRAPPER 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_REFERENCE_WRAPPER 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_REFERENCE_WRAPPER) -#endif // !defined(ASIO_HAS_STD_REFERENCE_WRAPPER) - -// Standard library support for type traits. -#if !defined(ASIO_HAS_STD_TYPE_TRAITS) -# if !defined(ASIO_DISABLE_STD_TYPE_TRAITS) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_TYPE_TRAITS 1 -# elif (__cplusplus >= 201103) -# if __has_include(<type_traits>) -# define ASIO_HAS_STD_TYPE_TRAITS 1 -# endif // __has_include(<type_traits>) +# if (__cplusplus >= 201103) +# define ASIO_HAS_BOOST_CONTEXT_FIBER 1 # endif // (__cplusplus >= 201103) # elif defined(__GNUC__) # if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) # if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_TYPE_TRAITS 1 +# define ASIO_HAS_BOOST_CONTEXT_FIBER 1 # endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) # endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) # endif // defined(__GNUC__) # if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_TYPE_TRAITS 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_TYPE_TRAITS) -#endif // !defined(ASIO_HAS_STD_TYPE_TRAITS) - -// Standard library support for the nullptr_t type. -#if !defined(ASIO_HAS_NULLPTR) -# if !defined(ASIO_DISABLE_NULLPTR) -# if defined(__clang__) -# if __has_feature(__cxx_nullptr__) -# define ASIO_HAS_NULLPTR 1 -# endif // __has_feature(__cxx_nullptr__) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_NULLPTR 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_NULLPTR 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_NULLPTR) -#endif // !defined(ASIO_HAS_NULLPTR) - -// Standard library support for the C++11 allocator additions. -#if !defined(ASIO_HAS_CXX11_ALLOCATORS) -# if !defined(ASIO_DISABLE_CXX11_ALLOCATORS) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_CXX11_ALLOCATORS 1 -# elif (__cplusplus >= 201103) -# define ASIO_HAS_CXX11_ALLOCATORS 1 -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_CXX11_ALLOCATORS 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1800) -# define ASIO_HAS_CXX11_ALLOCATORS 1 -# endif // (_MSC_VER >= 1800) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_CXX11_ALLOCATORS) -#endif // !defined(ASIO_HAS_CXX11_ALLOCATORS) - -// Standard library support for the cstdint header. -#if !defined(ASIO_HAS_CSTDINT) -# if !defined(ASIO_DISABLE_CSTDINT) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_CSTDINT 1 -# elif (__cplusplus >= 201103) -# define ASIO_HAS_CSTDINT 1 -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_CSTDINT 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_CSTDINT 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_CSTDINT) -#endif // !defined(ASIO_HAS_CSTDINT) - -// Standard library support for the thread class. -#if !defined(ASIO_HAS_STD_THREAD) -# if !defined(ASIO_DISABLE_STD_THREAD) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_THREAD 1 -# elif (__cplusplus >= 201103) -# if __has_include(<thread>) -# define ASIO_HAS_STD_THREAD 1 -# endif // __has_include(<thread>) -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_THREAD 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_THREAD 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_THREAD) -#endif // !defined(ASIO_HAS_STD_THREAD) - -// Standard library support for the mutex and condition variable classes. -#if !defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) -# if !defined(ASIO_DISABLE_STD_MUTEX_AND_CONDVAR) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 -# elif (__cplusplus >= 201103) -# if __has_include(<mutex>) -# define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 -# endif // __has_include(<mutex>) -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_MUTEX_AND_CONDVAR) -#endif // !defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) - -// Standard library support for the call_once function. -#if !defined(ASIO_HAS_STD_CALL_ONCE) -# if !defined(ASIO_DISABLE_STD_CALL_ONCE) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_CALL_ONCE 1 -# elif (__cplusplus >= 201103) -# if __has_include(<mutex>) -# define ASIO_HAS_STD_CALL_ONCE 1 -# endif // __has_include(<mutex>) -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_CALL_ONCE 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_CALL_ONCE 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_CALL_ONCE) -#endif // !defined(ASIO_HAS_STD_CALL_ONCE) - -// Standard library support for futures. -#if !defined(ASIO_HAS_STD_FUTURE) -# if !defined(ASIO_DISABLE_STD_FUTURE) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_FUTURE 1 -# elif (__cplusplus >= 201103) -# if __has_include(<future>) -# define ASIO_HAS_STD_FUTURE 1 -# endif // __has_include(<future>) -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_FUTURE 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_FUTURE 1 -# endif // (_MSC_VER >= 1700) +# if (_MSVC_LANG >= 201103) +# define ASIO_HAS_BOOST_CONTEXT_FIBER 1 +# endif // (_MSC_LANG >= 201103) # endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_FUTURE) -#endif // !defined(ASIO_HAS_STD_FUTURE) +# endif // !defined(ASIO_DISABLE_BOOST_CONTEXT_FIBER) +#endif // !defined(ASIO_HAS_BOOST_CONTEXT_FIBER) // Standard library support for std::string_view. #if !defined(ASIO_HAS_STD_STRING_VIEW) @@ -1187,24 +549,6 @@ # endif // !defined(ASIO_DISABLE_STRING_VIEW) #endif // !defined(ASIO_HAS_STRING_VIEW) -// Standard library support for iostream move construction and assignment. -#if !defined(ASIO_HAS_STD_IOSTREAM_MOVE) -# if !defined(ASIO_DISABLE_STD_IOSTREAM_MOVE) -# if defined(__GNUC__) -# if (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_IOSTREAM_MOVE 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_IOSTREAM_MOVE 1 -# endif // (_MSC_VER >= 1700) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_IOSTREAM_MOVE) -#endif // !defined(ASIO_HAS_STD_IOSTREAM_MOVE) - // Standard library has invoke_result (which supersedes result_of). #if !defined(ASIO_HAS_STD_INVOKE_RESULT) # if !defined(ASIO_DISABLE_STD_INVOKE_RESULT) @@ -1212,58 +556,14 @@ # if (_MSC_VER >= 1911 && _MSVC_LANG >= 201703) # define ASIO_HAS_STD_INVOKE_RESULT 1 # endif // (_MSC_VER >= 1911 && _MSVC_LANG >= 201703) +# else // defined(ASIO_MSVC) +# if (__cplusplus >= 201703) +# define ASIO_HAS_STD_INVOKE_RESULT 1 +# endif // (__cplusplus >= 201703) # endif // defined(ASIO_MSVC) # endif // !defined(ASIO_DISABLE_STD_INVOKE_RESULT) #endif // !defined(ASIO_HAS_STD_INVOKE_RESULT) -// Standard library support for std::exception_ptr and std::current_exception. -#if !defined(ASIO_HAS_STD_EXCEPTION_PTR) -# if !defined(ASIO_DISABLE_STD_EXCEPTION_PTR) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_EXCEPTION_PTR 1 -# elif (__cplusplus >= 201103) -# define ASIO_HAS_STD_EXCEPTION_PTR 1 -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_EXCEPTION_PTR 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1800) -# define ASIO_HAS_STD_EXCEPTION_PTR 1 -# endif // (_MSC_VER >= 1800) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_EXCEPTION_PTR) -#endif // !defined(ASIO_HAS_STD_EXCEPTION_PTR) - -// Standard library support for std::nested_exception. -#if !defined(ASIO_HAS_STD_NESTED_EXCEPTION) -# if !defined(ASIO_DISABLE_STD_NESTED_EXCEPTION) -# if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_NESTED_EXCEPTION 1 -# elif (__cplusplus >= 201103) -# define ASIO_HAS_STD_NESTED_EXCEPTION 1 -# endif // (__cplusplus >= 201103) -# elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_NESTED_EXCEPTION 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# endif // defined(__GNUC__) -# if defined(ASIO_MSVC) -# if (_MSC_VER >= 1900) -# define ASIO_HAS_STD_NESTED_EXCEPTION 1 -# endif // (_MSC_VER >= 1900) -# endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_NESTED_EXCEPTION) -#endif // !defined(ASIO_HAS_STD_NESTED_EXCEPTION) - // Standard library support for std::any. #if !defined(ASIO_HAS_STD_ANY) # if !defined(ASIO_DISABLE_STD_ANY) @@ -1288,6 +588,30 @@ # endif // !defined(ASIO_DISABLE_STD_ANY) #endif // !defined(ASIO_HAS_STD_ANY) +// Standard library support for std::variant. +#if !defined(ASIO_HAS_STD_VARIANT) +# if !defined(ASIO_DISABLE_STD_VARIANT) +# if defined(__clang__) +# if (__cplusplus >= 201703) +# if __has_include(<variant>) +# define ASIO_HAS_STD_VARIANT 1 +# endif // __has_include(<variant>) +# endif // (__cplusplus >= 201703) +# elif defined(__GNUC__) +# if (__GNUC__ >= 7) +# if (__cplusplus >= 201703) +# define ASIO_HAS_STD_VARIANT 1 +# endif // (__cplusplus >= 201703) +# endif // (__GNUC__ >= 7) +# endif // defined(__GNUC__) +# if defined(ASIO_MSVC) +# if (_MSC_VER >= 1910) && (_MSVC_LANG >= 201703) +# define ASIO_HAS_STD_VARIANT 1 +# endif // (_MSC_VER >= 1910) && (_MSVC_LANG >= 201703) +# endif // defined(ASIO_MSVC) +# endif // !defined(ASIO_DISABLE_STD_VARIANT) +#endif // !defined(ASIO_HAS_STD_VARIANT) + // Standard library support for std::source_location. #if !defined(ASIO_HAS_STD_SOURCE_LOCATION) # if !defined(ASIO_DISABLE_STD_SOURCE_LOCATION) @@ -1319,6 +643,50 @@ # endif // !defined(ASIO_DISABLE_SOURCE_LOCATION) #endif // !defined(ASIO_HAS_SOURCE_LOCATION) +// Boost support for source_location and system errors. +#if !defined(ASIO_HAS_BOOST_SOURCE_LOCATION) +# if !defined(ASIO_DISABLE_BOOST_SOURCE_LOCATION) +# if defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 107900) +# define ASIO_HAS_BOOST_SOURCE_LOCATION 1 +# endif // defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 107900) +# endif // !defined(ASIO_DISABLE_BOOST_SOURCE_LOCATION) +#endif // !defined(ASIO_HAS_BOOST_SOURCE_LOCATION) + +// Helper macros for working with Boost source locations. +#if defined(ASIO_HAS_BOOST_SOURCE_LOCATION) +# define ASIO_SOURCE_LOCATION_PARAM \ + , const boost::source_location& loc +# define ASIO_SOURCE_LOCATION_DEFAULTED_PARAM \ + , const boost::source_location& loc = BOOST_CURRENT_LOCATION +# define ASIO_SOURCE_LOCATION_ARG , loc +#else // if defined(ASIO_HAS_BOOST_SOURCE_LOCATION) +# define ASIO_SOURCE_LOCATION_PARAM +# define ASIO_SOURCE_LOCATION_DEFAULTED_PARAM +# define ASIO_SOURCE_LOCATION_ARG +#endif // if defined(ASIO_HAS_BOOST_SOURCE_LOCATION) + +// Standard library support for std::index_sequence. +#if !defined(ASIO_HAS_STD_INDEX_SEQUENCE) +# if !defined(ASIO_DISABLE_STD_INDEX_SEQUENCE) +# if defined(__clang__) +# if (__cplusplus >= 201402) +# define ASIO_HAS_STD_INDEX_SEQUENCE 1 +# endif // (__cplusplus >= 201402) +# elif defined(__GNUC__) +# if (__GNUC__ >= 7) +# if (__cplusplus >= 201402) +# define ASIO_HAS_STD_INDEX_SEQUENCE 1 +# endif // (__cplusplus >= 201402) +# endif // (__GNUC__ >= 7) +# endif // defined(__GNUC__) +# if defined(ASIO_MSVC) +# if (_MSC_VER >= 1910) && (_MSVC_LANG >= 201402) +# define ASIO_HAS_STD_INDEX_SEQUENCE 1 +# endif // (_MSC_VER >= 1910) && (_MSVC_LANG >= 201402) +# endif // defined(ASIO_MSVC) +# endif // !defined(ASIO_DISABLE_STD_INDEX_SEQUENCE) +#endif // !defined(ASIO_HAS_STD_INDEX_SEQUENCE) + // Windows App target. Windows but with a limited API. #if !defined(ASIO_WINDOWS_APP) # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0603) @@ -1454,7 +822,7 @@ # include <unistd.h> #endif // defined(ASIO_HAS_UNISTD_H) -// Linux: epoll, eventfd and timerfd. +// Linux: epoll, eventfd, timerfd and io_uring. #if defined(__linux__) # include <linux/version.h> # if !defined(ASIO_HAS_EPOLL) @@ -1478,8 +846,20 @@ # endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8) # endif // defined(ASIO_HAS_EPOLL) # endif // !defined(ASIO_HAS_TIMERFD) +# if defined(ASIO_HAS_IO_URING) +# if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0) +# error Linux kernel 5.10 or later is required to support io_uring +# endif // LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0) +# endif // defined(ASIO_HAS_IO_URING) #endif // defined(__linux__) +// Linux: io_uring is used instead of epoll. +#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# if !defined(ASIO_HAS_EPOLL) && defined(ASIO_HAS_IO_URING) +# define ASIO_HAS_IO_URING_AS_DEFAULT 1 +# endif // !defined(ASIO_HAS_EPOLL) && defined(ASIO_HAS_IO_URING) +#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT) + // Mac OS X, FreeBSD, NetBSD, OpenBSD: kqueue. #if (defined(__MACH__) && defined(__APPLE__)) \ || defined(__FreeBSD__) \ @@ -1581,6 +961,34 @@ # endif // !defined(ASIO_DISABLE_LOCAL_SOCKETS) #endif // !defined(ASIO_HAS_LOCAL_SOCKETS) +// Files. +#if !defined(ASIO_HAS_FILE) +# if !defined(ASIO_DISABLE_FILE) +# if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) +# define ASIO_HAS_FILE 1 +# elif defined(ASIO_HAS_IO_URING) +# define ASIO_HAS_FILE 1 +# endif // defined(ASIO_HAS_IO_URING) +# endif // !defined(ASIO_DISABLE_FILE) +#endif // !defined(ASIO_HAS_FILE) + +// Pipes. +#if !defined(ASIO_HAS_PIPE) +# if defined(ASIO_HAS_IOCP) \ + || !defined(ASIO_WINDOWS) \ + && !defined(ASIO_WINDOWS_RUNTIME) \ + && !defined(__CYGWIN__) +# if !defined(__SYMBIAN32__) +# if !defined(ASIO_DISABLE_PIPE) +# define ASIO_HAS_PIPE 1 +# endif // !defined(ASIO_DISABLE_PIPE) +# endif // !defined(__SYMBIAN32__) +# endif // defined(ASIO_HAS_IOCP) + // || !defined(ASIO_WINDOWS) + // && !defined(ASIO_WINDOWS_RUNTIME) + // && !defined(__CYGWIN__) +#endif // !defined(ASIO_HAS_PIPE) + // Can use sigaction() instead of signal(). #if !defined(ASIO_HAS_SIGACTION) # if !defined(ASIO_DISABLE_SIGACTION) @@ -1782,7 +1190,7 @@ # endif // !defined(ASIO_DISABLE_HANDLER_HOOKS) #endif // !defined(ASIO_HAS_HANDLER_HOOKS) -// Support for the __thread keyword extension. +// Support for the __thread keyword extension, or equivalent. #if !defined(ASIO_DISABLE_THREAD_KEYWORD_EXTENSION) # if defined(__linux__) # if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) @@ -1804,6 +1212,22 @@ # define ASIO_THREAD_KEYWORD __declspec(thread) # endif // (_MSC_VER >= 1700) # endif // defined(ASIO_MSVC) && defined(ASIO_WINDOWS_RUNTIME) +# if defined(__APPLE__) +# if defined(__clang__) +# if defined(__apple_build_version__) +# define ASIO_HAS_THREAD_KEYWORD_EXTENSION 1 +# define ASIO_THREAD_KEYWORD __thread +# endif // defined(__apple_build_version__) +# endif // defined(__clang__) +# endif // defined(__APPLE__) +# if !defined(ASIO_HAS_THREAD_KEYWORD_EXTENSION) +# if defined(ASIO_HAS_BOOST_CONFIG) +# if !defined(BOOST_NO_CXX11_THREAD_LOCAL) +# define ASIO_HAS_THREAD_KEYWORD_EXTENSION 1 +# define ASIO_THREAD_KEYWORD thread_local +# endif // !defined(BOOST_NO_CXX11_THREAD_LOCAL) +# endif // defined(ASIO_HAS_BOOST_CONFIG) +# endif // !defined(ASIO_HAS_THREAD_KEYWORD_EXTENSION) #endif // !defined(ASIO_DISABLE_THREAD_KEYWORD_EXTENSION) #if !defined(ASIO_THREAD_KEYWORD) # define ASIO_THREAD_KEYWORD __thread @@ -1857,6 +1281,22 @@ # define ASIO_UNUSED_VARIABLE #endif // !defined(ASIO_UNUSED_VARIABLE) +// Helper macro to tell the optimiser what may be assumed to be true. +#if defined(ASIO_MSVC) +# define ASIO_ASSUME(expr) __assume(expr) +#elif defined(__clang__) +# if __has_builtin(__builtin_assume) +# define ASIO_ASSUME(expr) __builtin_assume(expr) +# endif // __has_builtin(__builtin_assume) +#elif defined(__GNUC__) +# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +# define ASIO_ASSUME(expr) if (expr) {} else { __builtin_unreachable(); } +# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) +#endif // defined(__GNUC__) +#if !defined(ASIO_ASSUME) +# define ASIO_ASSUME(expr) (void)0 +#endif // !defined(ASIO_ASSUME) + // Support the co_await keyword on compilers known to allow it. #if !defined(ASIO_HAS_CO_AWAIT) # if !defined(ASIO_DISABLE_CO_AWAIT) @@ -1869,11 +1309,23 @@ # endif // defined(_RESUMABLE_FUNCTIONS_SUPPORTED) # endif // (_MSC_FULL_VER >= 190023506) # elif defined(__clang__) -# if (__cplusplus >= 201703) && defined(__cpp_coroutines) && (__cpp_coroutines >= 201703) -# if __has_include(<experimental/coroutine>) -# define ASIO_HAS_CO_AWAIT 1 -# endif // __has_include(<experimental/coroutine>) -# endif // (__cplusplus >= 201703) && (__cpp_coroutines >= 201703) +# if (__clang_major__ >= 14) +# if (__cplusplus >= 202002) && (__cpp_impl_coroutine >= 201902) +# if __has_include(<coroutine>) +# define ASIO_HAS_CO_AWAIT 1 +# endif // __has_include(<coroutine>) +# elif (__cplusplus >= 201703) && defined(__cpp_coroutines) && (__cpp_coroutines >= 201703) +# if __has_include(<experimental/coroutine>) +# define ASIO_HAS_CO_AWAIT 1 +# endif // __has_include(<experimental/coroutine>) +# endif // (__cplusplus >= 201703) && defined(__cpp_coroutines) && (__cpp_coroutines >= 201703) +# else // (__clang_major__ >= 14) +# if (__cplusplus >= 201703) && defined(__cpp_coroutines) && (__cpp_coroutines >= 201703) +# if __has_include(<experimental/coroutine>) +# define ASIO_HAS_CO_AWAIT 1 +# endif // __has_include(<experimental/coroutine>) +# endif // (__cplusplus >= 201703) && defined(__cpp_coroutines) && (__cpp_coroutines >= 201703) +# endif // (__clang_major__ >= 14) # elif defined(__GNUC__) # if (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902) # if __has_include(<coroutine>) @@ -1891,8 +1343,15 @@ # if (_MSC_VER >= 1928) && (_MSVC_LANG >= 201705) # define ASIO_HAS_STD_COROUTINE 1 # endif // (_MSC_VER >= 1928) && (_MSVC_LANG >= 201705) -# endif // defined(ASIO_MSVC) -# if defined(__GNUC__) +# elif defined(__clang__) +# if (__clang_major__ >= 14) +# if (__cplusplus >= 202002) && (__cpp_impl_coroutine >= 201902) +# if __has_include(<coroutine>) +# define ASIO_HAS_STD_COROUTINE 1 +# endif // __has_include(<coroutine>) +# endif // (__cplusplus >= 202002) && (__cpp_impl_coroutine >= 201902) +# endif // (__clang_major__ >= 14) +# elif defined(__GNUC__) # if (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902) # if __has_include(<coroutine>) # define ASIO_HAS_STD_COROUTINE 1 @@ -1927,28 +1386,37 @@ # endif // defined(_POSIX_VERSION) #endif // !defined(ASIO_HAS_MSG_NOSIGNAL) -// Standard library support for std::hash. -#if !defined(ASIO_HAS_STD_HASH) -# if !defined(ASIO_DISABLE_STD_HASH) +// Standard library support for std::to_address. +#if !defined(ASIO_HAS_STD_TO_ADDRESS) +# if !defined(ASIO_DISABLE_STD_TO_ADDRESS) # if defined(__clang__) -# if defined(ASIO_HAS_CLANG_LIBCXX) -# define ASIO_HAS_STD_HASH 1 -# elif (__cplusplus >= 201103) -# define ASIO_HAS_STD_HASH 1 -# endif // (__cplusplus >= 201103) +# if (__cplusplus >= 202002) +# define ASIO_HAS_STD_TO_ADDRESS 1 +# endif // (__cplusplus >= 202002) # elif defined(__GNUC__) -# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) -# if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# define ASIO_HAS_STD_HASH 1 -# endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) -# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) +# if (__GNUC__ >= 8) +# if (__cplusplus >= 202002) +# define ASIO_HAS_STD_TO_ADDRESS 1 +# endif // (__cplusplus >= 202002) +# endif // (__GNUC__ >= 8) # endif // defined(__GNUC__) # if defined(ASIO_MSVC) -# if (_MSC_VER >= 1700) -# define ASIO_HAS_STD_HASH 1 -# endif // (_MSC_VER >= 1700) +# if (_MSC_VER >= 1922) && (_MSVC_LANG >= 202002) +# define ASIO_HAS_STD_TO_ADDRESS 1 +# endif // (_MSC_VER >= 1922) && (_MSVC_LANG >= 202002) # endif // defined(ASIO_MSVC) -# endif // !defined(ASIO_DISABLE_STD_HASH) -#endif // !defined(ASIO_HAS_STD_HASH) +# endif // !defined(ASIO_DISABLE_STD_TO_ADDRESS) +#endif // !defined(ASIO_HAS_STD_TO_ADDRESS) + +// Standard library support for snprintf. +#if !defined(ASIO_HAS_SNPRINTF) +# if !defined(ASIO_DISABLE_SNPRINTF) +# if defined(__apple_build_version__) +# if (__clang_major__ >= 14) +# define ASIO_HAS_SNPRINTF 1 +# endif // (__clang_major__ >= 14) +# endif // defined(__apple_build_version__) +# endif // !defined(ASIO_DISABLE_SNPRINTF) +#endif // !defined(ASIO_HAS_SNPRINTF) #endif // ASIO_DETAIL_CONFIG_HPP diff --git a/3rdparty/asio/include/asio/detail/consuming_buffers.hpp b/3rdparty/asio/include/asio/detail/consuming_buffers.hpp index 0d99093a4dd..8af95aab769 100644 --- a/3rdparty/asio/include/asio/detail/consuming_buffers.hpp +++ b/3rdparty/asio/include/asio/detail/consuming_buffers.hpp @@ -2,7 +2,7 @@ // detail/consuming_buffers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,6 +20,7 @@ #include "asio/buffer.hpp" #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/limits.hpp" +#include "asio/registered_buffer.hpp" #include "asio/detail/push_options.hpp" @@ -34,21 +35,17 @@ struct prepared_buffers_max }; template <typename Elem, std::size_t N> -struct prepared_buffers_max<boost::array<Elem, N> > +struct prepared_buffers_max<boost::array<Elem, N>> { enum { value = N }; }; -#if defined(ASIO_HAS_STD_ARRAY) - template <typename Elem, std::size_t N> -struct prepared_buffers_max<std::array<Elem, N> > +struct prepared_buffers_max<std::array<Elem, N>> { enum { value = N }; }; -#endif // defined(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 @@ -269,6 +266,42 @@ public: #endif // !defined(ASIO_NO_DEPRECATED) +template <> +class consuming_buffers<mutable_buffer, + mutable_registered_buffer, const mutable_buffer*> + : public consuming_single_buffer<mutable_registered_buffer> +{ +public: + explicit consuming_buffers(const mutable_registered_buffer& buffer) + : consuming_single_buffer<mutable_registered_buffer>(buffer) + { + } +}; + +template <> +class consuming_buffers<const_buffer, + mutable_registered_buffer, const mutable_buffer*> + : public consuming_single_buffer<mutable_registered_buffer> +{ +public: + explicit consuming_buffers(const mutable_registered_buffer& buffer) + : consuming_single_buffer<mutable_registered_buffer>(buffer) + { + } +}; + +template <> +class consuming_buffers<const_buffer, + const_registered_buffer, const const_buffer*> + : public consuming_single_buffer<const_registered_buffer> +{ +public: + explicit consuming_buffers(const const_registered_buffer& buffer) + : consuming_single_buffer<const_registered_buffer>(buffer) + { + } +}; + template <typename Buffer, typename Elem> class consuming_buffers<Buffer, boost::array<Elem, 2>, typename boost::array<Elem, 2>::const_iterator> @@ -319,8 +352,6 @@ private: std::size_t total_consumed_; }; -#if defined(ASIO_HAS_STD_ARRAY) - template <typename Buffer, typename Elem> class consuming_buffers<Buffer, std::array<Elem, 2>, typename std::array<Elem, 2>::const_iterator> @@ -371,8 +402,6 @@ private: std::size_t total_consumed_; }; -#endif // defined(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> diff --git a/3rdparty/asio/include/asio/detail/cstddef.hpp b/3rdparty/asio/include/asio/detail/cstddef.hpp index e9fd2d23b83..15ec42df5f3 100644 --- a/3rdparty/asio/include/asio/detail/cstddef.hpp +++ b/3rdparty/asio/include/asio/detail/cstddef.hpp @@ -2,7 +2,7 @@ // detail/cstddef.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,11 +20,7 @@ namespace asio { -#if defined(ASIO_HAS_NULLPTR) using std::nullptr_t; -#else // defined(ASIO_HAS_NULLPTR) -struct nullptr_t {}; -#endif // defined(ASIO_HAS_NULLPTR) } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/cstdint.hpp b/3rdparty/asio/include/asio/detail/cstdint.hpp index d29929b711c..a696e34c8ae 100644 --- a/3rdparty/asio/include/asio/detail/cstdint.hpp +++ b/3rdparty/asio/include/asio/detail/cstdint.hpp @@ -2,7 +2,7 @@ // detail/cstdint.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,16 +16,10 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_CSTDINT) -# include <cstdint> -#else // defined(ASIO_HAS_CSTDINT) -# include <boost/cstdint.hpp> -#endif // defined(ASIO_HAS_CSTDINT) +#include <cstdint> namespace asio { -#if defined(ASIO_HAS_CSTDINT) using std::int16_t; using std::int_least16_t; using std::uint16_t; @@ -38,22 +32,8 @@ using std::int64_t; using std::int_least64_t; using std::uint64_t; using std::uint_least64_t; +using std::uintptr_t; using std::uintmax_t; -#else // defined(ASIO_HAS_CSTDINT) -using boost::int16_t; -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(ASIO_HAS_CSTDINT) } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/date_time_fwd.hpp b/3rdparty/asio/include/asio/detail/date_time_fwd.hpp index 1b210228de8..a586fbea713 100644 --- a/3rdparty/asio/include/asio/detail/date_time_fwd.hpp +++ b/3rdparty/asio/include/asio/detail/date_time_fwd.hpp @@ -2,7 +2,7 @@ // detail/date_time_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/deadline_timer_service.hpp b/3rdparty/asio/include/asio/detail/deadline_timer_service.hpp index a46e5653ef2..bd99a6e910c 100644 --- a/3rdparty/asio/include/asio/detail/deadline_timer_service.hpp +++ b/3rdparty/asio/include/asio/detail/deadline_timer_service.hpp @@ -2,7 +2,7 @@ // detail/deadline_timer_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -45,7 +45,7 @@ namespace detail { template <typename Time_Traits> class deadline_timer_service - : public execution_context_service_base<deadline_timer_service<Time_Traits> > + : public execution_context_service_base<deadline_timer_service<Time_Traits>> { public: // The time type. @@ -67,7 +67,7 @@ public: // Constructor. deadline_timer_service(execution_context& context) : execution_context_service_base< - deadline_timer_service<Time_Traits> >(context), + deadline_timer_service<Time_Traits>>(context), scheduler_(asio::use_service<timer_scheduler>(context)) { scheduler_.init_task(); @@ -247,7 +247,7 @@ public: void async_wait(implementation_type& impl, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. diff --git a/3rdparty/asio/include/asio/detail/dependent_type.hpp b/3rdparty/asio/include/asio/detail/dependent_type.hpp index bcdfff3c1d3..fde0e4a6eb5 100644 --- a/3rdparty/asio/include/asio/detail/dependent_type.hpp +++ b/3rdparty/asio/include/asio/detail/dependent_type.hpp @@ -2,7 +2,7 @@ // detail/dependent_type.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/descriptor_ops.hpp b/3rdparty/asio/include/asio/detail/descriptor_ops.hpp index 384aa8d1d13..c001696a9fd 100644 --- a/3rdparty/asio/include/asio/detail/descriptor_ops.hpp +++ b/3rdparty/asio/include/asio/detail/descriptor_ops.hpp @@ -2,7 +2,7 @@ // detail/descriptor_ops.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -24,6 +24,7 @@ #include <cstddef> #include "asio/error.hpp" #include "asio/error_code.hpp" +#include "asio/detail/cstdint.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/push_options.hpp" @@ -55,7 +56,7 @@ inline void get_last_error( { if (!is_error_condition) { - ec.assign(0, ec.category()); + asio::error::clear(ec); } else { @@ -67,6 +68,9 @@ inline void get_last_error( ASIO_DECL int open(const char* path, int flags, asio::error_code& ec); +ASIO_DECL int open(const char* path, int flags, unsigned mode, + asio::error_code& ec); + ASIO_DECL int close(int d, state_type& state, asio::error_code& ec); @@ -105,6 +109,42 @@ ASIO_DECL bool non_blocking_write1(int d, const void* data, std::size_t size, asio::error_code& ec, std::size_t& bytes_transferred); +#if defined(ASIO_HAS_FILE) + +ASIO_DECL std::size_t sync_read_at(int d, state_type state, + uint64_t offset, buf* bufs, std::size_t count, bool all_empty, + asio::error_code& ec); + +ASIO_DECL std::size_t sync_read_at1(int d, state_type state, + uint64_t offset, void* data, std::size_t size, + asio::error_code& ec); + +ASIO_DECL bool non_blocking_read_at(int d, uint64_t offset, + buf* bufs, std::size_t count, asio::error_code& ec, + std::size_t& bytes_transferred); + +ASIO_DECL bool non_blocking_read_at1(int d, uint64_t offset, + void* data, std::size_t size, asio::error_code& ec, + std::size_t& bytes_transferred); + +ASIO_DECL std::size_t sync_write_at(int d, state_type state, + uint64_t offset, const buf* bufs, std::size_t count, bool all_empty, + asio::error_code& ec); + +ASIO_DECL std::size_t sync_write_at1(int d, state_type state, + uint64_t offset, const void* data, std::size_t size, + asio::error_code& ec); + +ASIO_DECL bool non_blocking_write_at(int d, + uint64_t offset, const buf* bufs, std::size_t count, + asio::error_code& ec, std::size_t& bytes_transferred); + +ASIO_DECL bool non_blocking_write_at1(int d, + uint64_t offset, const void* data, std::size_t size, + asio::error_code& ec, std::size_t& bytes_transferred); + +#endif // defined(ASIO_HAS_FILE) + ASIO_DECL int ioctl(int d, state_type& state, long cmd, ioctl_arg_type* arg, asio::error_code& ec); diff --git a/3rdparty/asio/include/asio/detail/descriptor_read_op.hpp b/3rdparty/asio/include/asio/detail/descriptor_read_op.hpp index edc8d34022e..415490cb8a5 100644 --- a/3rdparty/asio/include/asio/detail/descriptor_read_op.hpp +++ b/3rdparty/asio/include/asio/detail/descriptor_read_op.hpp @@ -2,7 +2,7 @@ // detail/descriptor_read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -26,6 +26,7 @@ #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" +#include "asio/dispatch.hpp" #include "asio/detail/push_options.hpp" @@ -48,6 +49,7 @@ public: static status do_perform(reactor_op* base) { + ASIO_ASSUME(base != 0); descriptor_read_op_base* o(static_cast<descriptor_read_op_base*>(base)); typedef buffer_sequence_adapter<asio::mutable_buffer, @@ -85,6 +87,9 @@ class descriptor_read_op : public descriptor_read_op_base<MutableBufferSequence> { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(descriptor_read_op); descriptor_read_op(const asio::error_code& success_ec, @@ -92,7 +97,7 @@ public: Handler& handler, const IoExecutor& io_ex) : descriptor_read_op_base<MutableBufferSequence>(success_ec, descriptor, buffers, &descriptor_read_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -102,6 +107,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); descriptor_read_op* o(static_cast<descriptor_read_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -109,9 +115,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(o->ec_); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -133,6 +141,38 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + descriptor_read_op* o(static_cast<descriptor_read_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + private: Handler handler_; handler_work<Handler, IoExecutor> work_; diff --git a/3rdparty/asio/include/asio/detail/descriptor_write_op.hpp b/3rdparty/asio/include/asio/detail/descriptor_write_op.hpp index c2bc8675f58..ed1814e7e39 100644 --- a/3rdparty/asio/include/asio/detail/descriptor_write_op.hpp +++ b/3rdparty/asio/include/asio/detail/descriptor_write_op.hpp @@ -2,7 +2,7 @@ // detail/descriptor_write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -48,6 +48,7 @@ public: static status do_perform(reactor_op* base) { + ASIO_ASSUME(base != 0); descriptor_write_op_base* o(static_cast<descriptor_write_op_base*>(base)); typedef buffer_sequence_adapter<asio::const_buffer, @@ -85,6 +86,9 @@ class descriptor_write_op : public descriptor_write_op_base<ConstBufferSequence> { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(descriptor_write_op); descriptor_write_op(const asio::error_code& success_ec, @@ -92,7 +96,7 @@ public: Handler& handler, const IoExecutor& io_ex) : descriptor_write_op_base<ConstBufferSequence>(success_ec, descriptor, buffers, &descriptor_write_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -102,6 +106,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); descriptor_write_op* o(static_cast<descriptor_write_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -109,9 +114,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(o->ec_); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -133,6 +140,38 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + descriptor_write_op* o(static_cast<descriptor_write_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + private: Handler handler_; handler_work<Handler, IoExecutor> work_; diff --git a/3rdparty/asio/include/asio/detail/dev_poll_reactor.hpp b/3rdparty/asio/include/asio/detail/dev_poll_reactor.hpp index 92930bba5b9..720fd6b54e8 100644 --- a/3rdparty/asio/include/asio/detail/dev_poll_reactor.hpp +++ b/3rdparty/asio/include/asio/detail/dev_poll_reactor.hpp @@ -2,7 +2,7 @@ // detail/dev_poll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -28,6 +28,7 @@ #include "asio/detail/op_queue.hpp" #include "asio/detail/reactor_op.hpp" #include "asio/detail/reactor_op_queue.hpp" +#include "asio/detail/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp" @@ -41,7 +42,8 @@ namespace asio { namespace detail { class dev_poll_reactor - : public execution_context_service_base<dev_poll_reactor> + : public execution_context_service_base<dev_poll_reactor>, + public scheduler_task { public: enum op_types { read_op = 0, write_op = 1, @@ -84,13 +86,30 @@ public: per_descriptor_data& source_descriptor_data); // Post a reactor operation for immediate completion. - void post_immediate_completion(reactor_op* op, bool is_continuation); + void post_immediate_completion(operation* op, bool is_continuation) const; + + // Post a reactor operation for immediate completion. + ASIO_DECL static void call_post_immediate_completion( + operation* op, bool is_continuation, const void* self); // Start a new operation. The reactor operation will be performed when the // given descriptor is flagged as ready, or an error has occurred. ASIO_DECL void start_op(int op_type, socket_type descriptor, per_descriptor_data&, reactor_op* op, - bool is_continuation, bool allow_speculative); + bool is_continuation, bool allow_speculative, + void (*on_immediate)(operation*, bool, const void*), + const void* immediate_arg); + + // Start a new operation. The reactor operation will be performed when the + // given descriptor is flagged as ready, or an error has occurred. + void start_op(int op_type, socket_type descriptor, + per_descriptor_data& descriptor_data, reactor_op* op, + bool is_continuation, bool allow_speculative) + { + start_op(op_type, descriptor, descriptor_data, + op, is_continuation, allow_speculative, + &dev_poll_reactor::call_post_immediate_completion, this); + } // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the @@ -142,6 +161,12 @@ public: typename timer_queue<Time_Traits>::per_timer_data& timer, std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)()); + // Cancel the timer operations associated with the given key. + template <typename Time_Traits> + void cancel_timer_by_key(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data* timer, + void* cancellation_key); + // Move the timer operations associated with the given timer. template <typename Time_Traits> void move_timer(timer_queue<Time_Traits>& queue, diff --git a/3rdparty/asio/include/asio/detail/epoll_reactor.hpp b/3rdparty/asio/include/asio/detail/epoll_reactor.hpp index 15cb384d5a7..212767a760f 100644 --- a/3rdparty/asio/include/asio/detail/epoll_reactor.hpp +++ b/3rdparty/asio/include/asio/detail/epoll_reactor.hpp @@ -2,7 +2,7 @@ // detail/epoll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -25,6 +25,7 @@ #include "asio/detail/object_pool.hpp" #include "asio/detail/op_queue.hpp" #include "asio/detail/reactor_op.hpp" +#include "asio/detail/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp" @@ -42,7 +43,8 @@ namespace asio { namespace detail { class epoll_reactor - : public execution_context_service_base<epoll_reactor> + : public execution_context_service_base<epoll_reactor>, + public scheduler_task { private: // The mutex type used by this reactor. @@ -114,13 +116,30 @@ public: per_descriptor_data& source_descriptor_data); // Post a reactor operation for immediate completion. - void post_immediate_completion(operation* op, bool is_continuation); + void post_immediate_completion(operation* op, bool is_continuation) const; + + // Post a reactor operation for immediate completion. + ASIO_DECL static void call_post_immediate_completion( + operation* op, bool is_continuation, const void* self); // Start a new operation. The reactor operation will be performed when the // given descriptor is flagged as ready, or an error has occurred. ASIO_DECL void start_op(int op_type, socket_type descriptor, per_descriptor_data& descriptor_data, reactor_op* op, - bool is_continuation, bool allow_speculative); + bool is_continuation, bool allow_speculative, + void (*on_immediate)(operation*, bool, const void*), + const void* immediate_arg); + + // Start a new operation. The reactor operation will be performed when the + // given descriptor is flagged as ready, or an error has occurred. + void start_op(int op_type, socket_type descriptor, + per_descriptor_data& descriptor_data, reactor_op* op, + bool is_continuation, bool allow_speculative) + { + start_op(op_type, descriptor, descriptor_data, + op, is_continuation, allow_speculative, + &epoll_reactor::call_post_immediate_completion, this); + } // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the diff --git a/3rdparty/asio/include/asio/detail/event.hpp b/3rdparty/asio/include/asio/detail/event.hpp index d2b850af187..19e458cdf05 100644 --- a/3rdparty/asio/include/asio/detail/event.hpp +++ b/3rdparty/asio/include/asio/detail/event.hpp @@ -2,7 +2,7 @@ // detail/event.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,10 +23,8 @@ # include "asio/detail/win_event.hpp" #elif defined(ASIO_HAS_PTHREADS) # include "asio/detail/posix_event.hpp" -#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) -# include "asio/detail/std_event.hpp" #else -# error Only Windows, POSIX and std::condition_variable are supported! +# include "asio/detail/std_event.hpp" #endif namespace asio { @@ -38,7 +36,7 @@ typedef null_event event; typedef win_event event; #elif defined(ASIO_HAS_PTHREADS) typedef posix_event event; -#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) +#else typedef std_event event; #endif diff --git a/3rdparty/asio/include/asio/detail/eventfd_select_interrupter.hpp b/3rdparty/asio/include/asio/detail/eventfd_select_interrupter.hpp index 964e90c7439..0eb8843dd56 100644 --- a/3rdparty/asio/include/asio/detail/eventfd_select_interrupter.hpp +++ b/3rdparty/asio/include/asio/detail/eventfd_select_interrupter.hpp @@ -2,7 +2,7 @@ // detail/eventfd_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/3rdparty/asio/include/asio/detail/exception.hpp b/3rdparty/asio/include/asio/detail/exception.hpp new file mode 100644 index 00000000000..28c7cffb5d8 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/exception.hpp @@ -0,0 +1,29 @@ +// +// detail/exception.hpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_EXCEPTION_HPP +#define ASIO_DETAIL_EXCEPTION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <exception> + +namespace asio { + +using std::exception_ptr; +using std::current_exception; +using std::rethrow_exception; + +} // namespace asio + +#endif // ASIO_DETAIL_EXCEPTION_HPP diff --git a/3rdparty/asio/include/asio/detail/executor_function.hpp b/3rdparty/asio/include/asio/detail/executor_function.hpp index 6b24f3aa130..cccf31bf3af 100644 --- a/3rdparty/asio/include/asio/detail/executor_function.hpp +++ b/3rdparty/asio/include/asio/detail/executor_function.hpp @@ -2,7 +2,7 @@ // detail/executor_function.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,7 +17,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/push_options.hpp" @@ -25,8 +24,6 @@ namespace asio { namespace detail { -#if defined(ASIO_HAS_MOVE) - // Lightweight, move-only function object wrapper. class executor_function { @@ -38,11 +35,11 @@ public: typedef impl<F, Alloc> impl_type; typename impl_type::ptr p = { detail::addressof(a), impl_type::ptr::allocate(a), 0 }; - impl_ = new (p.v) impl_type(ASIO_MOVE_CAST(F)(f), a); + impl_ = new (p.v) impl_type(static_cast<F&&>(f), a); p.v = 0; } - executor_function(executor_function&& other) ASIO_NOEXCEPT + executor_function(executor_function&& other) noexcept : impl_(other.impl_) { other.impl_ = 0; @@ -79,8 +76,8 @@ private: thread_info_base::executor_function_tag, impl); template <typename F> - impl(ASIO_MOVE_ARG(F) f, const Alloc& a) - : function_(ASIO_MOVE_CAST(F)(f)), + impl(F&& f, const Alloc& a) + : function_(static_cast<F&&>(f)), allocator_(a) { complete_ = &executor_function::complete<Function, Alloc>; @@ -106,74 +103,25 @@ private: // associated with the function. Consequently, a local copy of the function // is required to ensure that any owning sub-object remains valid until // after we have deallocated the memory here. - Function function(ASIO_MOVE_CAST(Function)(i->function_)); + Function function(static_cast<Function&&>(i->function_)); p.reset(); // Make the upcall if required. if (call) { - asio_handler_invoke_helpers::invoke(function, function); + static_cast<Function&&>(function)(); } } impl_base* impl_; }; -#else // defined(ASIO_HAS_MOVE) - -// Not so lightweight, copyable function object wrapper. -class executor_function -{ -public: - template <typename F, typename Alloc> - explicit executor_function(const F& f, const Alloc&) - : impl_(new impl<typename decay<F>::type>(f)) - { - } - - void operator()() - { - impl_->complete_(impl_.get()); - } - -private: - // Base class for polymorphic function implementations. - struct impl_base - { - void (*complete_)(impl_base*); - }; - - // Polymorphic function implementation. - template <typename F> - struct impl : impl_base - { - impl(const F& f) - : function_(f) - { - complete_ = &executor_function::complete<F>; - } - - F function_; - }; - - // Helper to complete function invocation. - template <typename F> - static void complete(impl_base* i) - { - static_cast<impl<F>*>(i)->function_(); - } - - shared_ptr<impl_base> impl_; -}; - -#endif // defined(ASIO_HAS_MOVE) - // Lightweight, non-owning, copyable function object wrapper. class executor_function_view { public: template <typename F> - explicit executor_function_view(F& f) ASIO_NOEXCEPT + explicit executor_function_view(F& f) noexcept : complete_(&executor_function_view::complete<F>), function_(&f) { diff --git a/3rdparty/asio/include/asio/detail/executor_op.hpp b/3rdparty/asio/include/asio/detail/executor_op.hpp index f97618c378a..78e781e217b 100644 --- a/3rdparty/asio/include/asio/detail/executor_op.hpp +++ b/3rdparty/asio/include/asio/detail/executor_op.hpp @@ -2,7 +2,7 @@ // detail/executor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,7 +18,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/scheduler_operation.hpp" #include "asio/detail/push_options.hpp" @@ -34,9 +33,9 @@ public: ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(executor_op); template <typename H> - executor_op(ASIO_MOVE_ARG(H) h, const Alloc& allocator) + executor_op(H&& h, const Alloc& allocator) : Operation(&executor_op::do_complete), - handler_(ASIO_MOVE_CAST(H)(h)), + handler_(static_cast<H&&>(h)), allocator_(allocator) { } @@ -46,6 +45,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); executor_op* o(static_cast<executor_op*>(base)); Alloc allocator(o->allocator_); ptr p = { detail::addressof(allocator), o, o }; @@ -58,7 +58,7 @@ 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. - Handler handler(ASIO_MOVE_CAST(Handler)(o->handler_)); + Handler handler(static_cast<Handler&&>(o->handler_)); p.reset(); // Make the upcall if required. @@ -66,7 +66,7 @@ public: { fenced_block b(fenced_block::half); ASIO_HANDLER_INVOCATION_BEGIN(()); - asio_handler_invoke_helpers::invoke(handler, handler); + static_cast<Handler&&>(handler)(); ASIO_HANDLER_INVOCATION_END; } } diff --git a/3rdparty/asio/include/asio/detail/fd_set_adapter.hpp b/3rdparty/asio/include/asio/detail/fd_set_adapter.hpp index ade20ca56b3..80b8974a417 100644 --- a/3rdparty/asio/include/asio/detail/fd_set_adapter.hpp +++ b/3rdparty/asio/include/asio/detail/fd_set_adapter.hpp @@ -2,7 +2,7 @@ // detail/fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/fenced_block.hpp b/3rdparty/asio/include/asio/detail/fenced_block.hpp index 08e47d67169..ff096dc8486 100644 --- a/3rdparty/asio/include/asio/detail/fenced_block.hpp +++ b/3rdparty/asio/include/asio/detail/fenced_block.hpp @@ -2,7 +2,7 @@ // detail/fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,28 +20,8 @@ #if !defined(ASIO_HAS_THREADS) \ || defined(ASIO_DISABLE_FENCED_BLOCK) # include "asio/detail/null_fenced_block.hpp" -#elif defined(ASIO_HAS_STD_ATOMIC) -# include "asio/detail/std_fenced_block.hpp" -#elif defined(__MACH__) && defined(__APPLE__) -# include "asio/detail/macos_fenced_block.hpp" -#elif defined(__sun) -# include "asio/detail/solaris_fenced_block.hpp" -#elif defined(__GNUC__) && defined(__arm__) \ - && !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) -# include "asio/detail/gcc_arm_fenced_block.hpp" -#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) -# include "asio/detail/gcc_hppa_fenced_block.hpp" -#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) -# include "asio/detail/gcc_x86_fenced_block.hpp" -#elif defined(__GNUC__) \ - && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ - && !defined(__INTEL_COMPILER) && !defined(__ICL) \ - && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) -# include "asio/detail/gcc_sync_fenced_block.hpp" -#elif defined(ASIO_WINDOWS) && !defined(UNDER_CE) -# include "asio/detail/win_fenced_block.hpp" #else -# include "asio/detail/null_fenced_block.hpp" +# include "asio/detail/std_fenced_block.hpp" #endif namespace asio { @@ -50,28 +30,8 @@ namespace detail { #if !defined(ASIO_HAS_THREADS) \ || defined(ASIO_DISABLE_FENCED_BLOCK) typedef null_fenced_block fenced_block; -#elif defined(ASIO_HAS_STD_ATOMIC) -typedef std_fenced_block fenced_block; -#elif defined(__MACH__) && defined(__APPLE__) -typedef macos_fenced_block fenced_block; -#elif defined(__sun) -typedef solaris_fenced_block fenced_block; -#elif defined(__GNUC__) && defined(__arm__) \ - && !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) -typedef gcc_arm_fenced_block fenced_block; -#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) -typedef gcc_hppa_fenced_block fenced_block; -#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) -typedef gcc_x86_fenced_block fenced_block; -#elif defined(__GNUC__) \ - && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ - && !defined(__INTEL_COMPILER) && !defined(__ICL) \ - && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) -typedef gcc_sync_fenced_block fenced_block; -#elif defined(ASIO_WINDOWS) && !defined(UNDER_CE) -typedef win_fenced_block fenced_block; #else -typedef null_fenced_block fenced_block; +typedef std_fenced_block fenced_block; #endif } // namespace detail diff --git a/3rdparty/asio/include/asio/detail/functional.hpp b/3rdparty/asio/include/asio/detail/functional.hpp index 54256c130b0..145f9d2a9e1 100644 --- a/3rdparty/asio/include/asio/detail/functional.hpp +++ b/3rdparty/asio/include/asio/detail/functional.hpp @@ -2,7 +2,7 @@ // detail/functional.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,28 +16,17 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - #include <functional> -#if !defined(ASIO_HAS_STD_FUNCTION) -# include <boost/function.hpp> -#endif // !defined(ASIO_HAS_STD_FUNCTION) - namespace asio { namespace detail { -#if defined(ASIO_HAS_STD_FUNCTION) using std::function; -#else // defined(ASIO_HAS_STD_FUNCTION) -using boost::function; -#endif // defined(ASIO_HAS_STD_FUNCTION) } // namespace detail -#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) using std::ref; using std::reference_wrapper; -#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER) } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/future.hpp b/3rdparty/asio/include/asio/detail/future.hpp index 9fe828e78ee..f33136cbef2 100644 --- a/3rdparty/asio/include/asio/detail/future.hpp +++ b/3rdparty/asio/include/asio/detail/future.hpp @@ -2,7 +2,7 @@ // detail/future.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,18 +16,17 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" -#if defined(ASIO_HAS_STD_FUTURE) -# include <future> +#include <future> + // Even though the future header is available, libstdc++ may not implement the // std::future class itself. However, we need to have already included the // future header to reliably test for _GLIBCXX_HAS_GTHREADS. -# if defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX) -# if defined(_GLIBCXX_HAS_GTHREADS) -# define ASIO_HAS_STD_FUTURE_CLASS 1 -# endif // defined(_GLIBCXX_HAS_GTHREADS) -# else // defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX) +#if defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX) +# if defined(_GLIBCXX_HAS_GTHREADS) # define ASIO_HAS_STD_FUTURE_CLASS 1 -# endif // defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX) -#endif // defined(ASIO_HAS_STD_FUTURE) +# endif // defined(_GLIBCXX_HAS_GTHREADS) +#else // defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX) +# define ASIO_HAS_STD_FUTURE_CLASS 1 +#endif // defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX) #endif // ASIO_DETAIL_FUTURE_HPP diff --git a/3rdparty/asio/include/asio/detail/gcc_arm_fenced_block.hpp b/3rdparty/asio/include/asio/detail/gcc_arm_fenced_block.hpp deleted file mode 100644 index c879c22d6bf..00000000000 --- a/3rdparty/asio/include/asio/detail/gcc_arm_fenced_block.hpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// detail/gcc_arm_fenced_block.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP -#define ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#if defined(__GNUC__) && defined(__arm__) - -#include "asio/detail/noncopyable.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class gcc_arm_fenced_block - : private noncopyable -{ -public: - enum half_t { half }; - enum full_t { full }; - - // Constructor for a half fenced block. - explicit gcc_arm_fenced_block(half_t) - { - } - - // Constructor for a full fenced block. - explicit gcc_arm_fenced_block(full_t) - { - barrier(); - } - - // Destructor. - ~gcc_arm_fenced_block() - { - barrier(); - } - -private: - static void barrier() - { -#if defined(__ARM_ARCH_4__) \ - || defined(__ARM_ARCH_4T__) \ - || defined(__ARM_ARCH_5__) \ - || defined(__ARM_ARCH_5E__) \ - || defined(__ARM_ARCH_5T__) \ - || defined(__ARM_ARCH_5TE__) \ - || defined(__ARM_ARCH_5TEJ__) \ - || defined(__ARM_ARCH_6__) \ - || defined(__ARM_ARCH_6J__) \ - || defined(__ARM_ARCH_6K__) \ - || defined(__ARM_ARCH_6Z__) \ - || defined(__ARM_ARCH_6ZK__) \ - || defined(__ARM_ARCH_6T2__) -# if defined(__thumb__) - // This is just a placeholder and almost certainly not sufficient. - __asm__ __volatile__ ("" : : : "memory"); -# else // defined(__thumb__) - int a = 0, b = 0; - __asm__ __volatile__ ("swp %0, %1, [%2]" - : "=&r"(a) : "r"(1), "r"(&b) : "memory", "cc"); -# endif // defined(__thumb__) -#else - // ARMv7 and later. - __asm__ __volatile__ ("dmb" : : : "memory"); -#endif - } -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // defined(__GNUC__) && defined(__arm__) - -#endif // ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP diff --git a/3rdparty/asio/include/asio/detail/gcc_hppa_fenced_block.hpp b/3rdparty/asio/include/asio/detail/gcc_hppa_fenced_block.hpp deleted file mode 100644 index 38caa4b01c6..00000000000 --- a/3rdparty/asio/include/asio/detail/gcc_hppa_fenced_block.hpp +++ /dev/null @@ -1,68 +0,0 @@ -// -// detail/gcc_hppa_fenced_block.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP -#define ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#if defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) - -#include "asio/detail/noncopyable.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class gcc_hppa_fenced_block - : private noncopyable -{ -public: - enum half_t { half }; - enum full_t { full }; - - // Constructor for a half fenced block. - explicit gcc_hppa_fenced_block(half_t) - { - } - - // Constructor for a full fenced block. - explicit gcc_hppa_fenced_block(full_t) - { - barrier(); - } - - // Destructor. - ~gcc_hppa_fenced_block() - { - barrier(); - } - -private: - static void barrier() - { - // This is just a placeholder and almost certainly not sufficient. - __asm__ __volatile__ ("" : : : "memory"); - } -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // defined(__GNUC__) && (defined(__hppa) || defined(__hppa__)) - -#endif // ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP diff --git a/3rdparty/asio/include/asio/detail/gcc_sync_fenced_block.hpp b/3rdparty/asio/include/asio/detail/gcc_sync_fenced_block.hpp deleted file mode 100644 index 68fdcf722dd..00000000000 --- a/3rdparty/asio/include/asio/detail/gcc_sync_fenced_block.hpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// detail/gcc_sync_fenced_block.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP -#define ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#if defined(__GNUC__) \ - && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \ - && !defined(__INTEL_COMPILER) && !defined(__ICL) \ - && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) - -#include "asio/detail/noncopyable.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class gcc_sync_fenced_block - : private noncopyable -{ -public: - enum half_or_full_t { half, full }; - - // Constructor. - explicit gcc_sync_fenced_block(half_or_full_t) - : value_(0) - { - __sync_lock_test_and_set(&value_, 1); - } - - // Destructor. - ~gcc_sync_fenced_block() - { - __sync_lock_release(&value_); - } - -private: - int value_; -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // defined(__GNUC__) - // && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) - // && !defined(__INTEL_COMPILER) && !defined(__ICL) - // && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__) - -#endif // ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP diff --git a/3rdparty/asio/include/asio/detail/gcc_x86_fenced_block.hpp b/3rdparty/asio/include/asio/detail/gcc_x86_fenced_block.hpp deleted file mode 100644 index c21b2bad5af..00000000000 --- a/3rdparty/asio/include/asio/detail/gcc_x86_fenced_block.hpp +++ /dev/null @@ -1,99 +0,0 @@ -// -// detail/gcc_x86_fenced_block.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP -#define ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) - -#include "asio/detail/noncopyable.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class gcc_x86_fenced_block - : private noncopyable -{ -public: - enum half_t { half }; - enum full_t { full }; - - // Constructor for a half fenced block. - explicit gcc_x86_fenced_block(half_t) - { - } - - // Constructor for a full fenced block. - explicit gcc_x86_fenced_block(full_t) - { - lbarrier(); - } - - // Destructor. - ~gcc_x86_fenced_block() - { - sbarrier(); - } - -private: - static int barrier() - { - int r = 0, m = 1; - __asm__ __volatile__ ( - "xchgl %0, %1" : - "=r"(r), "=m"(m) : - "0"(1), "m"(m) : - "memory", "cc"); - return r; - } - - static void lbarrier() - { -#if defined(__SSE2__) -# if (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) - __builtin_ia32_lfence(); -# else // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) - __asm__ __volatile__ ("lfence" ::: "memory"); -# endif // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) -#else // defined(__SSE2__) - barrier(); -#endif // defined(__SSE2__) - } - - static void sbarrier() - { -#if defined(__SSE2__) -# if (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) - __builtin_ia32_sfence(); -# else // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) - __asm__ __volatile__ ("sfence" ::: "memory"); -# endif // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL) -#else // defined(__SSE2__) - barrier(); -#endif // defined(__SSE2__) - } -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) - -#endif // ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP diff --git a/3rdparty/asio/include/asio/detail/global.hpp b/3rdparty/asio/include/asio/detail/global.hpp index 685cf90f2cf..59de23a4884 100644 --- a/3rdparty/asio/include/asio/detail/global.hpp +++ b/3rdparty/asio/include/asio/detail/global.hpp @@ -2,7 +2,7 @@ // detail/global.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,10 +23,8 @@ # include "asio/detail/win_global.hpp" #elif defined(ASIO_HAS_PTHREADS) # include "asio/detail/posix_global.hpp" -#elif defined(ASIO_HAS_STD_CALL_ONCE) -# include "asio/detail/std_global.hpp" #else -# error Only Windows, POSIX and std::call_once are supported! +# include "asio/detail/std_global.hpp" #endif namespace asio { @@ -41,7 +39,7 @@ inline T& global() return win_global<T>(); #elif defined(ASIO_HAS_PTHREADS) return posix_global<T>(); -#elif defined(ASIO_HAS_STD_CALL_ONCE) +#else return std_global<T>(); #endif } diff --git a/3rdparty/asio/include/asio/detail/handler_alloc_helpers.hpp b/3rdparty/asio/include/asio/detail/handler_alloc_helpers.hpp index 14033a49a16..c14d542e48c 100644 --- a/3rdparty/asio/include/asio/detail/handler_alloc_helpers.hpp +++ b/3rdparty/asio/include/asio/detail/handler_alloc_helpers.hpp @@ -2,7 +2,7 @@ // detail/handler_alloc_helpers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -21,88 +21,37 @@ #include "asio/detail/recycling_allocator.hpp" #include "asio/detail/thread_info_base.hpp" #include "asio/associated_allocator.hpp" -#include "asio/handler_alloc_hook.hpp" #include "asio/detail/push_options.hpp" -// Calls to asio_handler_allocate and asio_handler_deallocate must be made from -// a namespace that does not contain any overloads of these functions. The -// asio_handler_alloc_helpers namespace is defined here for that purpose. -namespace asio_handler_alloc_helpers { - -#if defined(ASIO_NO_DEPRECATED) -template <typename Handler> -inline void error_if_hooks_are_defined(Handler& h) -{ - using asio::asio_handler_allocate; - // If you get an error here it is because some of your handlers still - // overload asio_handler_allocate, but this hook is no longer used. - (void)static_cast<asio::asio_handler_allocate_is_no_longer_used>( - asio_handler_allocate(static_cast<std::size_t>(0), - asio::detail::addressof(h))); - - using asio::asio_handler_deallocate; - // If you get an error here it is because some of your handlers still - // overload asio_handler_deallocate, but this hook is no longer used. - (void)static_cast<asio::asio_handler_deallocate_is_no_longer_used>( - asio_handler_deallocate(static_cast<void*>(0), - static_cast<std::size_t>(0), asio::detail::addressof(h))); -} -#endif // defined(ASIO_NO_DEPRECATED) +namespace asio { +namespace detail { -template <typename Handler> -inline void* allocate(std::size_t s, Handler& h, +inline void* default_allocate(std::size_t s, std::size_t align = ASIO_DEFAULT_ALIGN) { -#if !defined(ASIO_HAS_HANDLER_HOOKS) - return aligned_new(align, s); -#elif defined(ASIO_NO_DEPRECATED) - // The asio_handler_allocate hook is no longer used to obtain memory. - (void)&error_if_hooks_are_defined<Handler>; - (void)h; -# if !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) +#if !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) return asio::detail::thread_info_base::allocate( asio::detail::thread_context::top_of_thread_call_stack(), s, align); -# else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) - return aligned_new(align, s); -# endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) -#else - (void)align; - using asio::asio_handler_allocate; - return asio_handler_allocate(s, asio::detail::addressof(h)); -#endif +#else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) + return asio::aligned_new(align, s); +#endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) } -template <typename Handler> -inline void deallocate(void* p, std::size_t s, Handler& h) +inline void default_deallocate(void* p, std::size_t s) { -#if !defined(ASIO_HAS_HANDLER_HOOKS) - aligned_delete(p); -#elif defined(ASIO_NO_DEPRECATED) - // The asio_handler_allocate hook is no longer used to obtain memory. - (void)&error_if_hooks_are_defined<Handler>; - (void)h; #if !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) asio::detail::thread_info_base::deallocate( asio::detail::thread_context::top_of_thread_call_stack(), p, s); #else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) (void)s; - aligned_delete(p); + asio::aligned_delete(p); #endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) -#else - using asio::asio_handler_deallocate; - asio_handler_deallocate(p, s, asio::detail::addressof(h)); -#endif } -} // namespace asio_handler_alloc_helpers - -namespace asio { -namespace detail { - -template <typename Handler, typename T> -class hook_allocator +template <typename T> +class default_allocator { public: typedef T value_type; @@ -110,38 +59,31 @@ public: template <typename U> struct rebind { - typedef hook_allocator<Handler, U> other; + typedef default_allocator<U> other; }; - explicit hook_allocator(Handler& h) - : handler_(h) + default_allocator() noexcept { } template <typename U> - hook_allocator(const hook_allocator<Handler, U>& a) - : handler_(a.handler_) + default_allocator(const default_allocator<U>&) noexcept { } T* allocate(std::size_t n) { - return static_cast<T*>( - asio_handler_alloc_helpers::allocate( - sizeof(T) * n, handler_, ASIO_ALIGNOF(T))); + return static_cast<T*>(default_allocate(sizeof(T) * n, alignof(T))); } void deallocate(T* p, std::size_t n) { - asio_handler_alloc_helpers::deallocate(p, sizeof(T) * n, handler_); + default_deallocate(p, sizeof(T) * n); } - -//private: - Handler& handler_; }; -template <typename Handler> -class hook_allocator<Handler, void> +template <> +class default_allocator<void> { public: typedef void value_type; @@ -149,43 +91,38 @@ public: template <typename U> struct rebind { - typedef hook_allocator<Handler, U> other; + typedef default_allocator<U> other; }; - explicit hook_allocator(Handler& h) - : handler_(h) + default_allocator() noexcept { } template <typename U> - hook_allocator(const hook_allocator<Handler, U>& a) - : handler_(a.handler_) + default_allocator(const default_allocator<U>&) noexcept { } - -//private: - Handler& handler_; }; -template <typename Handler, typename Allocator> -struct get_hook_allocator +template <typename Allocator> +struct get_default_allocator { typedef Allocator type; - static type get(Handler&, const Allocator& a) + static type get(const Allocator& a) { return a; } }; -template <typename Handler, typename T> -struct get_hook_allocator<Handler, std::allocator<T> > +template <typename T> +struct get_default_allocator<std::allocator<T>> { - typedef hook_allocator<Handler, T> type; + typedef default_allocator<T> type; - static type get(Handler& handler, const std::allocator<T>&) + static type get(const std::allocator<T>&) { - return type(handler); + return type(); } }; @@ -206,12 +143,12 @@ struct get_hook_allocator<Handler, std::allocator<T> > { \ typedef typename ::asio::associated_allocator< \ Handler>::type associated_allocator_type; \ - typedef typename ::asio::detail::get_hook_allocator< \ - Handler, associated_allocator_type>::type hook_allocator_type; \ - ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \ - ::asio::detail::get_hook_allocator< \ - Handler, associated_allocator_type>::get( \ - handler, ::asio::get_associated_allocator(handler))); \ + typedef typename ::asio::detail::get_default_allocator< \ + associated_allocator_type>::type default_allocator_type; \ + ASIO_REBIND_ALLOC(default_allocator_type, op) a( \ + ::asio::detail::get_default_allocator< \ + associated_allocator_type>::get( \ + ::asio::get_associated_allocator(handler))); \ return a.allocate(1); \ } \ void reset() \ @@ -225,12 +162,12 @@ struct get_hook_allocator<Handler, std::allocator<T> > { \ typedef typename ::asio::associated_allocator< \ Handler>::type associated_allocator_type; \ - typedef typename ::asio::detail::get_hook_allocator< \ - Handler, associated_allocator_type>::type hook_allocator_type; \ - ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \ - ::asio::detail::get_hook_allocator< \ - Handler, associated_allocator_type>::get( \ - *h, ::asio::get_associated_allocator(*h))); \ + typedef typename ::asio::detail::get_default_allocator< \ + associated_allocator_type>::type default_allocator_type; \ + ASIO_REBIND_ALLOC(default_allocator_type, op) a( \ + ::asio::detail::get_default_allocator< \ + associated_allocator_type>::get( \ + ::asio::get_associated_allocator(*h))); \ a.deallocate(static_cast<op*>(v), 1); \ v = 0; \ } \ diff --git a/3rdparty/asio/include/asio/detail/handler_cont_helpers.hpp b/3rdparty/asio/include/asio/detail/handler_cont_helpers.hpp index 5d47465bdd4..9f8f971984f 100644 --- a/3rdparty/asio/include/asio/detail/handler_cont_helpers.hpp +++ b/3rdparty/asio/include/asio/detail/handler_cont_helpers.hpp @@ -2,7 +2,7 @@ // detail/handler_cont_helpers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/handler_invoke_helpers.hpp b/3rdparty/asio/include/asio/detail/handler_invoke_helpers.hpp deleted file mode 100644 index 86b8bf2b4b3..00000000000 --- a/3rdparty/asio/include/asio/detail/handler_invoke_helpers.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// -// detail/handler_invoke_helpers.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP -#define ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/memory.hpp" -#include "asio/handler_invoke_hook.hpp" - -#include "asio/detail/push_options.hpp" - -// Calls to asio_handler_invoke must be made from a namespace that does not -// contain overloads of this function. The asio_handler_invoke_helpers -// namespace is defined here for that purpose. -namespace asio_handler_invoke_helpers { - -#if defined(ASIO_NO_DEPRECATED) -template <typename Function, typename Context> -inline void error_if_hook_is_defined(Function& function, Context& context) -{ - using asio::asio_handler_invoke; - // If you get an error here it is because some of your handlers still - // overload asio_handler_invoke, but this hook is no longer used. - (void)static_cast<asio::asio_handler_invoke_is_no_longer_used>( - asio_handler_invoke(function, asio::detail::addressof(context))); -} -#endif // defined(ASIO_NO_DEPRECATED) - -template <typename Function, typename Context> -inline void invoke(Function& function, Context& context) -{ -#if !defined(ASIO_HAS_HANDLER_HOOKS) - Function tmp(function); - tmp(); -#elif defined(ASIO_NO_DEPRECATED) - // The asio_handler_invoke hook is no longer used to invoke the function. - (void)&error_if_hook_is_defined<Function, Context>; - (void)context; - function(); -#else - using asio::asio_handler_invoke; - asio_handler_invoke(function, asio::detail::addressof(context)); -#endif -} - -template <typename Function, typename Context> -inline void invoke(const Function& function, Context& context) -{ -#if !defined(ASIO_HAS_HANDLER_HOOKS) - Function tmp(function); - tmp(); -#elif defined(ASIO_NO_DEPRECATED) - // The asio_handler_invoke hook is no longer used to invoke the function. - (void)&error_if_hook_is_defined<const Function, Context>; - (void)context; - Function tmp(function); - tmp(); -#else - using asio::asio_handler_invoke; - asio_handler_invoke(function, asio::detail::addressof(context)); -#endif -} - -} // namespace asio_handler_invoke_helpers - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP diff --git a/3rdparty/asio/include/asio/detail/handler_tracking.hpp b/3rdparty/asio/include/asio/detail/handler_tracking.hpp index 14195cd4389..f47c777a2d6 100644 --- a/3rdparty/asio/include/asio/detail/handler_tracking.hpp +++ b/3rdparty/asio/include/asio/detail/handler_tracking.hpp @@ -2,7 +2,7 @@ // detail/handler_tracking.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -99,8 +99,8 @@ public: private: // Disallow copying and assignment. - location(const location&) ASIO_DELETED; - location& operator=(const location&) ASIO_DELETED; + location(const location&) = delete; + location& operator=(const location&) = delete; friend class handler_tracking; const char* file_; diff --git a/3rdparty/asio/include/asio/detail/handler_type_requirements.hpp b/3rdparty/asio/include/asio/detail/handler_type_requirements.hpp index ced34e8e014..54c53b9b6e3 100644 --- a/3rdparty/asio/include/asio/detail/handler_type_requirements.hpp +++ b/3rdparty/asio/include/asio/detail/handler_type_requirements.hpp @@ -2,7 +2,7 @@ // detail/handler_type_requirements.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -64,7 +64,7 @@ template <typename Handler> auto zero_arg_copyable_handler_test(Handler h, void*) -> decltype( sizeof(Handler(static_cast<const Handler&>(h))), - (ASIO_MOVE_OR_LVALUE(Handler)(h)()), + (static_cast<Handler&&>(h)()), char(0)); template <typename Handler> @@ -73,8 +73,8 @@ 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(ASIO_MOVE_CAST(Handler)(h))), - (ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1)), + sizeof(Handler(static_cast<Handler&&>(h))), + (static_cast<Handler&&>(h)(*a1)), char(0)); template <typename Handler> @@ -83,8 +83,8 @@ 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(ASIO_MOVE_CAST(Handler)(h))), - (ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1, *a2)), + sizeof(Handler(static_cast<Handler&&>(h))), + (static_cast<Handler&&>(h)(*a1, *a2)), char(0)); template <typename Handler> @@ -93,9 +93,9 @@ 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(ASIO_MOVE_CAST(Handler)(h))), - (ASIO_MOVE_OR_LVALUE(Handler)(h)( - *a1, ASIO_MOVE_CAST(Arg2)(*a2))), + sizeof(Handler(static_cast<Handler&&>(h))), + (static_cast<Handler&&>(h)( + *a1, static_cast<Arg2&&>(*a2))), char(0)); template <typename Handler> @@ -114,15 +114,9 @@ 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(ASIO_HAS_MOVE) template <typename T> T rvref(); template <typename T> T rvref(T); template <typename T> T rorlvref(); -#else // defined(ASIO_HAS_MOVE) -template <typename T> const T& rvref(); -template <typename T> const T& rvref(T); -template <typename T> T& rorlvref(); -#endif // defined(ASIO_HAS_MOVE) template <typename T> char argbyv(T); template <int> diff --git a/3rdparty/asio/include/asio/detail/handler_work.hpp b/3rdparty/asio/include/asio/detail/handler_work.hpp index c564eb944c3..596d076327a 100644 --- a/3rdparty/asio/include/asio/detail/handler_work.hpp +++ b/3rdparty/asio/include/asio/detail/handler_work.hpp @@ -2,7 +2,7 @@ // detail/handler_work.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,12 +16,14 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" +#include "asio/associated_allocator.hpp" #include "asio/associated_executor.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" +#include "asio/associated_immediate_executor.hpp" +#include "asio/detail/initiate_dispatch.hpp" #include "asio/detail/type_traits.hpp" +#include "asio/detail/work_dispatcher.hpp" #include "asio/execution/allocator.hpp" #include "asio/execution/blocking.hpp" -#include "asio/execution/execute.hpp" #include "asio/execution/executor.hpp" #include "asio/execution/outstanding_work.hpp" #include "asio/executor_work_guard.hpp" @@ -36,23 +38,15 @@ class io_context; #if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) +class any_completion_executor; class any_io_executor; #endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) namespace execution { -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename...> class any_executor; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename, typename, typename, typename, typename, - typename, typename, typename, typename> class any_executor; - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - } // namespace execution namespace detail { @@ -62,31 +56,29 @@ template <typename Executor, typename CandidateExecutor = void, class handler_work_base { public: - explicit handler_work_base(int, int, const Executor& ex) ASIO_NOEXCEPT + explicit handler_work_base(int, int, const Executor& ex) noexcept : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) { } template <typename OtherExecutor> handler_work_base(bool /*base1_owns_work*/, const Executor& ex, - const OtherExecutor& /*candidate*/) ASIO_NOEXCEPT + const OtherExecutor& /*candidate*/) noexcept : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) { } - handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT + handler_work_base(const handler_work_base& other) noexcept : executor_(other.executor_) { } -#if defined(ASIO_HAS_MOVE) - handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT - : executor_(ASIO_MOVE_CAST(executor_type)(other.executor_)) + handler_work_base(handler_work_base&& other) noexcept + : executor_(static_cast<executor_type&&>(other.executor_)) { } -#endif // defined(ASIO_HAS_MOVE) - bool owns_work() const ASIO_NOEXCEPT + bool owns_work() const noexcept { return true; } @@ -94,19 +86,15 @@ public: template <typename Function, typename Handler> void dispatch(Function& function, Handler& handler) { - execution::execute( - asio::prefer(executor_, - execution::blocking.possibly, - execution::allocator((get_associated_allocator)(handler))), - ASIO_MOVE_CAST(Function)(function)); + asio::prefer(executor_, + execution::allocator((get_associated_allocator)(handler)) + ).execute(static_cast<Function&&>(function)); } private: - typedef typename decay< - typename prefer_result<Executor, - execution::outstanding_work_t::tracked_t - >::type - >::type executor_type; + typedef decay_t< + prefer_result_t<Executor, execution::outstanding_work_t::tracked_t> + > executor_type; executor_type executor_; }; @@ -115,14 +103,15 @@ template <typename Executor, typename CandidateExecutor, typename IoContext, typename PolymorphicExecutor> class handler_work_base<Executor, CandidateExecutor, IoContext, PolymorphicExecutor, - typename enable_if< + enable_if_t< !execution::is_executor<Executor>::value && (!is_same<Executor, PolymorphicExecutor>::value || !is_same<CandidateExecutor, void>::value) - >::type> + > + > { public: - explicit handler_work_base(int, int, const Executor& ex) ASIO_NOEXCEPT + explicit handler_work_base(int, int, const Executor& ex) noexcept : executor_(ex), owns_work_(true) { @@ -130,7 +119,7 @@ public: } handler_work_base(bool /*base1_owns_work*/, const Executor& ex, - const Executor& candidate) ASIO_NOEXCEPT + const Executor& candidate) noexcept : executor_(ex), owns_work_(ex != candidate) { @@ -140,14 +129,14 @@ public: template <typename OtherExecutor> handler_work_base(bool /*base1_owns_work*/, const Executor& ex, - const OtherExecutor& /*candidate*/) ASIO_NOEXCEPT + const OtherExecutor& /*candidate*/) noexcept : executor_(ex), owns_work_(true) { executor_.on_work_started(); } - handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT + handler_work_base(const handler_work_base& other) noexcept : executor_(other.executor_), owns_work_(other.owns_work_) { @@ -155,14 +144,12 @@ public: executor_.on_work_started(); } -#if defined(ASIO_HAS_MOVE) - handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT - : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)), + handler_work_base(handler_work_base&& other) noexcept + : executor_(static_cast<Executor&&>(other.executor_)), owns_work_(other.owns_work_) { other.owns_work_ = false; } -#endif // defined(ASIO_HAS_MOVE) ~handler_work_base() { @@ -170,7 +157,7 @@ public: executor_.on_work_finished(); } - bool owns_work() const ASIO_NOEXCEPT + bool owns_work() const noexcept { return owns_work_; } @@ -178,7 +165,7 @@ public: template <typename Function, typename Handler> void dispatch(Function& function, Handler& handler) { - executor_.dispatch(ASIO_MOVE_CAST(Function)(function), + executor_.dispatch(static_cast<Function&&>(function), asio::get_associated_allocator(handler)); } @@ -189,30 +176,31 @@ private: template <typename Executor, typename IoContext, typename PolymorphicExecutor> class handler_work_base<Executor, void, IoContext, PolymorphicExecutor, - typename enable_if< + enable_if_t< is_same< Executor, typename IoContext::executor_type >::value - >::type> + > + > { public: explicit handler_work_base(int, int, const Executor&) { } - bool owns_work() const ASIO_NOEXCEPT + bool owns_work() const noexcept { return false; } template <typename Function, typename Handler> - void dispatch(Function& function, Handler& handler) + void dispatch(Function& function, Handler&) { // When using a native implementation, I/O completion handlers are // already dispatched according to the execution context's executor's // rules. We can call the function directly. - asio_handler_invoke_helpers::invoke(function, handler); + static_cast<Function&&>(function)(); } }; @@ -220,7 +208,7 @@ template <typename Executor, typename IoContext> class handler_work_base<Executor, void, IoContext, Executor> { public: - explicit handler_work_base(int, int, const Executor& ex) ASIO_NOEXCEPT + explicit handler_work_base(int, int, const Executor& ex) noexcept #if !defined(ASIO_NO_TYPEID) : executor_( ex.target_type() == typeid(typename IoContext::executor_type) @@ -234,7 +222,7 @@ public: } handler_work_base(bool /*base1_owns_work*/, const Executor& ex, - const Executor& candidate) ASIO_NOEXCEPT + const Executor& candidate) noexcept : executor_(ex != candidate ? ex : Executor()) { if (executor_) @@ -243,25 +231,23 @@ public: template <typename OtherExecutor> handler_work_base(const Executor& ex, - const OtherExecutor&) ASIO_NOEXCEPT + const OtherExecutor&) noexcept : executor_(ex) { executor_.on_work_started(); } - handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT + handler_work_base(const handler_work_base& other) noexcept : executor_(other.executor_) { if (executor_) executor_.on_work_started(); } -#if defined(ASIO_HAS_MOVE) - handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT - : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)) + handler_work_base(handler_work_base&& other) noexcept + : executor_(static_cast<Executor&&>(other.executor_)) { } -#endif // defined(ASIO_HAS_MOVE) ~handler_work_base() { @@ -269,7 +255,7 @@ public: executor_.on_work_finished(); } - bool owns_work() const ASIO_NOEXCEPT + bool owns_work() const noexcept { return !!executor_; } @@ -277,7 +263,7 @@ public: template <typename Function, typename Handler> void dispatch(Function& function, Handler& handler) { - executor_.dispatch(ASIO_MOVE_CAST(Function)(function), + executor_.dispatch(static_cast<Function&&>(function), asio::get_associated_allocator(handler)); } @@ -285,34 +271,15 @@ private: Executor executor_; }; -template < -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - typename... SupportableProperties, -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8, typename T9, -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - typename CandidateExecutor, typename IoContext, - typename PolymorphicExecutor> -class handler_work_base< -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - execution::any_executor<SupportableProperties...>, -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - execution::any_executor<T1, T2, T3, T4, T5, T6, T7, T8, T9>, -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) +template <typename... SupportableProperties, typename CandidateExecutor, + typename IoContext, typename PolymorphicExecutor> +class handler_work_base<execution::any_executor<SupportableProperties...>, CandidateExecutor, IoContext, PolymorphicExecutor> { public: - typedef -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - execution::any_executor<SupportableProperties...> -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - execution::any_executor<T1, T2, T3, T4, T5, T6, T7, T8, T9> -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - executor_type; + typedef execution::any_executor<SupportableProperties...> executor_type; - explicit handler_work_base(int, int, - const executor_type& ex) ASIO_NOEXCEPT + explicit handler_work_base(int, int, const executor_type& ex) noexcept #if !defined(ASIO_NO_TYPEID) : executor_( ex.target_type() == typeid(typename IoContext::executor_type) @@ -325,7 +292,7 @@ public: } handler_work_base(bool base1_owns_work, const executor_type& ex, - const executor_type& candidate) ASIO_NOEXCEPT + const executor_type& candidate) noexcept : executor_( !base1_owns_work && ex == candidate ? executor_type() @@ -335,24 +302,22 @@ public: template <typename OtherExecutor> handler_work_base(bool /*base1_owns_work*/, const executor_type& ex, - const OtherExecutor& /*candidate*/) ASIO_NOEXCEPT + const OtherExecutor& /*candidate*/) noexcept : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) { } - handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT + handler_work_base(const handler_work_base& other) noexcept : executor_(other.executor_) { } -#if defined(ASIO_HAS_MOVE) - handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT - : executor_(ASIO_MOVE_CAST(executor_type)(other.executor_)) + handler_work_base(handler_work_base&& other) noexcept + : executor_(static_cast<executor_type&&>(other.executor_)) { } -#endif // defined(ASIO_HAS_MOVE) - bool owns_work() const ASIO_NOEXCEPT + bool owns_work() const noexcept { return !!executor_; } @@ -360,9 +325,7 @@ public: template <typename Function, typename Handler> void dispatch(Function& function, Handler&) { - execution::execute( - asio::prefer(executor_, execution::blocking.possibly), - ASIO_MOVE_CAST(Function)(function)); + executor_.execute(static_cast<Function&&>(function)); } private: @@ -376,18 +339,17 @@ template <typename Executor, typename CandidateExecutor, class handler_work_base< Executor, CandidateExecutor, IoContext, PolymorphicExecutor, - typename enable_if< - is_same< - Executor, - any_io_executor - >::value - >::type> + enable_if_t< + is_same<Executor, any_completion_executor>::value + || is_same<Executor, any_io_executor>::value + > + > { public: typedef Executor executor_type; explicit handler_work_base(int, int, - const executor_type& ex) ASIO_NOEXCEPT + const executor_type& ex) noexcept #if !defined(ASIO_NO_TYPEID) : executor_( ex.target_type() == typeid(typename IoContext::executor_type) @@ -400,7 +362,7 @@ public: } handler_work_base(bool base1_owns_work, const executor_type& ex, - const executor_type& candidate) ASIO_NOEXCEPT + const executor_type& candidate) noexcept : executor_( !base1_owns_work && ex == candidate ? executor_type() @@ -410,24 +372,22 @@ public: template <typename OtherExecutor> handler_work_base(bool /*base1_owns_work*/, const executor_type& ex, - const OtherExecutor& /*candidate*/) ASIO_NOEXCEPT + const OtherExecutor& /*candidate*/) noexcept : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) { } - handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT + handler_work_base(const handler_work_base& other) noexcept : executor_(other.executor_) { } -#if defined(ASIO_HAS_MOVE) - handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT - : executor_(ASIO_MOVE_CAST(executor_type)(other.executor_)) + handler_work_base(handler_work_base&& other) noexcept + : executor_(static_cast<executor_type&&>(other.executor_)) { } -#endif // defined(ASIO_HAS_MOVE) - bool owns_work() const ASIO_NOEXCEPT + bool owns_work() const noexcept { return !!executor_; } @@ -435,9 +395,7 @@ public: template <typename Function, typename Handler> void dispatch(Function& function, Handler&) { - execution::execute( - asio::prefer(executor_, execution::blocking.possibly), - ASIO_MOVE_CAST(Function)(function)); + executor_.execute(static_cast<Function&&>(function)); } private: @@ -449,15 +407,14 @@ private: template <typename Handler, typename IoExecutor, typename = void> class handler_work : handler_work_base<IoExecutor>, - handler_work_base<typename associated_executor< - Handler, IoExecutor>::type, IoExecutor> + handler_work_base<associated_executor_t<Handler, IoExecutor>, IoExecutor> { public: typedef handler_work_base<IoExecutor> base1_type; - typedef handler_work_base<typename associated_executor< - Handler, IoExecutor>::type, IoExecutor> base2_type; + typedef handler_work_base<associated_executor_t<Handler, IoExecutor>, + IoExecutor> base2_type; - handler_work(Handler& handler, const IoExecutor& io_ex) ASIO_NOEXCEPT + handler_work(Handler& handler, const IoExecutor& io_ex) noexcept : base1_type(0, 0, io_ex), base2_type(base1_type::owns_work(), asio::get_associated_executor(handler, io_ex), io_ex) @@ -472,7 +429,7 @@ public: // When using a native implementation, I/O completion handlers are // already dispatched according to the execution context's executor's // rules. We can call the function directly. - asio_handler_invoke_helpers::invoke(function, handler); + static_cast<Function&&>(function)(); } else { @@ -484,18 +441,19 @@ public: template <typename Handler, typename IoExecutor> class handler_work< Handler, IoExecutor, - typename enable_if< + enable_if_t< is_same< typename associated_executor<Handler, IoExecutor>::asio_associated_executor_is_unspecialised, void >::value - >::type> : handler_work_base<IoExecutor> + > + > : handler_work_base<IoExecutor> { public: typedef handler_work_base<IoExecutor> base1_type; - handler_work(Handler&, const IoExecutor& io_ex) ASIO_NOEXCEPT + handler_work(Handler&, const IoExecutor& io_ex) noexcept : base1_type(0, 0, io_ex) { } @@ -508,7 +466,7 @@ public: // When using a native implementation, I/O completion handlers are // already dispatched according to the execution context's executor's // rules. We can call the function directly. - asio_handler_invoke_helpers::invoke(function, handler); + static_cast<Function&&>(function)(); } else { @@ -517,6 +475,34 @@ public: } }; +template <typename Handler, typename IoExecutor> +class immediate_handler_work +{ +public: + typedef handler_work<Handler, IoExecutor> handler_work_type; + + explicit immediate_handler_work(handler_work_type&& w) + : handler_work_(static_cast<handler_work_type&&>(w)) + { + } + + template <typename Function> + void complete(Function& function, Handler& handler, const void* io_ex) + { + typedef associated_immediate_executor_t<Handler, IoExecutor> + immediate_ex_type; + + immediate_ex_type immediate_ex = (get_associated_immediate_executor)( + handler, *static_cast<const IoExecutor*>(io_ex)); + + (initiate_dispatch_with_executor<immediate_ex_type>(immediate_ex))( + static_cast<Function&&>(function)); + } + +private: + handler_work_type handler_work_; +}; + } // namespace detail } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/hash_map.hpp b/3rdparty/asio/include/asio/detail/hash_map.hpp index 78edec8bdd1..e23de914a18 100644 --- a/3rdparty/asio/include/asio/detail/hash_map.hpp +++ b/3rdparty/asio/include/asio/detail/hash_map.hpp @@ -2,7 +2,7 @@ // detail/hash_map.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp b/3rdparty/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp index d7c5e35ba84..372ce426e57 100644 --- a/3rdparty/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp +++ b/3rdparty/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp @@ -2,7 +2,7 @@ // detail/impl/buffer_sequence_adapter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/descriptor_ops.ipp b/3rdparty/asio/include/asio/detail/impl/descriptor_ops.ipp index 9abf204a828..c56a512e462 100644 --- a/3rdparty/asio/include/asio/detail/impl/descriptor_ops.ipp +++ b/3rdparty/asio/include/asio/detail/impl/descriptor_ops.ipp @@ -2,7 +2,7 @@ // detail/impl/descriptor_ops.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -37,6 +37,14 @@ int open(const char* path, int flags, asio::error_code& ec) return result; } +int open(const char* path, int flags, + unsigned mode, asio::error_code& ec) +{ + int result = ::open(path, flags, mode); + get_last_error(ec, result < 0); + return result; +} + int close(int d, state_type& state, asio::error_code& ec) { int result = 0; @@ -61,7 +69,25 @@ int close(int d, state_type& state, asio::error_code& ec) ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK); #else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) ioctl_arg_type arg = 0; +# if defined(ENOTTY) || defined(ENOTCAPABLE) + result = ::ioctl(d, FIONBIO, &arg); + get_last_error(ec, result < 0); + if (false +# if defined(ENOTTY) + || ec.value() == ENOTTY +# endif // defined(ENOTTY) +# if defined(ENOTCAPABLE) + || ec.value() == ENOTCAPABLE +# endif // defined(ENOTCAPABLE) + ) + { + int flags = ::fcntl(d, F_GETFL, 0); + if (flags >= 0) + ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK); + } +# else // defined(ENOTTY) || defined(ENOTCAPABLE) ::ioctl(d, FIONBIO, &arg); +# endif // defined(ENOTTY) || defined(ENOTCAPABLE) #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) state &= ~non_blocking; @@ -95,6 +121,26 @@ bool set_user_non_blocking(int d, state_type& state, ioctl_arg_type arg = (value ? 1 : 0); int result = ::ioctl(d, FIONBIO, &arg); get_last_error(ec, result < 0); +# if defined(ENOTTY) || defined(ENOTCAPABLE) + if (false +# if defined(ENOTTY) + || ec.value() == ENOTTY +# endif // defined(ENOTTY) +# if defined(ENOTCAPABLE) + || ec.value() == ENOTCAPABLE +# endif // defined(ENOTCAPABLE) + ) + { + result = ::fcntl(d, F_GETFL, 0); + get_last_error(ec, result < 0); + if (result >= 0) + { + int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); + result = ::fcntl(d, F_SETFL, flag); + get_last_error(ec, result < 0); + } + } +# endif // defined(ENOTTY) || defined(ENOTCAPABLE) #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) if (result >= 0) @@ -145,6 +191,26 @@ bool set_internal_non_blocking(int d, state_type& state, ioctl_arg_type arg = (value ? 1 : 0); int result = ::ioctl(d, FIONBIO, &arg); get_last_error(ec, result < 0); +# if defined(ENOTTY) || defined(ENOTCAPABLE) + if (false +# if defined(ENOTTY) + || ec.value() == ENOTTY +# endif // defined(ENOTTY) +# if defined(ENOTCAPABLE) + || ec.value() == ENOTCAPABLE +# endif // defined(ENOTCAPABLE) + ) + { + result = ::fcntl(d, F_GETFL, 0); + get_last_error(ec, result < 0); + if (result >= 0) + { + int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); + result = ::fcntl(d, F_SETFL, flag); + get_last_error(ec, result < 0); + } + } +# endif // defined(ENOTTY) || defined(ENOTCAPABLE) #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) if (result >= 0) @@ -171,7 +237,7 @@ std::size_t sync_read(int d, state_type state, buf* bufs, // A request to read 0 bytes on a stream is a no-op. if (all_empty) { - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } @@ -217,7 +283,7 @@ std::size_t sync_read1(int d, state_type state, void* data, // A request to read 0 bytes on a stream is a no-op. if (size == 0) { - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } @@ -339,7 +405,7 @@ std::size_t sync_write(int d, state_type state, const buf* bufs, // A request to write 0 bytes on a stream is a no-op. if (all_empty) { - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } @@ -378,7 +444,7 @@ std::size_t sync_write1(int d, state_type state, const void* data, // A request to write 0 bytes on a stream is a no-op. if (size == 0) { - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } @@ -467,6 +533,323 @@ bool non_blocking_write1(int d, const void* data, std::size_t size, } } +#if defined(ASIO_HAS_FILE) + +std::size_t sync_read_at(int d, state_type state, uint64_t offset, + buf* bufs, std::size_t count, bool all_empty, asio::error_code& ec) +{ + if (d == -1) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // A request to read 0 bytes on a stream is a no-op. + if (all_empty) + { + asio::error::clear(ec); + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = ::preadv(d, bufs, static_cast<int>(count), offset); + get_last_error(ec, bytes < 0); + + // Check if operation succeeded. + if (bytes > 0) + return bytes; + + // Check for EOF. + if (bytes == 0) + { + ec = asio::error::eof; + return 0; + } + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != asio::error::would_block + && ec != asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_read(d, 0, ec) < 0) + return 0; + } +} + +std::size_t sync_read_at1(int d, state_type state, uint64_t offset, + void* data, std::size_t size, asio::error_code& ec) +{ + if (d == -1) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // A request to read 0 bytes on a stream is a no-op. + if (size == 0) + { + asio::error::clear(ec); + return 0; + } + + // Read some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = ::pread(d, data, size, offset); + get_last_error(ec, bytes < 0); + + // Check if operation succeeded. + if (bytes > 0) + return bytes; + + // Check for EOF. + if (bytes == 0) + { + ec = asio::error::eof; + return 0; + } + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != asio::error::would_block + && ec != asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_read(d, 0, ec) < 0) + return 0; + } +} + +bool non_blocking_read_at(int d, uint64_t offset, buf* bufs, std::size_t count, + asio::error_code& ec, std::size_t& bytes_transferred) +{ + for (;;) + { + // Read some data. + signed_size_type bytes = ::preadv(d, bufs, static_cast<int>(count), offset); + get_last_error(ec, bytes < 0); + + // Check for EOF. + if (bytes == 0) + { + ec = asio::error::eof; + return true; + } + + // Check if operation succeeded. + if (bytes > 0) + { + bytes_transferred = bytes; + return true; + } + + // Retry operation if interrupted by signal. + if (ec == asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + return false; + + // Operation failed. + bytes_transferred = 0; + return true; + } +} + +bool non_blocking_read_at1(int d, uint64_t offset, void* data, std::size_t size, + asio::error_code& ec, std::size_t& bytes_transferred) +{ + for (;;) + { + // Read some data. + signed_size_type bytes = ::pread(d, data, size, offset); + get_last_error(ec, bytes < 0); + + // Check for EOF. + if (bytes == 0) + { + ec = asio::error::eof; + return true; + } + + // Check if operation succeeded. + if (bytes > 0) + { + bytes_transferred = bytes; + return true; + } + + // Retry operation if interrupted by signal. + if (ec == asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + return false; + + // Operation failed. + bytes_transferred = 0; + return true; + } +} + +std::size_t sync_write_at(int d, state_type state, uint64_t offset, + const buf* bufs, std::size_t count, bool all_empty, + asio::error_code& ec) +{ + if (d == -1) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // A request to write 0 bytes on a stream is a no-op. + if (all_empty) + { + asio::error::clear(ec); + return 0; + } + + // Write some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = ::pwritev(d, + bufs, static_cast<int>(count), offset); + get_last_error(ec, bytes < 0); + + // Check if operation succeeded. + if (bytes > 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != asio::error::would_block + && ec != asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_write(d, 0, ec) < 0) + return 0; + } +} + +std::size_t sync_write_at1(int d, state_type state, uint64_t offset, + const void* data, std::size_t size, asio::error_code& ec) +{ + if (d == -1) + { + ec = asio::error::bad_descriptor; + return 0; + } + + // A request to write 0 bytes on a stream is a no-op. + if (size == 0) + { + asio::error::clear(ec); + return 0; + } + + // Write some data. + for (;;) + { + // Try to complete the operation without blocking. + signed_size_type bytes = ::pwrite(d, data, size, offset); + get_last_error(ec, bytes < 0); + + // Check if operation succeeded. + if (bytes > 0) + return bytes; + + // Operation failed. + if ((state & user_set_non_blocking) + || (ec != asio::error::would_block + && ec != asio::error::try_again)) + return 0; + + // Wait for descriptor to become ready. + if (descriptor_ops::poll_write(d, 0, ec) < 0) + return 0; + } +} + +bool non_blocking_write_at(int d, uint64_t offset, + const buf* bufs, std::size_t count, + asio::error_code& ec, std::size_t& bytes_transferred) +{ + for (;;) + { + // Write some data. + signed_size_type bytes = ::pwritev(d, + bufs, static_cast<int>(count), offset); + get_last_error(ec, bytes < 0); + + // Check if operation succeeded. + if (bytes >= 0) + { + bytes_transferred = bytes; + return true; + } + + // Retry operation if interrupted by signal. + if (ec == asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + return false; + + // Operation failed. + bytes_transferred = 0; + return true; + } +} + +bool non_blocking_write_at1(int d, uint64_t offset, + const void* data, std::size_t size, + asio::error_code& ec, std::size_t& bytes_transferred) +{ + for (;;) + { + // Write some data. + signed_size_type bytes = ::pwrite(d, data, size, offset); + get_last_error(ec, bytes < 0); + + // Check if operation succeeded. + if (bytes >= 0) + { + bytes_transferred = bytes; + return true; + } + + // Retry operation if interrupted by signal. + if (ec == asio::error::interrupted) + continue; + + // Check if we need to run the operation again. + if (ec == asio::error::would_block + || ec == asio::error::try_again) + return false; + + // Operation failed. + bytes_transferred = 0; + return true; + } +} + +#endif // defined(ASIO_HAS_FILE) + int ioctl(int d, state_type& state, long cmd, ioctl_arg_type* arg, asio::error_code& ec) { diff --git a/3rdparty/asio/include/asio/detail/impl/dev_poll_reactor.hpp b/3rdparty/asio/include/asio/detail/impl/dev_poll_reactor.hpp index f9babbb53a6..b483e44fd1c 100644 --- a/3rdparty/asio/include/asio/detail/impl/dev_poll_reactor.hpp +++ b/3rdparty/asio/include/asio/detail/impl/dev_poll_reactor.hpp @@ -2,7 +2,7 @@ // detail/impl/dev_poll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -27,7 +27,7 @@ namespace asio { namespace detail { inline void dev_poll_reactor::post_immediate_completion( - reactor_op* op, bool is_continuation) + operation* op, bool is_continuation) const { scheduler_.post_immediate_completion(op, is_continuation); } @@ -77,6 +77,18 @@ std::size_t dev_poll_reactor::cancel_timer(timer_queue<Time_Traits>& queue, } template <typename Time_Traits> +void dev_poll_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data* timer, + void* cancellation_key) +{ + asio::detail::mutex::scoped_lock lock(mutex_); + op_queue<operation> ops; + queue.cancel_timer_by_key(timer, ops, cancellation_key); + lock.unlock(); + scheduler_.post_deferred_completions(ops); +} + +template <typename Time_Traits> 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) diff --git a/3rdparty/asio/include/asio/detail/impl/dev_poll_reactor.ipp b/3rdparty/asio/include/asio/detail/impl/dev_poll_reactor.ipp index 42efcd624aa..c9c53fbeafd 100644 --- a/3rdparty/asio/include/asio/detail/impl/dev_poll_reactor.ipp +++ b/3rdparty/asio/include/asio/detail/impl/dev_poll_reactor.ipp @@ -2,7 +2,7 @@ // detail/impl/dev_poll_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -148,15 +148,24 @@ void dev_poll_reactor::move_descriptor(socket_type, { } +void dev_poll_reactor::call_post_immediate_completion( + operation* op, bool is_continuation, const void* self) +{ + static_cast<const dev_poll_reactor*>(self)->post_immediate_completion( + op, is_continuation); +} + void dev_poll_reactor::start_op(int op_type, socket_type descriptor, dev_poll_reactor::per_descriptor_data&, reactor_op* op, - bool is_continuation, bool allow_speculative) + bool is_continuation, bool allow_speculative, + void (*on_immediate)(operation*, bool, const void*), + const void* immediate_arg) { asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) { - post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } @@ -169,7 +178,7 @@ void dev_poll_reactor::start_op(int op_type, socket_type descriptor, if (op->perform()) { lock.unlock(); - scheduler_.post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } } diff --git a/3rdparty/asio/include/asio/detail/impl/epoll_reactor.hpp b/3rdparty/asio/include/asio/detail/impl/epoll_reactor.hpp index 3055085f4a3..4fffeb75924 100644 --- a/3rdparty/asio/include/asio/detail/impl/epoll_reactor.hpp +++ b/3rdparty/asio/include/asio/detail/impl/epoll_reactor.hpp @@ -2,7 +2,7 @@ // detail/impl/epoll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -25,7 +25,7 @@ namespace asio { namespace detail { inline void epoll_reactor::post_immediate_completion( - operation* op, bool is_continuation) + operation* op, bool is_continuation) const { scheduler_.post_immediate_completion(op, is_continuation); } diff --git a/3rdparty/asio/include/asio/detail/impl/epoll_reactor.ipp b/3rdparty/asio/include/asio/detail/impl/epoll_reactor.ipp index 79ec5410767..51795bda40c 100644 --- a/3rdparty/asio/include/asio/detail/impl/epoll_reactor.ipp +++ b/3rdparty/asio/include/asio/detail/impl/epoll_reactor.ipp @@ -2,7 +2,7 @@ // detail/impl/epoll_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -229,14 +229,23 @@ void epoll_reactor::move_descriptor(socket_type, source_descriptor_data = 0; } +void epoll_reactor::call_post_immediate_completion( + operation* op, bool is_continuation, const void* self) +{ + static_cast<const epoll_reactor*>(self)->post_immediate_completion( + op, is_continuation); +} + void epoll_reactor::start_op(int op_type, socket_type descriptor, epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op, - bool is_continuation, bool allow_speculative) + bool is_continuation, bool allow_speculative, + void (*on_immediate)(operation*, bool, const void*), + const void* immediate_arg) { if (!descriptor_data) { op->ec_ = asio::error::bad_descriptor; - post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } @@ -244,7 +253,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor, if (descriptor_data->shutdown_) { - post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } @@ -262,7 +271,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor, if (descriptor_data->registered_events_ != 0) descriptor_data->try_speculative_[op_type] = false; descriptor_lock.unlock(); - scheduler_.post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } } @@ -270,7 +279,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor, if (descriptor_data->registered_events_ == 0) { op->ec_ = asio::error::operation_not_supported; - scheduler_.post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } @@ -289,7 +298,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor, { op->ec_ = asio::error_code(errno, asio::error::get_system_category()); - scheduler_.post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } } @@ -298,7 +307,7 @@ void epoll_reactor::start_op(int op_type, socket_type descriptor, else if (descriptor_data->registered_events_ == 0) { op->ec_ = asio::error::operation_not_supported; - scheduler_.post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } else diff --git a/3rdparty/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp b/3rdparty/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp index 8ed61f8b7c9..2e970d8850b 100644 --- a/3rdparty/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp +++ b/3rdparty/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp @@ -2,7 +2,7 @@ // detail/impl/eventfd_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/3rdparty/asio/include/asio/detail/impl/handler_tracking.ipp b/3rdparty/asio/include/asio/detail/impl/handler_tracking.ipp index 79a87df09b5..f4e3e3b501a 100644 --- a/3rdparty/asio/include/asio/detail/impl/handler_tracking.ipp +++ b/3rdparty/asio/include/asio/detail/impl/handler_tracking.ipp @@ -2,7 +2,7 @@ // detail/impl/handler_tracking.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -29,7 +29,7 @@ #if defined(ASIO_HAS_BOOST_DATE_TIME) # include "asio/time_traits.hpp" -#elif defined(ASIO_HAS_CHRONO) +#else // defined(ASIO_HAS_BOOST_DATE_TIME) # include "asio/detail/chrono.hpp" # include "asio/detail/chrono_time_traits.hpp" # include "asio/wait_traits.hpp" @@ -57,12 +57,12 @@ 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(ASIO_HAS_CHRONO) +#else // defined(ASIO_HAS_BOOST_DATE_TIME) typedef chrono_time_traits<chrono::system_clock, - asio::wait_traits<chrono::system_clock> > traits_helper; + asio::wait_traits<chrono::system_clock>> traits_helper; traits_helper::posix_time_duration now( chrono::system_clock::now().time_since_epoch()); -#endif +#endif // defined(ASIO_HAS_BOOST_DATE_TIME) seconds = static_cast<uint64_t>(now.total_seconds()); microseconds = static_cast<uint64_t>(now.total_microseconds() % 1000000); } @@ -365,7 +365,9 @@ void handler_tracking::write_line(const char* format, ...) va_start(args, format); char line[256] = ""; -#if defined(ASIO_HAS_SECURE_RTL) +#if defined(ASIO_HAS_SNPRINTF) + int length = vsnprintf(line, sizeof(line), format, args); +#elif defined(ASIO_HAS_SECURE_RTL) int length = vsprintf_s(line, sizeof(line), format, args); #else // defined(ASIO_HAS_SECURE_RTL) int length = vsprintf(line, format, args); diff --git a/3rdparty/asio/include/asio/detail/impl/io_uring_descriptor_service.ipp b/3rdparty/asio/include/asio/detail/impl/io_uring_descriptor_service.ipp new file mode 100644 index 00000000000..21b9e232cfb --- /dev/null +++ b/3rdparty/asio/include/asio/detail/impl/io_uring_descriptor_service.ipp @@ -0,0 +1,205 @@ +// +// detail/impl/io_uring_descriptor_service.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_IO_URING_DESCRIPTOR_SERVICE_IPP +#define ASIO_DETAIL_IMPL_IO_URING_DESCRIPTOR_SERVICE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/error.hpp" +#include "asio/detail/io_uring_descriptor_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +io_uring_descriptor_service::io_uring_descriptor_service( + execution_context& context) + : execution_context_service_base<io_uring_descriptor_service>(context), + io_uring_service_(asio::use_service<io_uring_service>(context)) +{ + io_uring_service_.init_task(); +} + +void io_uring_descriptor_service::shutdown() +{ +} + +void io_uring_descriptor_service::construct( + io_uring_descriptor_service::implementation_type& impl) +{ + impl.descriptor_ = -1; + impl.state_ = 0; + impl.io_object_data_ = 0; +} + +void io_uring_descriptor_service::move_construct( + io_uring_descriptor_service::implementation_type& impl, + io_uring_descriptor_service::implementation_type& other_impl) + noexcept +{ + impl.descriptor_ = other_impl.descriptor_; + other_impl.descriptor_ = -1; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + impl.io_object_data_ = other_impl.io_object_data_; + other_impl.io_object_data_ = 0; +} + +void io_uring_descriptor_service::move_assign( + io_uring_descriptor_service::implementation_type& impl, + io_uring_descriptor_service& /*other_service*/, + io_uring_descriptor_service::implementation_type& other_impl) +{ + destroy(impl); + + impl.descriptor_ = other_impl.descriptor_; + other_impl.descriptor_ = -1; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + impl.io_object_data_ = other_impl.io_object_data_; + other_impl.io_object_data_ = 0; +} + +void io_uring_descriptor_service::destroy( + io_uring_descriptor_service::implementation_type& impl) +{ + if (is_open(impl)) + { + ASIO_HANDLER_OPERATION((io_uring_service_.context(), + "descriptor", &impl, impl.descriptor_, "close")); + + io_uring_service_.deregister_io_object(impl.io_object_data_); + asio::error_code ignored_ec; + descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec); + io_uring_service_.cleanup_io_object(impl.io_object_data_); + } +} + +asio::error_code io_uring_descriptor_service::assign( + io_uring_descriptor_service::implementation_type& impl, + const native_handle_type& native_descriptor, asio::error_code& ec) +{ + if (is_open(impl)) + { + ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); + return ec; + } + + io_uring_service_.register_io_object(impl.io_object_data_); + + impl.descriptor_ = native_descriptor; + impl.state_ = descriptor_ops::possible_dup; + ec = success_ec_; + return ec; +} + +asio::error_code io_uring_descriptor_service::close( + io_uring_descriptor_service::implementation_type& impl, + asio::error_code& ec) +{ + if (is_open(impl)) + { + ASIO_HANDLER_OPERATION((io_uring_service_.context(), + "descriptor", &impl, impl.descriptor_, "close")); + + io_uring_service_.deregister_io_object(impl.io_object_data_); + descriptor_ops::close(impl.descriptor_, impl.state_, ec); + io_uring_service_.cleanup_io_object(impl.io_object_data_); + } + else + { + ec = success_ec_; + } + + // The descriptor is closed by the OS even if close() returns an error. + // + // (Actually, POSIX says the state of the descriptor is unspecified. On + // Linux the descriptor is apparently closed anyway; e.g. see + // http://lkml.org/lkml/2005/9/10/129 + construct(impl); + + ASIO_ERROR_LOCATION(ec); + return ec; +} + +io_uring_descriptor_service::native_handle_type +io_uring_descriptor_service::release( + io_uring_descriptor_service::implementation_type& impl) +{ + native_handle_type descriptor = impl.descriptor_; + + if (is_open(impl)) + { + ASIO_HANDLER_OPERATION((io_uring_service_.context(), + "descriptor", &impl, impl.descriptor_, "release")); + + io_uring_service_.deregister_io_object(impl.io_object_data_); + io_uring_service_.cleanup_io_object(impl.io_object_data_); + construct(impl); + } + + return descriptor; +} + +asio::error_code io_uring_descriptor_service::cancel( + io_uring_descriptor_service::implementation_type& impl, + asio::error_code& ec) +{ + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + ASIO_ERROR_LOCATION(ec); + return ec; + } + + ASIO_HANDLER_OPERATION((io_uring_service_.context(), + "descriptor", &impl, impl.descriptor_, "cancel")); + + io_uring_service_.cancel_ops(impl.io_object_data_); + ec = success_ec_; + return ec; +} + +void io_uring_descriptor_service::start_op( + io_uring_descriptor_service::implementation_type& impl, + int op_type, io_uring_operation* op, bool is_continuation, bool noop) +{ + if (!noop) + { + io_uring_service_.start_op(op_type, + impl.io_object_data_, op, is_continuation); + } + else + { + io_uring_service_.post_immediate_completion(op, is_continuation); + } +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IMPL_IO_URING_DESCRIPTOR_SERVICE_IPP diff --git a/3rdparty/asio/include/asio/detail/impl/io_uring_file_service.ipp b/3rdparty/asio/include/asio/detail/impl/io_uring_file_service.ipp new file mode 100644 index 00000000000..4742a7190d3 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/impl/io_uring_file_service.ipp @@ -0,0 +1,140 @@ +// +// detail/impl/io_uring_file_service.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_IO_URING_FILE_SERVICE_IPP +#define ASIO_DETAIL_IMPL_IO_URING_FILE_SERVICE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_FILE) \ + && defined(ASIO_HAS_IO_URING) + +#include <cstring> +#include <sys/stat.h> +#include "asio/detail/io_uring_file_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +io_uring_file_service::io_uring_file_service( + execution_context& context) + : execution_context_service_base<io_uring_file_service>(context), + descriptor_service_(context) +{ +} + +void io_uring_file_service::shutdown() +{ + descriptor_service_.shutdown(); +} + +asio::error_code io_uring_file_service::open( + io_uring_file_service::implementation_type& impl, + const char* path, file_base::flags open_flags, + asio::error_code& ec) +{ + if (is_open(impl)) + { + ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); + return ec; + } + + descriptor_ops::state_type state = 0; + int fd = descriptor_ops::open(path, static_cast<int>(open_flags), 0777, ec); + if (fd < 0) + { + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // We're done. Take ownership of the serial port descriptor. + if (descriptor_service_.assign(impl, fd, ec)) + { + asio::error_code ignored_ec; + descriptor_ops::close(fd, state, ignored_ec); + } + + (void)::posix_fadvise(native_handle(impl), 0, 0, + impl.is_stream_ ? POSIX_FADV_SEQUENTIAL : POSIX_FADV_RANDOM); + + ASIO_ERROR_LOCATION(ec); + return ec; +} + +uint64_t io_uring_file_service::size( + const io_uring_file_service::implementation_type& impl, + asio::error_code& ec) const +{ + struct stat s; + int result = ::fstat(native_handle(impl), &s); + descriptor_ops::get_last_error(ec, result != 0); + ASIO_ERROR_LOCATION(ec); + return !ec ? s.st_size : 0; +} + +asio::error_code io_uring_file_service::resize( + io_uring_file_service::implementation_type& impl, + uint64_t n, asio::error_code& ec) +{ + int result = ::ftruncate(native_handle(impl), n); + descriptor_ops::get_last_error(ec, result != 0); + ASIO_ERROR_LOCATION(ec); + return ec; +} + +asio::error_code io_uring_file_service::sync_all( + io_uring_file_service::implementation_type& impl, + asio::error_code& ec) +{ + int result = ::fsync(native_handle(impl)); + descriptor_ops::get_last_error(ec, result != 0); + return ec; +} + +asio::error_code io_uring_file_service::sync_data( + io_uring_file_service::implementation_type& impl, + asio::error_code& ec) +{ +#if defined(_POSIX_SYNCHRONIZED_IO) + int result = ::fdatasync(native_handle(impl)); +#else // defined(_POSIX_SYNCHRONIZED_IO) + int result = ::fsync(native_handle(impl)); +#endif // defined(_POSIX_SYNCHRONIZED_IO) + descriptor_ops::get_last_error(ec, result != 0); + ASIO_ERROR_LOCATION(ec); + return ec; +} + +uint64_t io_uring_file_service::seek( + io_uring_file_service::implementation_type& impl, int64_t offset, + file_base::seek_basis whence, asio::error_code& ec) +{ + int64_t result = ::lseek(native_handle(impl), offset, whence); + descriptor_ops::get_last_error(ec, result < 0); + ASIO_ERROR_LOCATION(ec); + return !ec ? static_cast<uint64_t>(result) : 0; +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_FILE) + // && defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IMPL_IO_URING_FILE_SERVICE_IPP diff --git a/3rdparty/asio/include/asio/detail/impl/io_uring_service.hpp b/3rdparty/asio/include/asio/detail/impl/io_uring_service.hpp new file mode 100644 index 00000000000..8dfab1e6d1d --- /dev/null +++ b/3rdparty/asio/include/asio/detail/impl/io_uring_service.hpp @@ -0,0 +1,112 @@ +// +// detail/impl/io_uring_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_IO_URING_SERVICE_HPP +#define ASIO_DETAIL_IMPL_IO_URING_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/scheduler.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +inline void io_uring_service::post_immediate_completion( + operation* op, bool is_continuation) +{ + scheduler_.post_immediate_completion(op, is_continuation); +} + +template <typename Time_Traits> +void io_uring_service::add_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_add_timer_queue(queue); +} + +template <typename Time_Traits> +void io_uring_service::remove_timer_queue(timer_queue<Time_Traits>& queue) +{ + do_remove_timer_queue(queue); +} + +template <typename Time_Traits> +void io_uring_service::schedule_timer(timer_queue<Time_Traits>& queue, + const typename Time_Traits::time_type& time, + typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op) +{ + mutex::scoped_lock lock(mutex_); + + if (shutdown_) + { + scheduler_.post_immediate_completion(op, false); + return; + } + + bool earliest = queue.enqueue_timer(time, timer, op); + scheduler_.work_started(); + if (earliest) + { + update_timeout(); + post_submit_sqes_op(lock); + } +} + +template <typename Time_Traits> +std::size_t io_uring_service::cancel_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& timer, + std::size_t max_cancelled) +{ + mutex::scoped_lock lock(mutex_); + op_queue<operation> ops; + std::size_t n = queue.cancel_timer(timer, ops, max_cancelled); + lock.unlock(); + scheduler_.post_deferred_completions(ops); + return n; +} + +template <typename Time_Traits> +void io_uring_service::cancel_timer_by_key(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data* timer, + void* cancellation_key) +{ + mutex::scoped_lock lock(mutex_); + op_queue<operation> ops; + queue.cancel_timer_by_key(timer, ops, cancellation_key); + lock.unlock(); + scheduler_.post_deferred_completions(ops); +} + +template <typename Time_Traits> +void io_uring_service::move_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& target, + typename timer_queue<Time_Traits>::per_timer_data& source) +{ + mutex::scoped_lock lock(mutex_); + op_queue<operation> ops; + queue.cancel_timer(target, ops); + queue.move_timer(target, source); + lock.unlock(); + scheduler_.post_deferred_completions(ops); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IMPL_IO_URING_SERVICE_HPP diff --git a/3rdparty/asio/include/asio/detail/impl/io_uring_service.ipp b/3rdparty/asio/include/asio/detail/impl/io_uring_service.ipp new file mode 100644 index 00000000000..740010cda11 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/impl/io_uring_service.ipp @@ -0,0 +1,914 @@ +// +// detail/impl/io_uring_service.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_IO_URING_SERVICE_IPP +#define ASIO_DETAIL_IMPL_IO_URING_SERVICE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include <cstddef> +#include <sys/eventfd.h> +#include "asio/detail/io_uring_service.hpp" +#include "asio/detail/reactor_op.hpp" +#include "asio/detail/scheduler.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +io_uring_service::io_uring_service(asio::execution_context& ctx) + : execution_context_service_base<io_uring_service>(ctx), + scheduler_(use_service<scheduler>(ctx)), + mutex_(ASIO_CONCURRENCY_HINT_IS_LOCKING( + REACTOR_REGISTRATION, scheduler_.concurrency_hint())), + outstanding_work_(0), + submit_sqes_op_(this), + pending_sqes_(0), + pending_submit_sqes_op_(false), + shutdown_(false), + timeout_(), + registration_mutex_(mutex_.enabled()), + reactor_(use_service<reactor>(ctx)), + reactor_data_(), + event_fd_(-1) +{ + reactor_.init_task(); + init_ring(); + register_with_reactor(); +} + +io_uring_service::~io_uring_service() +{ + if (ring_.ring_fd != -1) + ::io_uring_queue_exit(&ring_); + if (event_fd_ != -1) + ::close(event_fd_); +} + +void io_uring_service::shutdown() +{ + mutex::scoped_lock lock(mutex_); + shutdown_ = true; + lock.unlock(); + + op_queue<operation> ops; + + // Cancel all outstanding operations. + while (io_object* io_obj = registered_io_objects_.first()) + { + for (int i = 0; i < max_ops; ++i) + { + if (!io_obj->queues_[i].op_queue_.empty()) + { + ops.push(io_obj->queues_[i].op_queue_); + if (::io_uring_sqe* sqe = get_sqe()) + ::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0); + } + } + io_obj->shutdown_ = true; + registered_io_objects_.free(io_obj); + } + + // Cancel the timeout operation. + if (::io_uring_sqe* sqe = get_sqe()) + ::io_uring_prep_cancel(sqe, &timeout_, IOSQE_IO_DRAIN); + submit_sqes(); + + // Wait for all completions to come back. + for (; outstanding_work_ > 0; --outstanding_work_) + { + ::io_uring_cqe* cqe = 0; + if (::io_uring_wait_cqe(&ring_, &cqe) != 0) + break; + } + + timer_queues_.get_all_timers(ops); + + scheduler_.abandon_operations(ops); +} + +void io_uring_service::notify_fork( + asio::execution_context::fork_event fork_ev) +{ + switch (fork_ev) + { + case asio::execution_context::fork_prepare: + { + // Cancel all outstanding operations. They will be restarted + // after the fork completes. + mutex::scoped_lock registration_lock(registration_mutex_); + for (io_object* io_obj = registered_io_objects_.first(); + io_obj != 0; io_obj = io_obj->next_) + { + mutex::scoped_lock io_object_lock(io_obj->mutex_); + for (int i = 0; i < max_ops; ++i) + { + if (!io_obj->queues_[i].op_queue_.empty() + && !io_obj->queues_[i].cancel_requested_) + { + mutex::scoped_lock lock(mutex_); + if (::io_uring_sqe* sqe = get_sqe()) + ::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0); + } + } + } + + // Cancel the timeout operation. + { + mutex::scoped_lock lock(mutex_); + if (::io_uring_sqe* sqe = get_sqe()) + ::io_uring_prep_cancel(sqe, &timeout_, IOSQE_IO_DRAIN); + submit_sqes(); + } + + // Wait for all completions to come back, and post all completed I/O + // queues to the scheduler. Note that some operations may have already + // completed, or were explicitly cancelled. All others will be + // automatically restarted. + op_queue<operation> ops; + for (; outstanding_work_ > 0; --outstanding_work_) + { + ::io_uring_cqe* cqe = 0; + if (::io_uring_wait_cqe(&ring_, &cqe) != 0) + break; + if (void* ptr = ::io_uring_cqe_get_data(cqe)) + { + if (ptr != this && ptr != &timer_queues_ && ptr != &timeout_) + { + io_queue* io_q = static_cast<io_queue*>(ptr); + io_q->set_result(cqe->res); + ops.push(io_q); + } + } + } + scheduler_.post_deferred_completions(ops); + + // Restart and eventfd operation. + register_with_reactor(); + } + break; + + case asio::execution_context::fork_parent: + // Restart the timeout and eventfd operations. + update_timeout(); + register_with_reactor(); + break; + + case asio::execution_context::fork_child: + { + // The child process gets a new io_uring instance. + ::io_uring_queue_exit(&ring_); + init_ring(); + register_with_reactor(); + } + break; + default: + break; + } +} + +void io_uring_service::init_task() +{ + scheduler_.init_task(); +} + +void io_uring_service::register_io_object( + io_uring_service::per_io_object_data& io_obj) +{ + io_obj = allocate_io_object(); + + mutex::scoped_lock io_object_lock(io_obj->mutex_); + + io_obj->service_ = this; + io_obj->shutdown_ = false; + for (int i = 0; i < max_ops; ++i) + { + io_obj->queues_[i].io_object_ = io_obj; + io_obj->queues_[i].cancel_requested_ = false; + } +} + +void io_uring_service::register_internal_io_object( + io_uring_service::per_io_object_data& io_obj, + int op_type, io_uring_operation* op) +{ + io_obj = allocate_io_object(); + + mutex::scoped_lock io_object_lock(io_obj->mutex_); + + io_obj->service_ = this; + io_obj->shutdown_ = false; + for (int i = 0; i < max_ops; ++i) + { + io_obj->queues_[i].io_object_ = io_obj; + io_obj->queues_[i].cancel_requested_ = false; + } + + io_obj->queues_[op_type].op_queue_.push(op); + io_object_lock.unlock(); + mutex::scoped_lock lock(mutex_); + if (::io_uring_sqe* sqe = get_sqe()) + { + op->prepare(sqe); + ::io_uring_sqe_set_data(sqe, &io_obj->queues_[op_type]); + post_submit_sqes_op(lock); + } + else + { + asio::error_code ec(ENOBUFS, + asio::error::get_system_category()); + asio::detail::throw_error(ec, "io_uring_get_sqe"); + } +} + +void io_uring_service::register_buffers(const ::iovec* v, unsigned n) +{ + int result = ::io_uring_register_buffers(&ring_, v, n); + if (result < 0) + { + asio::error_code ec(-result, + asio::error::get_system_category()); + asio::detail::throw_error(ec, "io_uring_register_buffers"); + } +} + +void io_uring_service::unregister_buffers() +{ + (void)::io_uring_unregister_buffers(&ring_); +} + +void io_uring_service::start_op(int op_type, + io_uring_service::per_io_object_data& io_obj, + io_uring_operation* op, bool is_continuation) +{ + if (!io_obj) + { + op->ec_ = asio::error::bad_descriptor; + post_immediate_completion(op, is_continuation); + return; + } + + mutex::scoped_lock io_object_lock(io_obj->mutex_); + + if (io_obj->shutdown_) + { + io_object_lock.unlock(); + post_immediate_completion(op, is_continuation); + return; + } + + if (io_obj->queues_[op_type].op_queue_.empty()) + { + if (op->perform(false)) + { + io_object_lock.unlock(); + scheduler_.post_immediate_completion(op, is_continuation); + } + else + { + io_obj->queues_[op_type].op_queue_.push(op); + io_object_lock.unlock(); + mutex::scoped_lock lock(mutex_); + if (::io_uring_sqe* sqe = get_sqe()) + { + op->prepare(sqe); + ::io_uring_sqe_set_data(sqe, &io_obj->queues_[op_type]); + scheduler_.work_started(); + post_submit_sqes_op(lock); + } + else + { + lock.unlock(); + io_obj->queues_[op_type].set_result(-ENOBUFS); + post_immediate_completion(&io_obj->queues_[op_type], is_continuation); + } + } + } + else + { + io_obj->queues_[op_type].op_queue_.push(op); + scheduler_.work_started(); + } +} + +void io_uring_service::cancel_ops(io_uring_service::per_io_object_data& io_obj) +{ + if (!io_obj) + return; + + mutex::scoped_lock io_object_lock(io_obj->mutex_); + op_queue<operation> ops; + do_cancel_ops(io_obj, ops); + io_object_lock.unlock(); + scheduler_.post_deferred_completions(ops); +} + +void io_uring_service::cancel_ops_by_key( + io_uring_service::per_io_object_data& io_obj, + int op_type, void* cancellation_key) +{ + if (!io_obj) + return; + + mutex::scoped_lock io_object_lock(io_obj->mutex_); + + bool first = true; + op_queue<operation> ops; + op_queue<io_uring_operation> other_ops; + while (io_uring_operation* op = io_obj->queues_[op_type].op_queue_.front()) + { + io_obj->queues_[op_type].op_queue_.pop(); + if (op->cancellation_key_ == cancellation_key) + { + if (first) + { + other_ops.push(op); + if (!io_obj->queues_[op_type].cancel_requested_) + { + io_obj->queues_[op_type].cancel_requested_ = true; + mutex::scoped_lock lock(mutex_); + if (::io_uring_sqe* sqe = get_sqe()) + { + ::io_uring_prep_cancel(sqe, &io_obj->queues_[op_type], 0); + submit_sqes(); + } + } + } + else + { + op->ec_ = asio::error::operation_aborted; + ops.push(op); + } + } + else + other_ops.push(op); + first = false; + } + io_obj->queues_[op_type].op_queue_.push(other_ops); + + io_object_lock.unlock(); + + scheduler_.post_deferred_completions(ops); +} + +void io_uring_service::deregister_io_object( + io_uring_service::per_io_object_data& io_obj) +{ + if (!io_obj) + return; + + mutex::scoped_lock io_object_lock(io_obj->mutex_); + if (!io_obj->shutdown_) + { + op_queue<operation> ops; + bool pending_cancelled_ops = do_cancel_ops(io_obj, ops); + io_obj->shutdown_ = true; + io_object_lock.unlock(); + scheduler_.post_deferred_completions(ops); + if (pending_cancelled_ops) + { + // There are still pending operations. Prevent cleanup_io_object from + // freeing the I/O object and let the last operation to complete free it. + io_obj = 0; + } + else + { + // Leave io_obj set so that it will be freed by the subsequent call to + // cleanup_io_object. + } + } + else + { + // We are shutting down, so prevent cleanup_io_object from freeing + // the I/O object and let the destructor free it instead. + io_obj = 0; + } +} + +void io_uring_service::cleanup_io_object( + io_uring_service::per_io_object_data& io_obj) +{ + if (io_obj) + { + free_io_object(io_obj); + io_obj = 0; + } +} + +void io_uring_service::run(long usec, op_queue<operation>& ops) +{ + __kernel_timespec ts; + int local_ops = 0; + + if (usec > 0) + { + ts.tv_sec = usec / 1000000; + ts.tv_nsec = (usec % 1000000) * 1000; + mutex::scoped_lock lock(mutex_); + if (::io_uring_sqe* sqe = get_sqe()) + { + ++local_ops; + ::io_uring_prep_timeout(sqe, &ts, 0, 0); + ::io_uring_sqe_set_data(sqe, &ts); + submit_sqes(); + } + } + + ::io_uring_cqe* cqe = 0; + int result = (usec == 0) + ? ::io_uring_peek_cqe(&ring_, &cqe) + : ::io_uring_wait_cqe(&ring_, &cqe); + + if (local_ops > 0) + { + if (result != 0 || ::io_uring_cqe_get_data(cqe) != &ts) + { + mutex::scoped_lock lock(mutex_); + if (::io_uring_sqe* sqe = get_sqe()) + { + ++local_ops; + ::io_uring_prep_timeout_remove(sqe, reinterpret_cast<__u64>(&ts), 0); + ::io_uring_sqe_set_data(sqe, &ts); + submit_sqes(); + } + } + } + + bool check_timers = false; + int count = 0; + while (result == 0 || local_ops > 0) + { + if (result == 0) + { + if (void* ptr = ::io_uring_cqe_get_data(cqe)) + { + if (ptr == this) + { + // The io_uring service was interrupted. + } + else if (ptr == &timer_queues_) + { + check_timers = true; + } + else if (ptr == &timeout_) + { + check_timers = true; + timeout_.tv_sec = 0; + timeout_.tv_nsec = 0; + } + else if (ptr == &ts) + { + --local_ops; + } + else + { + io_queue* io_q = static_cast<io_queue*>(ptr); + io_q->set_result(cqe->res); + ops.push(io_q); + } + } + ::io_uring_cqe_seen(&ring_, cqe); + ++count; + } + result = (count < complete_batch_size || local_ops > 0) + ? ::io_uring_peek_cqe(&ring_, &cqe) : -EAGAIN; + } + + decrement(outstanding_work_, count); + + if (check_timers) + { + mutex::scoped_lock lock(mutex_); + timer_queues_.get_ready_timers(ops); + if (timeout_.tv_sec == 0 && timeout_.tv_nsec == 0) + { + timeout_ = get_timeout(); + if (::io_uring_sqe* sqe = get_sqe()) + { + ::io_uring_prep_timeout(sqe, &timeout_, 0, 0); + ::io_uring_sqe_set_data(sqe, &timeout_); + push_submit_sqes_op(ops); + } + } + } +} + +void io_uring_service::interrupt() +{ + mutex::scoped_lock lock(mutex_); + if (::io_uring_sqe* sqe = get_sqe()) + { + ::io_uring_prep_nop(sqe); + ::io_uring_sqe_set_data(sqe, this); + } + submit_sqes(); +} + +void io_uring_service::init_ring() +{ + int result = ::io_uring_queue_init(ring_size, &ring_, 0); + if (result < 0) + { + ring_.ring_fd = -1; + asio::error_code ec(-result, + asio::error::get_system_category()); + asio::detail::throw_error(ec, "io_uring_queue_init"); + } + +#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT) + event_fd_ = ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); + if (event_fd_ < 0) + { + asio::error_code ec(-result, + asio::error::get_system_category()); + ::io_uring_queue_exit(&ring_); + asio::detail::throw_error(ec, "eventfd"); + } + + result = ::io_uring_register_eventfd(&ring_, event_fd_); + if (result < 0) + { + ::close(event_fd_); + ::io_uring_queue_exit(&ring_); + asio::error_code ec(-result, + asio::error::get_system_category()); + asio::detail::throw_error(ec, "io_uring_queue_init"); + } +#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT) +} + +#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT) +class io_uring_service::event_fd_read_op : + public reactor_op +{ +public: + event_fd_read_op(io_uring_service* s) + : reactor_op(asio::error_code(), + &event_fd_read_op::do_perform, event_fd_read_op::do_complete), + service_(s) + { + } + + static status do_perform(reactor_op* base) + { + event_fd_read_op* o(static_cast<event_fd_read_op*>(base)); + + for (;;) + { + // Only perform one read. The kernel maintains an atomic counter. + uint64_t counter(0); + errno = 0; + int bytes_read = ::read(o->service_->event_fd_, + &counter, sizeof(uint64_t)); + if (bytes_read < 0 && errno == EINTR) + continue; + break; + } + + op_queue<operation> ops; + o->service_->run(0, ops); + o->service_->scheduler_.post_deferred_completions(ops); + + return not_done; + } + + static void do_complete(void* /*owner*/, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + event_fd_read_op* o(static_cast<event_fd_read_op*>(base)); + delete o; + } + +private: + io_uring_service* service_; +}; +#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT) + +void io_uring_service::register_with_reactor() +{ +#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT) + reactor_.register_internal_descriptor(reactor::read_op, + event_fd_, reactor_data_, new event_fd_read_op(this)); +#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT) +} + +io_uring_service::io_object* io_uring_service::allocate_io_object() +{ + mutex::scoped_lock registration_lock(registration_mutex_); + return registered_io_objects_.alloc( + ASIO_CONCURRENCY_HINT_IS_LOCKING( + REACTOR_IO, scheduler_.concurrency_hint())); +} + +void io_uring_service::free_io_object(io_uring_service::io_object* io_obj) +{ + mutex::scoped_lock registration_lock(registration_mutex_); + registered_io_objects_.free(io_obj); +} + +bool io_uring_service::do_cancel_ops( + per_io_object_data& io_obj, op_queue<operation>& ops) +{ + bool cancel_op = false; + + for (int i = 0; i < max_ops; ++i) + { + if (io_uring_operation* first_op = io_obj->queues_[i].op_queue_.front()) + { + cancel_op = true; + io_obj->queues_[i].op_queue_.pop(); + while (io_uring_operation* op = io_obj->queues_[i].op_queue_.front()) + { + op->ec_ = asio::error::operation_aborted; + io_obj->queues_[i].op_queue_.pop(); + ops.push(op); + } + io_obj->queues_[i].op_queue_.push(first_op); + } + } + + if (cancel_op) + { + mutex::scoped_lock lock(mutex_); + for (int i = 0; i < max_ops; ++i) + { + if (!io_obj->queues_[i].op_queue_.empty() + && !io_obj->queues_[i].cancel_requested_) + { + io_obj->queues_[i].cancel_requested_ = true; + if (::io_uring_sqe* sqe = get_sqe()) + ::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0); + } + } + submit_sqes(); + } + + return cancel_op; +} + +void io_uring_service::do_add_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.insert(&queue); +} + +void io_uring_service::do_remove_timer_queue(timer_queue_base& queue) +{ + mutex::scoped_lock lock(mutex_); + timer_queues_.erase(&queue); +} + +void io_uring_service::update_timeout() +{ + if (::io_uring_sqe* sqe = get_sqe()) + { + ::io_uring_prep_timeout_remove(sqe, reinterpret_cast<__u64>(&timeout_), 0); + ::io_uring_sqe_set_data(sqe, &timer_queues_); + } +} + +__kernel_timespec io_uring_service::get_timeout() const +{ + __kernel_timespec ts; + long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000); + ts.tv_sec = usec / 1000000; + ts.tv_nsec = usec ? (usec % 1000000) * 1000 : 1; + return ts; +} + +::io_uring_sqe* io_uring_service::get_sqe() +{ + ::io_uring_sqe* sqe = ::io_uring_get_sqe(&ring_); + if (!sqe) + { + submit_sqes(); + sqe = ::io_uring_get_sqe(&ring_); + } + if (sqe) + { + ::io_uring_sqe_set_data(sqe, 0); + ++pending_sqes_; + } + return sqe; +} + +void io_uring_service::submit_sqes() +{ + if (pending_sqes_ != 0) + { + int result = ::io_uring_submit(&ring_); + if (result > 0) + { + pending_sqes_ -= result; + increment(outstanding_work_, result); + } + } +} + +void io_uring_service::post_submit_sqes_op(mutex::scoped_lock& lock) +{ + if (pending_sqes_ >= submit_batch_size) + { + submit_sqes(); + } + else if (pending_sqes_ != 0 && !pending_submit_sqes_op_) + { + pending_submit_sqes_op_ = true; + lock.unlock(); + scheduler_.post_immediate_completion(&submit_sqes_op_, false); + } +} + +void io_uring_service::push_submit_sqes_op(op_queue<operation>& ops) +{ + if (pending_sqes_ != 0 && !pending_submit_sqes_op_) + { + pending_submit_sqes_op_ = true; + ops.push(&submit_sqes_op_); + scheduler_.compensating_work_started(); + } +} + +io_uring_service::submit_sqes_op::submit_sqes_op(io_uring_service* s) + : operation(&io_uring_service::submit_sqes_op::do_complete), + service_(s) +{ +} + +void io_uring_service::submit_sqes_op::do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, std::size_t /*bytes_transferred*/) +{ + if (owner) + { + submit_sqes_op* o = static_cast<submit_sqes_op*>(base); + mutex::scoped_lock lock(o->service_->mutex_); + o->service_->submit_sqes(); + if (o->service_->pending_sqes_ != 0) + o->service_->scheduler_.post_immediate_completion(o, true); + else + o->service_->pending_submit_sqes_op_ = false; + } +} + +io_uring_service::io_queue::io_queue() + : operation(&io_uring_service::io_queue::do_complete) +{ +} + +struct io_uring_service::perform_io_cleanup_on_block_exit +{ + explicit perform_io_cleanup_on_block_exit(io_uring_service* s) + : service_(s), io_object_to_free_(0), first_op_(0) + { + } + + ~perform_io_cleanup_on_block_exit() + { + if (io_object_to_free_) + { + mutex::scoped_lock lock(service_->mutex_); + service_->free_io_object(io_object_to_free_); + } + + if (first_op_) + { + // Post the remaining completed operations for invocation. + if (!ops_.empty()) + service_->scheduler_.post_deferred_completions(ops_); + + // A user-initiated operation has completed, but there's no need to + // explicitly call work_finished() here. Instead, we'll take advantage of + // the fact that the scheduler will call work_finished() once we return. + } + else + { + // No user-initiated operations have completed, so we need to compensate + // for the work_finished() call that the scheduler will make once this + // operation returns. + service_->scheduler_.compensating_work_started(); + } + } + + io_uring_service* service_; + io_object* io_object_to_free_; + op_queue<operation> ops_; + operation* first_op_; +}; + +operation* io_uring_service::io_queue::perform_io(int result) +{ + perform_io_cleanup_on_block_exit io_cleanup(io_object_->service_); + mutex::scoped_lock io_object_lock(io_object_->mutex_); + + if (result != -ECANCELED || cancel_requested_) + { + if (io_uring_operation* op = op_queue_.front()) + { + if (result < 0) + { + op->ec_.assign(-result, asio::error::get_system_category()); + op->bytes_transferred_ = 0; + } + else + { + op->ec_.assign(0, op->ec_.category()); + op->bytes_transferred_ = static_cast<std::size_t>(result); + } + } + + while (io_uring_operation* op = op_queue_.front()) + { + if (op->perform(io_cleanup.ops_.empty())) + { + op_queue_.pop(); + io_cleanup.ops_.push(op); + } + else + break; + } + } + + cancel_requested_ = false; + + if (!op_queue_.empty()) + { + io_uring_service* service = io_object_->service_; + mutex::scoped_lock lock(service->mutex_); + if (::io_uring_sqe* sqe = service->get_sqe()) + { + op_queue_.front()->prepare(sqe); + ::io_uring_sqe_set_data(sqe, this); + service->post_submit_sqes_op(lock); + } + else + { + lock.unlock(); + while (io_uring_operation* op = op_queue_.front()) + { + op->ec_ = asio::error::no_buffer_space; + op_queue_.pop(); + io_cleanup.ops_.push(op); + } + } + } + + // The last operation to complete on a shut down object must free it. + if (io_object_->shutdown_) + { + io_cleanup.io_object_to_free_ = io_object_; + for (int i = 0; i < max_ops; ++i) + if (!io_object_->queues_[i].op_queue_.empty()) + io_cleanup.io_object_to_free_ = 0; + } + + // The first operation will be returned for completion now. The others will + // be posted for later by the io_cleanup object's destructor. + io_cleanup.first_op_ = io_cleanup.ops_.front(); + io_cleanup.ops_.pop(); + return io_cleanup.first_op_; +} + +void io_uring_service::io_queue::do_complete(void* owner, operation* base, + const asio::error_code& ec, std::size_t bytes_transferred) +{ + if (owner) + { + io_queue* io_q = static_cast<io_queue*>(base); + int result = static_cast<int>(bytes_transferred); + if (operation* op = io_q->perform_io(result)) + { + op->complete(owner, ec, 0); + } + } +} + +io_uring_service::io_object::io_object(bool locking) + : mutex_(locking) +{ +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IMPL_IO_URING_SERVICE_IPP diff --git a/3rdparty/asio/include/asio/detail/impl/io_uring_socket_service_base.ipp b/3rdparty/asio/include/asio/detail/impl/io_uring_socket_service_base.ipp new file mode 100644 index 00000000000..79302fdc6f6 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/impl/io_uring_socket_service_base.ipp @@ -0,0 +1,249 @@ +// +// detail/io_uring_socket_service_base.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP +#define ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/io_uring_socket_service_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +io_uring_socket_service_base::io_uring_socket_service_base( + execution_context& context) + : io_uring_service_(asio::use_service<io_uring_service>(context)) +{ + io_uring_service_.init_task(); +} + +void io_uring_socket_service_base::base_shutdown() +{ +} + +void io_uring_socket_service_base::construct( + io_uring_socket_service_base::base_implementation_type& impl) +{ + impl.socket_ = invalid_socket; + impl.state_ = 0; + impl.io_object_data_ = 0; +} + +void io_uring_socket_service_base::base_move_construct( + io_uring_socket_service_base::base_implementation_type& impl, + io_uring_socket_service_base::base_implementation_type& other_impl) + noexcept +{ + impl.socket_ = other_impl.socket_; + other_impl.socket_ = invalid_socket; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + impl.io_object_data_ = other_impl.io_object_data_; + other_impl.io_object_data_ = 0; +} + +void io_uring_socket_service_base::base_move_assign( + io_uring_socket_service_base::base_implementation_type& impl, + io_uring_socket_service_base& /*other_service*/, + io_uring_socket_service_base::base_implementation_type& other_impl) +{ + destroy(impl); + + impl.socket_ = other_impl.socket_; + other_impl.socket_ = invalid_socket; + + impl.state_ = other_impl.state_; + other_impl.state_ = 0; + + impl.io_object_data_ = other_impl.io_object_data_; + other_impl.io_object_data_ = 0; +} + +void io_uring_socket_service_base::destroy( + io_uring_socket_service_base::base_implementation_type& impl) +{ + if (impl.socket_ != invalid_socket) + { + ASIO_HANDLER_OPERATION((io_uring_service_.context(), + "socket", &impl, impl.socket_, "close")); + + io_uring_service_.deregister_io_object(impl.io_object_data_); + asio::error_code ignored_ec; + socket_ops::close(impl.socket_, impl.state_, true, ignored_ec); + io_uring_service_.cleanup_io_object(impl.io_object_data_); + } +} + +asio::error_code io_uring_socket_service_base::close( + io_uring_socket_service_base::base_implementation_type& impl, + asio::error_code& ec) +{ + if (is_open(impl)) + { + ASIO_HANDLER_OPERATION((io_uring_service_.context(), + "socket", &impl, impl.socket_, "close")); + + io_uring_service_.deregister_io_object(impl.io_object_data_); + socket_ops::close(impl.socket_, impl.state_, false, ec); + io_uring_service_.cleanup_io_object(impl.io_object_data_); + } + else + { + ec = success_ec_; + } + + // The descriptor is closed by the OS even if close() returns an error. + // + // (Actually, POSIX says the state of the descriptor is unspecified. On + // Linux the descriptor is apparently closed anyway; e.g. see + // http://lkml.org/lkml/2005/9/10/129 + construct(impl); + + return ec; +} + +socket_type io_uring_socket_service_base::release( + io_uring_socket_service_base::base_implementation_type& impl, + asio::error_code& ec) +{ + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return invalid_socket; + } + + ASIO_HANDLER_OPERATION((io_uring_service_.context(), + "socket", &impl, impl.socket_, "release")); + + io_uring_service_.deregister_io_object(impl.io_object_data_); + io_uring_service_.cleanup_io_object(impl.io_object_data_); + socket_type sock = impl.socket_; + construct(impl); + ec = success_ec_; + return sock; +} + +asio::error_code io_uring_socket_service_base::cancel( + io_uring_socket_service_base::base_implementation_type& impl, + asio::error_code& ec) +{ + if (!is_open(impl)) + { + ec = asio::error::bad_descriptor; + return ec; + } + + ASIO_HANDLER_OPERATION((io_uring_service_.context(), + "socket", &impl, impl.socket_, "cancel")); + + io_uring_service_.cancel_ops(impl.io_object_data_); + ec = success_ec_; + return ec; +} + +asio::error_code io_uring_socket_service_base::do_open( + io_uring_socket_service_base::base_implementation_type& impl, + int af, int type, int protocol, asio::error_code& ec) +{ + if (is_open(impl)) + { + ec = asio::error::already_open; + return ec; + } + + socket_holder sock(socket_ops::socket(af, type, protocol, ec)); + if (sock.get() == invalid_socket) + return ec; + + io_uring_service_.register_io_object(impl.io_object_data_); + + impl.socket_ = sock.release(); + switch (type) + { + case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; + case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; + default: impl.state_ = 0; break; + } + ec = success_ec_; + return ec; +} + +asio::error_code io_uring_socket_service_base::do_assign( + io_uring_socket_service_base::base_implementation_type& impl, int type, + const io_uring_socket_service_base::native_handle_type& native_socket, + asio::error_code& ec) +{ + if (is_open(impl)) + { + ec = asio::error::already_open; + return ec; + } + + io_uring_service_.register_io_object(impl.io_object_data_); + + impl.socket_ = native_socket; + switch (type) + { + case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break; + case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break; + default: impl.state_ = 0; break; + } + impl.state_ |= socket_ops::possible_dup; + ec = success_ec_; + return ec; +} + +void io_uring_socket_service_base::start_op( + io_uring_socket_service_base::base_implementation_type& impl, + int op_type, io_uring_operation* op, bool is_continuation, bool noop) +{ + if (!noop) + { + io_uring_service_.start_op(op_type, + impl.io_object_data_, op, is_continuation); + } + else + { + io_uring_service_.post_immediate_completion(op, is_continuation); + } +} + +void io_uring_socket_service_base::start_accept_op( + io_uring_socket_service_base::base_implementation_type& impl, + io_uring_operation* op, bool is_continuation, bool peer_is_open) +{ + if (!peer_is_open) + start_op(impl, io_uring_service::read_op, op, is_continuation, false); + else + { + op->ec_ = asio::error::already_open; + io_uring_service_.post_immediate_completion(op, is_continuation); + } +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP diff --git a/3rdparty/asio/include/asio/detail/impl/kqueue_reactor.hpp b/3rdparty/asio/include/asio/detail/impl/kqueue_reactor.hpp index 82584ae7914..3f79e9f7217 100644 --- a/3rdparty/asio/include/asio/detail/impl/kqueue_reactor.hpp +++ b/3rdparty/asio/include/asio/detail/impl/kqueue_reactor.hpp @@ -2,7 +2,7 @@ // detail/impl/kqueue_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -28,7 +28,7 @@ namespace asio { namespace detail { inline void kqueue_reactor::post_immediate_completion( - operation* op, bool is_continuation) + operation* op, bool is_continuation) const { scheduler_.post_immediate_completion(op, is_continuation); } diff --git a/3rdparty/asio/include/asio/detail/impl/kqueue_reactor.ipp b/3rdparty/asio/include/asio/detail/impl/kqueue_reactor.ipp index 60b5ca861ee..210a89dd49e 100644 --- a/3rdparty/asio/include/asio/detail/impl/kqueue_reactor.ipp +++ b/3rdparty/asio/include/asio/detail/impl/kqueue_reactor.ipp @@ -2,7 +2,7 @@ // detail/impl/kqueue_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -190,14 +190,23 @@ void kqueue_reactor::move_descriptor(socket_type, source_descriptor_data = 0; } +void kqueue_reactor::call_post_immediate_completion( + operation* op, bool is_continuation, const void* self) +{ + static_cast<const kqueue_reactor*>(self)->post_immediate_completion( + op, is_continuation); +} + void kqueue_reactor::start_op(int op_type, socket_type descriptor, kqueue_reactor::per_descriptor_data& descriptor_data, reactor_op* op, - bool is_continuation, bool allow_speculative) + bool is_continuation, bool allow_speculative, + void (*on_immediate)(operation*, bool, const void*), + const void* immediate_arg) { if (!descriptor_data) { op->ec_ = asio::error::bad_descriptor; - post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } @@ -205,7 +214,7 @@ void kqueue_reactor::start_op(int op_type, socket_type descriptor, if (descriptor_data->shutdown_) { - post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } @@ -220,7 +229,7 @@ void kqueue_reactor::start_op(int op_type, socket_type descriptor, if (op->perform()) { descriptor_lock.unlock(); - scheduler_.post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } @@ -239,7 +248,7 @@ void kqueue_reactor::start_op(int op_type, socket_type descriptor, { op->ec_ = asio::error_code(errno, asio::error::get_system_category()); - scheduler_.post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } } diff --git a/3rdparty/asio/include/asio/detail/impl/null_event.ipp b/3rdparty/asio/include/asio/detail/impl/null_event.ipp index 7b8f968fa0f..1c9f5684298 100644 --- a/3rdparty/asio/include/asio/detail/impl/null_event.ipp +++ b/3rdparty/asio/include/asio/detail/impl/null_event.ipp @@ -2,7 +2,7 @@ // detail/impl/null_event.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/pipe_select_interrupter.ipp b/3rdparty/asio/include/asio/detail/impl/pipe_select_interrupter.ipp index 31c1b5c9b30..75138312d9d 100644 --- a/3rdparty/asio/include/asio/detail/impl/pipe_select_interrupter.ipp +++ b/3rdparty/asio/include/asio/detail/impl/pipe_select_interrupter.ipp @@ -2,7 +2,7 @@ // detail/impl/pipe_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/posix_event.ipp b/3rdparty/asio/include/asio/detail/impl/posix_event.ipp index a823d8fbee8..76d5c468cbf 100644 --- a/3rdparty/asio/include/asio/detail/impl/posix_event.ipp +++ b/3rdparty/asio/include/asio/detail/impl/posix_event.ipp @@ -2,7 +2,7 @@ // detail/impl/posix_event.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/posix_mutex.ipp b/3rdparty/asio/include/asio/detail/impl/posix_mutex.ipp index c553ab4eef8..5fd832f9821 100644 --- a/3rdparty/asio/include/asio/detail/impl/posix_mutex.ipp +++ b/3rdparty/asio/include/asio/detail/impl/posix_mutex.ipp @@ -2,7 +2,7 @@ // detail/impl/posix_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/reactive_serial_port_service.ipp b/3rdparty/asio/include/asio/detail/impl/posix_serial_port_service.ipp index 23515a96c18..98ed5822877 100644 --- a/3rdparty/asio/include/asio/detail/impl/reactive_serial_port_service.ipp +++ b/3rdparty/asio/include/asio/detail/impl/posix_serial_port_service.ipp @@ -1,16 +1,16 @@ // -// detail/impl/reactive_serial_port_service.ipp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// detail/impl/posix_serial_port_service.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP -#define ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP +#ifndef ASIO_DETAIL_IMPL_POSIX_SERIAL_PORT_SERVICE_IPP +#define ASIO_DETAIL_IMPL_POSIX_SERIAL_PORT_SERVICE_IPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once @@ -22,32 +22,33 @@ #if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__) #include <cstring> -#include "asio/detail/reactive_serial_port_service.hpp" +#include "asio/detail/posix_serial_port_service.hpp" #include "asio/detail/push_options.hpp" namespace asio { namespace detail { -reactive_serial_port_service::reactive_serial_port_service( +posix_serial_port_service::posix_serial_port_service( execution_context& context) - : execution_context_service_base<reactive_serial_port_service>(context), + : execution_context_service_base<posix_serial_port_service>(context), descriptor_service_(context) { } -void reactive_serial_port_service::shutdown() +void posix_serial_port_service::shutdown() { descriptor_service_.shutdown(); } -asio::error_code reactive_serial_port_service::open( - reactive_serial_port_service::implementation_type& impl, +asio::error_code posix_serial_port_service::open( + posix_serial_port_service::implementation_type& impl, const std::string& device, asio::error_code& ec) { if (is_open(impl)) { ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); return ec; } @@ -55,7 +56,10 @@ asio::error_code reactive_serial_port_service::open( int fd = descriptor_ops::open(device.c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY, ec); if (fd < 0) + { + ASIO_ERROR_LOCATION(ec); return ec; + } int s = descriptor_ops::fcntl(fd, F_GETFL, ec); if (s >= 0) @@ -64,6 +68,7 @@ asio::error_code reactive_serial_port_service::open( { asio::error_code ignored_ec; descriptor_ops::close(fd, state, ignored_ec); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -92,6 +97,7 @@ asio::error_code reactive_serial_port_service::open( { asio::error_code ignored_ec; descriptor_ops::close(fd, state, ignored_ec); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -102,40 +108,53 @@ asio::error_code reactive_serial_port_service::open( descriptor_ops::close(fd, state, ignored_ec); } + ASIO_ERROR_LOCATION(ec); return ec; } -asio::error_code reactive_serial_port_service::do_set_option( - reactive_serial_port_service::implementation_type& impl, - reactive_serial_port_service::store_function_type store, +asio::error_code posix_serial_port_service::do_set_option( + posix_serial_port_service::implementation_type& impl, + posix_serial_port_service::store_function_type store, const void* option, asio::error_code& ec) { termios ios; int s = ::tcgetattr(descriptor_service_.native_handle(impl), &ios); descriptor_ops::get_last_error(ec, s < 0); if (s < 0) + { + ASIO_ERROR_LOCATION(ec); return ec; + } if (store(option, ios, ec)) + { + ASIO_ERROR_LOCATION(ec); return ec; + } s = ::tcsetattr(descriptor_service_.native_handle(impl), TCSANOW, &ios); descriptor_ops::get_last_error(ec, s < 0); + ASIO_ERROR_LOCATION(ec); return ec; } -asio::error_code reactive_serial_port_service::do_get_option( - const reactive_serial_port_service::implementation_type& impl, - reactive_serial_port_service::load_function_type load, +asio::error_code posix_serial_port_service::do_get_option( + const posix_serial_port_service::implementation_type& impl, + posix_serial_port_service::load_function_type load, void* option, asio::error_code& ec) const { termios ios; int s = ::tcgetattr(descriptor_service_.native_handle(impl), &ios); descriptor_ops::get_last_error(ec, s < 0); if (s < 0) + { + ASIO_ERROR_LOCATION(ec); return ec; + } - return load(option, ios, ec); + load(option, ios, ec); + ASIO_ERROR_LOCATION(ec); + return ec; } } // namespace detail @@ -146,4 +165,4 @@ asio::error_code reactive_serial_port_service::do_get_option( #endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__) #endif // defined(ASIO_HAS_SERIAL_PORT) -#endif // ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP +#endif // ASIO_DETAIL_IMPL_POSIX_SERIAL_PORT_SERVICE_IPP diff --git a/3rdparty/asio/include/asio/detail/impl/posix_thread.ipp b/3rdparty/asio/include/asio/detail/impl/posix_thread.ipp index 94373ee0287..7602377336e 100644 --- a/3rdparty/asio/include/asio/detail/impl/posix_thread.ipp +++ b/3rdparty/asio/include/asio/detail/impl/posix_thread.ipp @@ -2,7 +2,7 @@ // detail/impl/posix_thread.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/posix_tss_ptr.ipp b/3rdparty/asio/include/asio/detail/impl/posix_tss_ptr.ipp index 6a368e0ffd1..099274b2779 100644 --- a/3rdparty/asio/include/asio/detail/impl/posix_tss_ptr.ipp +++ b/3rdparty/asio/include/asio/detail/impl/posix_tss_ptr.ipp @@ -2,7 +2,7 @@ // detail/impl/posix_tss_ptr.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/reactive_descriptor_service.ipp b/3rdparty/asio/include/asio/detail/impl/reactive_descriptor_service.ipp index 9caf06877d7..829aefb01bf 100644 --- a/3rdparty/asio/include/asio/detail/impl/reactive_descriptor_service.ipp +++ b/3rdparty/asio/include/asio/detail/impl/reactive_descriptor_service.ipp @@ -2,7 +2,7 @@ // detail/impl/reactive_descriptor_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,7 +19,8 @@ #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \ - && !defined(__CYGWIN__) + && !defined(__CYGWIN__) \ + && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/error.hpp" #include "asio/detail/reactive_descriptor_service.hpp" @@ -46,12 +47,13 @@ void reactive_descriptor_service::construct( { impl.descriptor_ = -1; impl.state_ = 0; + impl.reactor_data_ = reactor::per_descriptor_data(); } void reactive_descriptor_service::move_construct( reactive_descriptor_service::implementation_type& impl, reactive_descriptor_service::implementation_type& other_impl) - ASIO_NOEXCEPT + noexcept { impl.descriptor_ = other_impl.descriptor_; other_impl.descriptor_ = -1; @@ -105,6 +107,7 @@ asio::error_code reactive_descriptor_service::assign( if (is_open(impl)) { ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); return ec; } @@ -113,6 +116,7 @@ asio::error_code reactive_descriptor_service::assign( { ec = asio::error_code(err, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -151,6 +155,7 @@ asio::error_code reactive_descriptor_service::close( // We'll just have to assume that other OSes follow the same behaviour.) construct(impl); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -180,6 +185,7 @@ asio::error_code reactive_descriptor_service::cancel( if (!is_open(impl)) { ec = asio::error::bad_descriptor; + ASIO_ERROR_LOCATION(ec); return ec; } @@ -191,10 +197,10 @@ asio::error_code reactive_descriptor_service::cancel( return ec; } -void reactive_descriptor_service::start_op( - reactive_descriptor_service::implementation_type& impl, - int op_type, reactor_op* op, bool is_continuation, - bool is_non_blocking, bool noop) +void reactive_descriptor_service::do_start_op(implementation_type& impl, + int op_type, reactor_op* op, bool is_continuation, bool is_non_blocking, + bool noop, void (*on_immediate)(operation* op, bool, const void*), + const void* immediate_arg) { if (!noop) { @@ -202,13 +208,13 @@ void reactive_descriptor_service::start_op( descriptor_ops::set_internal_non_blocking( impl.descriptor_, impl.state_, true, op->ec_)) { - reactor_.start_op(op_type, impl.descriptor_, - impl.reactor_data_, op, is_continuation, is_non_blocking); + reactor_.start_op(op_type, impl.descriptor_, impl.reactor_data_, op, + is_continuation, is_non_blocking, on_immediate, immediate_arg); return; } } - reactor_.post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); } } // namespace detail @@ -219,5 +225,6 @@ void reactive_descriptor_service::start_op( #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__) + // && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP diff --git a/3rdparty/asio/include/asio/detail/impl/reactive_socket_service_base.ipp b/3rdparty/asio/include/asio/detail/impl/reactive_socket_service_base.ipp index afda16f3520..a02001b421f 100644 --- a/3rdparty/asio/include/asio/detail/impl/reactive_socket_service_base.ipp +++ b/3rdparty/asio/include/asio/detail/impl/reactive_socket_service_base.ipp @@ -2,7 +2,7 @@ // detail/reactive_socket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,7 +18,8 @@ #include "asio/detail/config.hpp" #if !defined(ASIO_HAS_IOCP) \ - && !defined(ASIO_WINDOWS_RUNTIME) + && !defined(ASIO_WINDOWS_RUNTIME) \ + && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/detail/reactive_socket_service_base.hpp" @@ -43,12 +44,13 @@ void reactive_socket_service_base::construct( { impl.socket_ = invalid_socket; impl.state_ = 0; + impl.reactor_data_ = reactor::per_descriptor_data(); } void reactive_socket_service_base::base_move_construct( reactive_socket_service_base::base_implementation_type& impl, reactive_socket_service_base::base_implementation_type& other_impl) - ASIO_NOEXCEPT + noexcept { impl.socket_ = other_impl.socket_; other_impl.socket_ = invalid_socket; @@ -231,10 +233,11 @@ asio::error_code reactive_socket_service_base::do_assign( return ec; } -void reactive_socket_service_base::start_op( - reactive_socket_service_base::base_implementation_type& impl, - int op_type, reactor_op* op, bool is_continuation, - bool is_non_blocking, bool noop) +void reactive_socket_service_base::do_start_op( + reactive_socket_service_base::base_implementation_type& impl, int op_type, + reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop, + void (*on_immediate)(operation* op, bool, const void*), + const void* immediate_arg) { if (!noop) { @@ -242,32 +245,38 @@ void reactive_socket_service_base::start_op( || socket_ops::set_internal_non_blocking( impl.socket_, impl.state_, true, op->ec_)) { - reactor_.start_op(op_type, impl.socket_, - impl.reactor_data_, op, is_continuation, is_non_blocking); + reactor_.start_op(op_type, impl.socket_, impl.reactor_data_, op, + is_continuation, is_non_blocking, on_immediate, immediate_arg); return; } } - reactor_.post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); } -void reactive_socket_service_base::start_accept_op( +void reactive_socket_service_base::do_start_accept_op( reactive_socket_service_base::base_implementation_type& impl, - reactor_op* op, bool is_continuation, bool peer_is_open) + reactor_op* op, bool is_continuation, bool peer_is_open, + void (*on_immediate)(operation* op, bool, const void*), + const void* immediate_arg) { if (!peer_is_open) - start_op(impl, reactor::read_op, op, is_continuation, true, false); + { + do_start_op(impl, reactor::read_op, op, is_continuation, + true, false, on_immediate, immediate_arg); + } else { op->ec_ = asio::error::already_open; - reactor_.post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); } } -void reactive_socket_service_base::start_connect_op( +void reactive_socket_service_base::do_start_connect_op( reactive_socket_service_base::base_implementation_type& impl, - reactor_op* op, bool is_continuation, - const socket_addr_type* addr, size_t addrlen) + reactor_op* op, bool is_continuation, const void* addr, size_t addrlen, + void (*on_immediate)(operation* op, bool, const void*), + const void* immediate_arg) { if ((impl.state_ & socket_ops::non_blocking) || socket_ops::set_internal_non_blocking( @@ -279,14 +288,14 @@ void reactive_socket_service_base::start_connect_op( || op->ec_ == asio::error::would_block) { op->ec_ = asio::error_code(); - reactor_.start_op(reactor::connect_op, impl.socket_, - impl.reactor_data_, op, is_continuation, false); + reactor_.start_op(reactor::connect_op, impl.socket_, impl.reactor_data_, + op, is_continuation, false, on_immediate, immediate_arg); return; } } } - reactor_.post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); } } // namespace detail @@ -296,5 +305,6 @@ void reactive_socket_service_base::start_connect_op( #endif // !defined(ASIO_HAS_IOCP) // && !defined(ASIO_WINDOWS_RUNTIME) + // && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP diff --git a/3rdparty/asio/include/asio/detail/impl/resolver_service_base.ipp b/3rdparty/asio/include/asio/detail/impl/resolver_service_base.ipp index bd1b0bc0296..8d9e944ddde 100644 --- a/3rdparty/asio/include/asio/detail/impl/resolver_service_base.ipp +++ b/3rdparty/asio/include/asio/detail/impl/resolver_service_base.ipp @@ -2,7 +2,7 @@ // detail/impl/resolver_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -105,14 +105,14 @@ void resolver_service_base::destroy( void resolver_service_base::move_construct(implementation_type& impl, implementation_type& other_impl) { - impl = ASIO_MOVE_CAST(implementation_type)(other_impl); + impl = static_cast<implementation_type&&>(other_impl); } void resolver_service_base::move_assign(implementation_type& impl, resolver_service_base&, implementation_type& other_impl) { destroy(impl); - impl = ASIO_MOVE_CAST(implementation_type)(other_impl); + impl = static_cast<implementation_type&&>(other_impl); } void resolver_service_base::cancel( diff --git a/3rdparty/asio/include/asio/detail/impl/scheduler.ipp b/3rdparty/asio/include/asio/detail/impl/scheduler.ipp index 0734fc8e832..eccc80322d1 100644 --- a/3rdparty/asio/include/asio/detail/impl/scheduler.ipp +++ b/3rdparty/asio/include/asio/detail/impl/scheduler.ipp @@ -2,7 +2,7 @@ // detail/impl/scheduler.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,11 +20,16 @@ #include "asio/detail/concurrency_hint.hpp" #include "asio/detail/event.hpp" #include "asio/detail/limits.hpp" -#include "asio/detail/reactor.hpp" #include "asio/detail/scheduler.hpp" #include "asio/detail/scheduler_thread_info.hpp" #include "asio/detail/signal_blocker.hpp" +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/io_uring_service.hpp" +#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/reactor.hpp" +#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) + #include "asio/detail/push_options.hpp" namespace asio { @@ -104,7 +109,7 @@ struct scheduler::work_cleanup }; scheduler::scheduler(asio::execution_context& ctx, - int concurrency_hint, bool own_thread) + int concurrency_hint, bool own_thread, get_task_func_type get_task) : asio::detail::execution_context_service_base<scheduler>(ctx), one_thread_(concurrency_hint == 1 || !ASIO_CONCURRENCY_HINT_IS_LOCKING( @@ -114,6 +119,7 @@ scheduler::scheduler(asio::execution_context& ctx, mutex_(ASIO_CONCURRENCY_HINT_IS_LOCKING( SCHEDULER, concurrency_hint)), task_(0), + get_task_(get_task), task_interrupted_(true), outstanding_work_(0), stopped_(false), @@ -178,7 +184,7 @@ void scheduler::init_task() mutex::scoped_lock lock(mutex_); if (!shutdown_ && !task_) { - task_ = &use_service<reactor>(this->context()); + task_ = get_task_(this->context()); op_queue_.push(&task_operation_); wake_one_thread_and_unlock(lock); } @@ -321,6 +327,7 @@ void scheduler::restart() void scheduler::compensating_work_started() { thread_info_base* this_thread = thread_call_stack::contains(this); + ASIO_ASSUME(this_thread != 0); // Only called from inside scheduler. ++static_cast<thread_info*>(this_thread)->private_outstanding_work; } @@ -651,6 +658,15 @@ void scheduler::wake_one_thread_and_unlock( } } +scheduler_task* scheduler::get_default_task(asio::execution_context& ctx) +{ +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + return &use_service<io_uring_service>(ctx); +#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) + return &use_service<reactor>(ctx); +#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) +} + } // namespace detail } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/impl/select_reactor.hpp b/3rdparty/asio/include/asio/detail/impl/select_reactor.hpp index c0499618bb6..933b02cddc5 100644 --- a/3rdparty/asio/include/asio/detail/impl/select_reactor.hpp +++ b/3rdparty/asio/include/asio/detail/impl/select_reactor.hpp @@ -2,7 +2,7 @@ // detail/impl/select_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -35,7 +35,7 @@ namespace asio { namespace detail { inline void select_reactor::post_immediate_completion( - reactor_op* op, bool is_continuation) + operation* op, bool is_continuation) const { scheduler_.post_immediate_completion(op, is_continuation); } diff --git a/3rdparty/asio/include/asio/detail/impl/select_reactor.ipp b/3rdparty/asio/include/asio/detail/impl/select_reactor.ipp index f7d64731de7..5e5946bb84b 100644 --- a/3rdparty/asio/include/asio/detail/impl/select_reactor.ipp +++ b/3rdparty/asio/include/asio/detail/impl/select_reactor.ipp @@ -2,7 +2,7 @@ // detail/impl/select_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -66,6 +66,7 @@ select_reactor::select_reactor(asio::execution_context& ctx) #if defined(ASIO_HAS_IOCP) stop_thread_(false), thread_(0), + restart_reactor_(this), #endif // defined(ASIO_HAS_IOCP) shutdown_(false) { @@ -113,8 +114,12 @@ void select_reactor::shutdown() void select_reactor::notify_fork( asio::execution_context::fork_event fork_ev) { +#if defined(ASIO_HAS_IOCP) + (void)fork_ev; +#else // defined(ASIO_HAS_IOCP) if (fork_ev == asio::execution_context::fork_child) interrupter_.recreate(); +#endif // defined(ASIO_HAS_IOCP) } void select_reactor::init_task() @@ -146,15 +151,23 @@ void select_reactor::move_descriptor(socket_type, { } +void select_reactor::call_post_immediate_completion( + operation* op, bool is_continuation, const void* self) +{ + static_cast<const select_reactor*>(self)->post_immediate_completion( + op, is_continuation); +} + void select_reactor::start_op(int op_type, socket_type descriptor, - select_reactor::per_descriptor_data&, reactor_op* op, - bool is_continuation, bool) + select_reactor::per_descriptor_data&, reactor_op* op, bool is_continuation, + bool, void (*on_immediate)(operation*, bool, const void*), + const void* immediate_arg) { asio::detail::mutex::scoped_lock lock(mutex_); if (shutdown_) { - post_immediate_completion(op, is_continuation); + on_immediate(op, is_continuation, immediate_arg); return; } @@ -262,7 +275,12 @@ void select_reactor::run(long usec, op_queue<operation>& ops) if (!interrupter_.reset()) { lock.lock(); +#if defined(ASIO_HAS_IOCP) + stop_thread_ = true; + scheduler_.post_immediate_completion(&restart_reactor_, false); +#else // defined(ASIO_HAS_IOCP) interrupter_.recreate(); +#endif // defined(ASIO_HAS_IOCP) } --retval; } @@ -299,11 +317,36 @@ void select_reactor::run_thread() { lock.unlock(); op_queue<operation> ops; - run(true, ops); + run(-1, ops); scheduler_.post_deferred_completions(ops); lock.lock(); } } + +void select_reactor::restart_reactor::do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, std::size_t /*bytes_transferred*/) +{ + if (owner) + { + select_reactor* reactor = static_cast<restart_reactor*>(base)->reactor_; + + if (reactor->thread_) + { + reactor->thread_->join(); + delete reactor->thread_; + reactor->thread_ = 0; + } + + asio::detail::mutex::scoped_lock lock(reactor->mutex_); + reactor->interrupter_.recreate(); + reactor->stop_thread_ = false; + lock.unlock(); + + asio::detail::signal_blocker sb; + reactor->thread_ = + new asio::detail::thread(thread_function(reactor)); + } +} #endif // defined(ASIO_HAS_IOCP) void select_reactor::do_add_timer_queue(timer_queue_base& queue) diff --git a/3rdparty/asio/include/asio/detail/impl/service_registry.hpp b/3rdparty/asio/include/asio/detail/impl/service_registry.hpp index 8b9566e103a..2490636c0ad 100644 --- a/3rdparty/asio/include/asio/detail/impl/service_registry.hpp +++ b/3rdparty/asio/include/asio/detail/impl/service_registry.hpp @@ -2,7 +2,7 @@ // detail/impl/service_registry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -64,8 +64,7 @@ inline void service_registry::init_key( #if !defined(ASIO_NO_TYPEID) template <typename Service> void service_registry::init_key(execution_context::service::key& key, - typename enable_if< - is_base_of<typename Service::key_type, Service>::value>::type*) + enable_if_t<is_base_of<typename Service::key_type, Service>::value>*) { key.type_info_ = &typeid(typeid_wrapper<Service>); key.id_ = 0; diff --git a/3rdparty/asio/include/asio/detail/impl/service_registry.ipp b/3rdparty/asio/include/asio/detail/impl/service_registry.ipp index 363a56fb82f..b0133421d25 100644 --- a/3rdparty/asio/include/asio/detail/impl/service_registry.ipp +++ b/3rdparty/asio/include/asio/detail/impl/service_registry.ipp @@ -2,7 +2,7 @@ // detail/impl/service_registry.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/signal_set_service.ipp b/3rdparty/asio/include/asio/detail/impl/signal_set_service.ipp index b657d0e580f..7f6be8b71a9 100644 --- a/3rdparty/asio/include/asio/detail/impl/signal_set_service.ipp +++ b/3rdparty/asio/include/asio/detail/impl/signal_set_service.ipp @@ -2,7 +2,7 @@ // detail/impl/signal_set_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,12 +19,17 @@ #include <cstring> #include <stdexcept> -#include "asio/detail/reactor.hpp" #include "asio/detail/signal_blocker.hpp" #include "asio/detail/signal_set_service.hpp" #include "asio/detail/static_mutex.hpp" #include "asio/detail/throw_exception.hpp" +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/io_uring_service.hpp" +#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/reactor.hpp" +#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) + #include "asio/detail/push_options.hpp" namespace asio { @@ -49,12 +54,16 @@ struct signal_state // A count of the number of objects that are registered for each signal. std::size_t registration_count_[max_signal_number]; + + // The flags used for each registered signal. + signal_set_base::flags_t flags_[max_signal_number]; }; signal_state* get_signal_state() { static signal_state state = { - ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0, { 0 } }; + ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0, + { 0 }, { signal_set_base::flags_t() } }; return &state; } @@ -85,9 +94,42 @@ void asio_signal_handler(int signal_number) #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \ && !defined(__CYGWIN__) -class signal_set_service::pipe_read_op : public reactor_op +class signal_set_service::pipe_read_op : +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + public io_uring_operation +# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) + public reactor_op +# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) { public: +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + pipe_read_op() + : io_uring_operation(asio::error_code(), &pipe_read_op::do_prepare, + &pipe_read_op::do_perform, pipe_read_op::do_complete) + { + } + + static void do_prepare(io_uring_operation*, ::io_uring_sqe* sqe) + { + signal_state* state = get_signal_state(); + + int fd = state->read_descriptor_; + ::io_uring_prep_poll_add(sqe, fd, POLLIN); + } + + static bool do_perform(io_uring_operation*, bool) + { + signal_state* state = get_signal_state(); + + int fd = state->read_descriptor_; + int signal_number = 0; + while (::read(fd, &signal_number, sizeof(int)) == sizeof(int)) + if (signal_number >= 0 && signal_number < max_signal_number) + signal_set_service::deliver_signal(signal_number); + + return false; + } +# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) pipe_read_op() : reactor_op(asio::error_code(), &pipe_read_op::do_perform, pipe_read_op::do_complete) @@ -106,6 +148,7 @@ public: return not_done; } +# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) static void do_complete(void* /*owner*/, operation* base, const asio::error_code& /*ec*/, @@ -125,7 +168,11 @@ signal_set_service::signal_set_service(execution_context& context) #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \ && !defined(__CYGWIN__) +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + io_uring_service_(asio::use_service<io_uring_service>(context)), +# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) reactor_(asio::use_service<reactor>(context)), +# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__) @@ -137,7 +184,11 @@ signal_set_service::signal_set_service(execution_context& context) #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \ && !defined(__CYGWIN__) +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + io_uring_service_.init_task(); +# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) reactor_.init_task(); +# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__) @@ -187,8 +238,14 @@ void signal_set_service::notify_fork(execution_context::fork_event fork_ev) int read_descriptor = state->read_descriptor_; state->fork_prepared_ = true; lock.unlock(); +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + (void)read_descriptor; + io_uring_service_.deregister_io_object(io_object_data_); + io_uring_service_.cleanup_io_object(io_object_data_); +# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_); reactor_.cleanup_descriptor_data(reactor_data_); +# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) } break; case execution_context::fork_parent: @@ -197,8 +254,14 @@ void signal_set_service::notify_fork(execution_context::fork_event fork_ev) int read_descriptor = state->read_descriptor_; state->fork_prepared_ = false; lock.unlock(); +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + (void)read_descriptor; + io_uring_service_.register_internal_io_object(io_object_data_, + io_uring_service::read_op, new pipe_read_op); +# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) reactor_.register_internal_descriptor(reactor::read_op, read_descriptor, reactor_data_, new pipe_read_op); +# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) } break; case execution_context::fork_child: @@ -210,8 +273,14 @@ void signal_set_service::notify_fork(execution_context::fork_event fork_ev) int read_descriptor = state->read_descriptor_; state->fork_prepared_ = false; lock.unlock(); +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + (void)read_descriptor; + io_uring_service_.register_internal_io_object(io_object_data_, + io_uring_service::read_op, new pipe_read_op); +# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) reactor_.register_internal_descriptor(reactor::read_op, read_descriptor, reactor_data_, new pipe_read_op); +# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) } break; default: @@ -241,8 +310,8 @@ void signal_set_service::destroy( } asio::error_code signal_set_service::add( - signal_set_service::implementation_type& impl, - int signal_number, asio::error_code& ec) + signal_set_service::implementation_type& impl, int signal_number, + signal_set_base::flags_t f, asio::error_code& ec) { // Check that the signal number is valid. if (signal_number < 0 || signal_number >= max_signal_number) @@ -251,6 +320,15 @@ asio::error_code signal_set_service::add( return ec; } + // Check that the specified flags are supported. +#if !defined(ASIO_HAS_SIGACTION) + if (f != signal_set_base::flags::dont_care) + { + ec = asio::error::operation_not_supported; + return ec; + } +#endif // !defined(ASIO_HAS_SIGACTION) + signal_state* state = get_signal_state(); static_mutex::scoped_lock lock(state->mutex_); @@ -278,6 +356,8 @@ asio::error_code signal_set_service::add( memset(&sa, 0, sizeof(sa)); sa.sa_handler = asio_signal_handler; sigfillset(&sa.sa_mask); + if (f != signal_set_base::flags::dont_care) + sa.sa_flags = static_cast<int>(f); if (::sigaction(signal_number, &sa, 0) == -1) # else // defined(ASIO_HAS_SIGACTION) if (::signal(signal_number, asio_signal_handler) == SIG_ERR) @@ -292,7 +372,39 @@ asio::error_code signal_set_service::add( delete new_registration; return ec; } +# if defined(ASIO_HAS_SIGACTION) + state->flags_[signal_number] = f; +# endif // defined(ASIO_HAS_SIGACTION) } +# if defined(ASIO_HAS_SIGACTION) + // Otherwise check to see if the flags have changed. + else if (f != signal_set_base::flags::dont_care) + { + if (f != state->flags_[signal_number]) + { + using namespace std; // For memset. + if (state->flags_[signal_number] != signal_set_base::flags::dont_care) + { + ec = asio::error::invalid_argument; + delete new_registration; + return ec; + } + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = asio_signal_handler; + sigfillset(&sa.sa_mask); + sa.sa_flags = static_cast<int>(f); + if (::sigaction(signal_number, &sa, 0) == -1) + { + ec = asio::error_code(errno, + asio::error::get_system_category()); + delete new_registration; + return ec; + } + state->flags_[signal_number] = f; + } + } +# endif // defined(ASIO_HAS_SIGACTION) #endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION) // Record the new registration in the set. @@ -361,6 +473,9 @@ asio::error_code signal_set_service::remove( # endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) return ec; } +# if defined(ASIO_HAS_SIGACTION) + state->flags_[signal_number] = signal_set_base::flags_t(); +# endif // defined(ASIO_HAS_SIGACTION) } #endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION) @@ -415,6 +530,9 @@ asio::error_code signal_set_service::clear( # endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) return ec; } +# if defined(ASIO_HAS_SIGACTION) + state->flags_[reg->signal_number_] = signal_set_base::flags_t(); +# endif // defined(ASIO_HAS_SIGACTION) } #endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION) @@ -462,6 +580,33 @@ asio::error_code signal_set_service::cancel( return ec; } +void signal_set_service::cancel_ops_by_key( + signal_set_service::implementation_type& impl, void* cancellation_key) +{ + op_queue<operation> ops; + { + op_queue<signal_op> other_ops; + signal_state* state = get_signal_state(); + static_mutex::scoped_lock lock(state->mutex_); + + while (signal_op* op = impl.queue_.front()) + { + impl.queue_.pop(); + if (op->cancellation_key_ == cancellation_key) + { + op->ec_ = asio::error::operation_aborted; + ops.push(op); + } + else + other_ops.push(op); + } + + impl.queue_.push(other_ops); + } + + scheduler_.post_deferred_completions(ops); +} + void signal_set_service::deliver_signal(int signal_number) { signal_state* state = get_signal_state(); @@ -538,8 +683,14 @@ void signal_set_service::add_service(signal_set_service* service) // Register for pipe readiness notifications. int read_descriptor = state->read_descriptor_; lock.unlock(); +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + (void)read_descriptor; + service->io_uring_service_.register_internal_io_object( + service->io_object_data_, io_uring_service::read_op, new pipe_read_op); +# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) service->reactor_.register_internal_descriptor(reactor::read_op, read_descriptor, service->reactor_data_, new pipe_read_op); +# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__) @@ -558,10 +709,17 @@ void signal_set_service::remove_service(signal_set_service* service) // Disable the pipe readiness notifications. int read_descriptor = state->read_descriptor_; lock.unlock(); +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + (void)read_descriptor; + service->io_uring_service_.deregister_io_object(service->io_object_data_); + service->io_uring_service_.cleanup_io_object(service->io_object_data_); + lock.lock(); +# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) service->reactor_.deregister_internal_descriptor( read_descriptor, service->reactor_data_); service->reactor_.cleanup_descriptor_data(service->reactor_data_); lock.lock(); +# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__) diff --git a/3rdparty/asio/include/asio/detail/impl/socket_ops.ipp b/3rdparty/asio/include/asio/detail/impl/socket_ops.ipp index 3403f1c0a85..7feb7ca02df 100644 --- a/3rdparty/asio/include/asio/detail/impl/socket_ops.ipp +++ b/3rdparty/asio/include/asio/detail/impl/socket_ops.ipp @@ -2,7 +2,7 @@ // detail/impl/socket_ops.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -78,7 +78,7 @@ inline void get_last_error( { if (!is_error_condition) { - ec.assign(0, ec.category()); + asio::error::clear(ec); } else { @@ -94,16 +94,18 @@ inline void get_last_error( template <typename SockLenType> inline socket_type call_accept(SockLenType msghdr::*, - socket_type s, socket_addr_type* addr, std::size_t* addrlen) + socket_type s, void* addr, std::size_t* addrlen) { SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0; - socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0); + socket_type result = ::accept(s, + static_cast<socket_addr_type*>(addr), + addrlen ? &tmp_addrlen : 0); if (addrlen) *addrlen = (std::size_t)tmp_addrlen; return result; } -socket_type accept(socket_type s, socket_addr_type* addr, +socket_type accept(socket_type s, void* addr, std::size_t* addrlen, asio::error_code& ec) { if (s == invalid_socket) @@ -129,12 +131,12 @@ socket_type accept(socket_type s, socket_addr_type* addr, } #endif - ec.assign(0, ec.category()); + asio::error::clear(ec); return new_s; } socket_type sync_accept(socket_type s, state_type state, - socket_addr_type* addr, std::size_t* addrlen, asio::error_code& ec) + void* addr, std::size_t* addrlen, asio::error_code& ec) { // Accept a socket. for (;;) @@ -179,9 +181,8 @@ socket_type sync_accept(socket_type s, state_type state, #if defined(ASIO_HAS_IOCP) -void complete_iocp_accept(socket_type s, - void* output_buffer, DWORD address_length, - socket_addr_type* addr, std::size_t* addrlen, +void complete_iocp_accept(socket_type s, void* output_buffer, + DWORD address_length, void* addr, std::size_t* addrlen, socket_type new_socket, asio::error_code& ec) { // Map non-portable errors to their portable counterparts. @@ -225,7 +226,7 @@ void complete_iocp_accept(socket_type s, #else // defined(ASIO_HAS_IOCP) bool non_blocking_accept(socket_type s, - state_type state, socket_addr_type* addr, std::size_t* addrlen, + state_type state, void* addr, std::size_t* addrlen, asio::error_code& ec, socket_type& new_socket) { for (;;) @@ -272,12 +273,13 @@ bool non_blocking_accept(socket_type s, template <typename SockLenType> inline int call_bind(SockLenType msghdr::*, - socket_type s, const socket_addr_type* addr, std::size_t addrlen) + socket_type s, const void* addr, std::size_t addrlen) { - return ::bind(s, addr, (SockLenType)addrlen); + return ::bind(s, static_cast<const socket_addr_type*>(addr), + (SockLenType)addrlen); } -int bind(socket_type s, const socket_addr_type* addr, +int bind(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec) { if (s == invalid_socket) @@ -337,7 +339,25 @@ int close(socket_type s, state_type& state, ::fcntl(s, F_SETFL, flags & ~O_NONBLOCK); # else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) ioctl_arg_type arg = 0; +# if defined(ENOTTY) || defined(ENOTCAPABLE) + result = ::ioctl(s, FIONBIO, &arg); + get_last_error(ec, result < 0); + if (false +# if defined(ENOTTY) + || ec.value() == ENOTTY +# endif // defined(ENOTTY) +# if defined(ENOTCAPABLE) + || ec.value() == ENOTCAPABLE +# endif // defined(ENOTCAPABLE) + ) + { + int flags = ::fcntl(s, F_GETFL, 0); + if (flags >= 0) + ::fcntl(s, F_SETFL, flags & ~O_NONBLOCK); + } +# else // defined(ENOTTY) || defined(ENOTCAPABLE) ::ioctl(s, FIONBIO, &arg); +# endif // defined(ENOTTY) || defined(ENOTCAPABLE) # endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) #endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) state &= ~non_blocking; @@ -376,11 +396,31 @@ bool set_user_non_blocking(socket_type s, result = ::fcntl(s, F_SETFL, flag); get_last_error(ec, result < 0); } -#else +#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) ioctl_arg_type arg = (value ? 1 : 0); int result = ::ioctl(s, FIONBIO, &arg); get_last_error(ec, result < 0); -#endif +# if defined(ENOTTY) || defined(ENOTCAPABLE) + if (false +# if defined(ENOTTY) + || ec.value() == ENOTTY +# endif // defined(ENOTTY) +# if defined(ENOTCAPABLE) + || ec.value() == ENOTCAPABLE +# endif // defined(ENOTCAPABLE) + ) + { + result = ::fcntl(s, F_GETFL, 0); + get_last_error(ec, result < 0); + if (result >= 0) + { + int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); + result = ::fcntl(s, F_SETFL, flag); + get_last_error(ec, result < 0); + } + } +# endif // defined(ENOTTY) || defined(ENOTCAPABLE) +#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) if (result >= 0) { @@ -430,11 +470,31 @@ bool set_internal_non_blocking(socket_type s, result = ::fcntl(s, F_SETFL, flag); get_last_error(ec, result < 0); } -#else +#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) ioctl_arg_type arg = (value ? 1 : 0); int result = ::ioctl(s, FIONBIO, &arg); get_last_error(ec, result < 0); -#endif +# if defined(ENOTTY) || defined(ENOTCAPABLE) + if (false +# if defined(ENOTTY) + || ec.value() == ENOTTY +# endif // defined(ENOTTY) +# if defined(ENOTCAPABLE) + || ec.value() == ENOTCAPABLE +# endif // defined(ENOTCAPABLE) + ) + { + result = ::fcntl(s, F_GETFL, 0); + get_last_error(ec, result < 0); + if (result >= 0) + { + int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK)); + result = ::fcntl(s, F_SETFL, flag); + get_last_error(ec, result < 0); + } + } +# endif // defined(ENOTTY) || defined(ENOTCAPABLE) +#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__) if (result >= 0) { @@ -463,12 +523,13 @@ int shutdown(socket_type s, int what, asio::error_code& ec) template <typename SockLenType> inline int call_connect(SockLenType msghdr::*, - socket_type s, const socket_addr_type* addr, std::size_t addrlen) + socket_type s, const void* addr, std::size_t addrlen) { - return ::connect(s, addr, (SockLenType)addrlen); + return ::connect(s, static_cast<const socket_addr_type*>(addr), + (SockLenType)addrlen); } -int connect(socket_type s, const socket_addr_type* addr, +int connect(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec) { if (s == invalid_socket) @@ -481,12 +542,17 @@ int connect(socket_type s, const socket_addr_type* addr, get_last_error(ec, result != 0); #if defined(__linux__) if (result != 0 && ec == asio::error::try_again) - ec = asio::error::no_buffer_space; + { + if (static_cast<const socket_addr_type*>(addr)->sa_family == AF_UNIX) + ec = asio::error::in_progress; + else + ec = asio::error::no_buffer_space; + } #endif // defined(__linux__) return result; } -void sync_connect(socket_type s, const socket_addr_type* addr, +void sync_connect(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec) { // Perform the connect operation. @@ -596,7 +662,7 @@ bool non_blocking_connect(socket_type s, asio::error_code& ec) asio::error::get_system_category()); } else - ec.assign(0, ec.category()); + asio::error::clear(ec); } return true; @@ -722,9 +788,9 @@ void init_buf(buf& b, const void* data, size_t size) #endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) } -inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr) +inline void init_msghdr_msg_name(void*& name, void* addr) { - name = addr; + name = static_cast<socket_addr_type*>(addr); } inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr) @@ -733,15 +799,15 @@ inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr) } template <typename T> -inline void init_msghdr_msg_name(T& name, socket_addr_type* addr) +inline void init_msghdr_msg_name(T& name, void* addr) { - name = reinterpret_cast<T>(addr); + name = static_cast<T>(addr); } template <typename T> -inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr) +inline void init_msghdr_msg_name(T& name, const void* addr) { - name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr)); + name = static_cast<T>(const_cast<void*>(addr)); } signed_size_type recv(socket_type s, buf* bufs, size_t count, @@ -763,7 +829,7 @@ signed_size_type recv(socket_type s, buf* bufs, size_t count, result = 0; if (result != 0) return socket_error_retval; - ec.assign(0, ec.category()); + asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr(); @@ -796,7 +862,7 @@ signed_size_type recv1(socket_type s, void* data, size_t size, result = 0; if (result != 0) return socket_error_retval; - ec.assign(0, ec.category()); + asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) signed_size_type result = ::recv(s, static_cast<char*>(data), size, flags); @@ -817,7 +883,7 @@ size_t sync_recv(socket_type s, state_type state, buf* bufs, // A request to read 0 bytes on a stream is a no-op. if (all_empty && (state & stream_oriented)) { - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } @@ -862,7 +928,7 @@ size_t sync_recv1(socket_type s, state_type state, void* data, // A request to read 0 bytes on a stream is a no-op. if (size == 0 && (state & stream_oriented)) { - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } @@ -915,7 +981,7 @@ void complete_iocp_recv(state_type state, } else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA) { - ec.assign(0, ec.category()); + asio::error::clear(ec); } // Check for connection closed. @@ -1008,8 +1074,7 @@ bool non_blocking_recv1(socket_type s, #endif // defined(ASIO_HAS_IOCP) signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, - int flags, socket_addr_type* addr, std::size_t* addrlen, - asio::error_code& ec) + int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) { #if defined(ASIO_WINDOWS) || defined(__CYGWIN__) // Receive some data. @@ -1017,8 +1082,8 @@ signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, DWORD bytes_transferred = 0; DWORD recv_flags = flags; int tmp_addrlen = (int)*addrlen; - int result = ::WSARecvFrom(s, bufs, recv_buf_count, - &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0); + int result = ::WSARecvFrom(s, bufs, recv_buf_count, &bytes_transferred, + &recv_flags, static_cast<socket_addr_type*>(addr), &tmp_addrlen, 0, 0); get_last_error(ec, true); *addrlen = (std::size_t)tmp_addrlen; if (ec.value() == ERROR_NETNAME_DELETED) @@ -1029,7 +1094,7 @@ signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, result = 0; if (result != 0) return socket_error_retval; - ec.assign(0, ec.category()); + asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr(); @@ -1045,21 +1110,19 @@ signed_size_type recvfrom(socket_type s, buf* bufs, size_t count, } template <typename SockLenType> -inline signed_size_type call_recvfrom(SockLenType msghdr::*, - socket_type s, void* data, size_t size, int flags, - socket_addr_type* addr, std::size_t* addrlen) +inline signed_size_type call_recvfrom(SockLenType msghdr::*, socket_type s, + void* data, size_t size, int flags, void* addr, std::size_t* addrlen) { SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0; - signed_size_type result = ::recvfrom(s, static_cast<char*>(data), - size, flags, addr, addrlen ? &tmp_addrlen : 0); + signed_size_type result = ::recvfrom(s, static_cast<char*>(data), size, + flags, static_cast<socket_addr_type*>(addr), addrlen ? &tmp_addrlen : 0); if (addrlen) *addrlen = (std::size_t)tmp_addrlen; return result; } signed_size_type recvfrom1(socket_type s, void* data, size_t size, - int flags, socket_addr_type* addr, std::size_t* addrlen, - asio::error_code& ec) + int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) { #if defined(ASIO_WINDOWS) || defined(__CYGWIN__) // Receive some data. @@ -1069,8 +1132,8 @@ signed_size_type recvfrom1(socket_type s, void* data, size_t size, DWORD bytes_transferred = 0; DWORD recv_flags = flags; int tmp_addrlen = (int)*addrlen; - int result = ::WSARecvFrom(s, &buf, 1, &bytes_transferred, - &recv_flags, addr, &tmp_addrlen, 0, 0); + int result = ::WSARecvFrom(s, &buf, 1, &bytes_transferred, &recv_flags, + static_cast<socket_addr_type*>(addr), &tmp_addrlen, 0, 0); get_last_error(ec, true); *addrlen = (std::size_t)tmp_addrlen; if (ec.value() == ERROR_NETNAME_DELETED) @@ -1081,7 +1144,7 @@ signed_size_type recvfrom1(socket_type s, void* data, size_t size, result = 0; if (result != 0) return socket_error_retval; - ec.assign(0, ec.category()); + asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) signed_size_type result = call_recvfrom(&msghdr::msg_namelen, @@ -1091,9 +1154,8 @@ signed_size_type recvfrom1(socket_type s, void* data, size_t size, #endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) } -size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, - size_t count, int flags, socket_addr_type* addr, - std::size_t* addrlen, asio::error_code& ec) +size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, size_t count, + int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) { if (s == invalid_socket) { @@ -1124,9 +1186,8 @@ size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, } } -size_t sync_recvfrom1(socket_type s, state_type state, void* data, - size_t size, int flags, socket_addr_type* addr, - std::size_t* addrlen, asio::error_code& ec) +size_t sync_recvfrom1(socket_type s, state_type state, void* data, size_t size, + int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) { if (s == invalid_socket) { @@ -1177,15 +1238,14 @@ void complete_iocp_recvfrom( } else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA) { - ec.assign(0, ec.category()); + asio::error::clear(ec); } } #else // defined(ASIO_HAS_IOCP) -bool non_blocking_recvfrom(socket_type s, - buf* bufs, size_t count, int flags, - socket_addr_type* addr, std::size_t* addrlen, +bool non_blocking_recvfrom(socket_type s, buf* bufs, + size_t count, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec, size_t& bytes_transferred) { for (;;) @@ -1216,9 +1276,8 @@ bool non_blocking_recvfrom(socket_type s, } } -bool non_blocking_recvfrom1(socket_type s, - void* data, size_t size, int flags, - socket_addr_type* addr, std::size_t* addrlen, +bool non_blocking_recvfrom1(socket_type s, void* data, + size_t size, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec, size_t& bytes_transferred) { for (;;) @@ -1324,7 +1383,7 @@ void complete_iocp_recvmsg( } else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA) { - ec.assign(0, ec.category()); + asio::error::clear(ec); } } @@ -1381,7 +1440,7 @@ signed_size_type send(socket_type s, const buf* bufs, size_t count, ec = asio::error::connection_refused; if (result != 0) return socket_error_retval; - ec.assign(0, ec.category()); + asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr(); @@ -1415,7 +1474,7 @@ signed_size_type send1(socket_type s, const void* data, size_t size, ec = asio::error::connection_refused; if (result != 0) return socket_error_retval; - ec.assign(0, ec.category()); + asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) #if defined(ASIO_HAS_MSG_NOSIGNAL) @@ -1440,7 +1499,7 @@ size_t sync_send(socket_type s, state_type state, const buf* bufs, // A request to write 0 bytes to a stream is a no-op. if (all_empty && (state & stream_oriented)) { - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } @@ -1478,7 +1537,7 @@ size_t sync_send1(socket_type s, state_type state, const void* data, // A request to write 0 bytes to a stream is a no-op. if (size == 0 && (state & stream_oriented)) { - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } @@ -1590,16 +1649,17 @@ bool non_blocking_send1(socket_type s, #endif // defined(ASIO_HAS_IOCP) -signed_size_type sendto(socket_type s, const buf* bufs, size_t count, - int flags, const socket_addr_type* addr, std::size_t addrlen, - asio::error_code& ec) +signed_size_type sendto(socket_type s, const buf* bufs, + size_t count, int flags, const void* addr, + std::size_t addrlen, asio::error_code& ec) { #if defined(ASIO_WINDOWS) || defined(__CYGWIN__) // Send the data. DWORD send_buf_count = static_cast<DWORD>(count); DWORD bytes_transferred = 0; int result = ::WSASendTo(s, const_cast<buf*>(bufs), - send_buf_count, &bytes_transferred, flags, addr, + send_buf_count, &bytes_transferred, flags, + static_cast<const socket_addr_type*>(addr), static_cast<int>(addrlen), 0, 0); get_last_error(ec, true); if (ec.value() == ERROR_NETNAME_DELETED) @@ -1608,7 +1668,7 @@ signed_size_type sendto(socket_type s, const buf* bufs, size_t count, ec = asio::error::connection_refused; if (result != 0) return socket_error_retval; - ec.assign(0, ec.category()); + asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) msghdr msg = msghdr(); @@ -1628,15 +1688,15 @@ signed_size_type sendto(socket_type s, const buf* bufs, size_t count, template <typename SockLenType> inline signed_size_type call_sendto(SockLenType msghdr::*, socket_type s, const void* data, size_t size, int flags, - const socket_addr_type* addr, std::size_t addrlen) + const void* addr, std::size_t addrlen) { - return ::sendto(s, static_cast<char*>(const_cast<void*>(data)), - size, flags, addr, (SockLenType)addrlen); + return ::sendto(s, static_cast<char*>(const_cast<void*>(data)), size, flags, + static_cast<const socket_addr_type*>(addr), (SockLenType)addrlen); } -signed_size_type sendto1(socket_type s, const void* data, size_t size, - int flags, const socket_addr_type* addr, std::size_t addrlen, - asio::error_code& ec) +signed_size_type sendto1(socket_type s, const void* data, + size_t size, int flags, const void* addr, + std::size_t addrlen, asio::error_code& ec) { #if defined(ASIO_WINDOWS) || defined(__CYGWIN__) // Send the data. @@ -1644,8 +1704,9 @@ signed_size_type sendto1(socket_type s, const void* data, size_t size, buf.buf = const_cast<char*>(static_cast<const char*>(data)); buf.len = static_cast<ULONG>(size); DWORD bytes_transferred = 0; - int result = ::WSASendTo(s, &buf, 1, &bytes_transferred, - flags, addr, static_cast<int>(addrlen), 0, 0); + int result = ::WSASendTo(s, &buf, 1, &bytes_transferred, flags, + static_cast<const socket_addr_type*>(addr), + static_cast<int>(addrlen), 0, 0); get_last_error(ec, true); if (ec.value() == ERROR_NETNAME_DELETED) ec = asio::error::connection_reset; @@ -1653,7 +1714,7 @@ signed_size_type sendto1(socket_type s, const void* data, size_t size, ec = asio::error::connection_refused; if (result != 0) return socket_error_retval; - ec.assign(0, ec.category()); + asio::error::clear(ec); return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) #if defined(ASIO_HAS_MSG_NOSIGNAL) @@ -1666,8 +1727,8 @@ signed_size_type sendto1(socket_type s, const void* data, size_t size, #endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) } -size_t sync_sendto(socket_type s, state_type state, const buf* bufs, - size_t count, int flags, const socket_addr_type* addr, +size_t sync_sendto(socket_type s, state_type state, + const buf* bufs, size_t count, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec) { if (s == invalid_socket) @@ -1699,8 +1760,8 @@ size_t sync_sendto(socket_type s, state_type state, const buf* bufs, } } -size_t sync_sendto1(socket_type s, state_type state, const void* data, - size_t size, int flags, const socket_addr_type* addr, +size_t sync_sendto1(socket_type s, state_type state, + const void* data, size_t size, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec) { if (s == invalid_socket) @@ -1736,7 +1797,7 @@ size_t sync_sendto1(socket_type s, state_type state, const void* data, bool non_blocking_sendto(socket_type s, const buf* bufs, size_t count, int flags, - const socket_addr_type* addr, std::size_t addrlen, + const void* addr, std::size_t addrlen, asio::error_code& ec, size_t& bytes_transferred) { for (;;) @@ -1769,7 +1830,7 @@ bool non_blocking_sendto(socket_type s, bool non_blocking_sendto1(socket_type s, const void* data, size_t size, int flags, - const socket_addr_type* addr, std::size_t addrlen, + const void* addr, std::size_t addrlen, asio::error_code& ec, size_t& bytes_transferred) { for (;;) @@ -1883,7 +1944,7 @@ int setsockopt(socket_type s, state_type& state, int level, int optname, state |= enable_connection_aborted; else state &= ~enable_connection_aborted; - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } @@ -1968,7 +2029,7 @@ int getsockopt(socket_type s, state_type state, int level, int optname, } *static_cast<int*>(optval) = (state & enable_connection_aborted) ? 1 : 0; - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } @@ -1995,7 +2056,7 @@ int getsockopt(socket_type s, state_type state, int level, int optname, // value is non-zero (i.e. true). This corresponds to the behavior of // IPv6 sockets on Windows platforms pre-Vista. *static_cast<DWORD*>(optval) = 1; - ec.assign(0, ec.category()); + asio::error::clear(ec); } return result; } @@ -2015,7 +2076,7 @@ int getsockopt(socket_type s, state_type state, int level, int optname, // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets // on Windows platforms pre-Vista. *static_cast<DWORD*>(optval) = 1; - ec.assign(0, ec.category()); + asio::error::clear(ec); } return result; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) @@ -2040,16 +2101,17 @@ int getsockopt(socket_type s, state_type state, int level, int optname, template <typename SockLenType> inline int call_getpeername(SockLenType msghdr::*, - socket_type s, socket_addr_type* addr, std::size_t* addrlen) + socket_type s, void* addr, std::size_t* addrlen) { SockLenType tmp_addrlen = (SockLenType)*addrlen; - int result = ::getpeername(s, addr, &tmp_addrlen); + int result = ::getpeername(s, + static_cast<socket_addr_type*>(addr), &tmp_addrlen); *addrlen = (std::size_t)tmp_addrlen; return result; } -int getpeername(socket_type s, socket_addr_type* addr, - std::size_t* addrlen, bool cached, asio::error_code& ec) +int getpeername(socket_type s, void* addr, std::size_t* addrlen, + bool cached, asio::error_code& ec) { if (s == invalid_socket) { @@ -2076,7 +2138,7 @@ int getpeername(socket_type s, socket_addr_type* addr, } // The cached value is still valid. - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } #else // defined(ASIO_WINDOWS) && !defined(ASIO_WINDOWS_APP) @@ -2092,15 +2154,16 @@ int getpeername(socket_type s, socket_addr_type* addr, template <typename SockLenType> inline int call_getsockname(SockLenType msghdr::*, - socket_type s, socket_addr_type* addr, std::size_t* addrlen) + socket_type s, void* addr, std::size_t* addrlen) { SockLenType tmp_addrlen = (SockLenType)*addrlen; - int result = ::getsockname(s, addr, &tmp_addrlen); + int result = ::getsockname(s, + static_cast<socket_addr_type*>(addr), &tmp_addrlen); *addrlen = (std::size_t)tmp_addrlen; return result; } -int getsockname(socket_type s, socket_addr_type* addr, +int getsockname(socket_type s, void* addr, std::size_t* addrlen, asio::error_code& ec) { if (s == invalid_socket) @@ -2171,7 +2234,7 @@ int select(int nfds, fd_set* readfds, fd_set* writefds, if (milliseconds == 0) milliseconds = 1; // Force context switch. ::Sleep(milliseconds); - ec.assign(0, ec.category()); + asio::error::clear(ec); return 0; } @@ -2491,7 +2554,7 @@ const char* inet_ntop(int af, const void* src, char* dest, size_t length, // Windows may set error code on success. if (result != socket_error_retval) - ec.assign(0, ec.category()); + asio::error::clear(ec); // Windows may not set an error code on failure. else if (result == socket_error_retval && !ec) @@ -2514,7 +2577,11 @@ const char* inet_ntop(int af, const void* src, char* dest, size_t length, && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02)); if ((!is_link_local && !is_multicast_link_local) || if_indextoname(static_cast<unsigned>(scope_id), if_name + 1) == 0) +#if defined(ASIO_HAS_SNPRINTF) + snprintf(if_name + 1, sizeof(if_name) - 1, "%lu", scope_id); +#else // defined(ASIO_HAS_SNPRINTF) sprintf(if_name + 1, "%lu", scope_id); +#endif // defined(ASIO_HAS_SNPRINTF) strcat(dest, if_name); } return result; @@ -2545,7 +2612,7 @@ int inet_pton(int af, const char* src, void* dest, bytes[1] = static_cast<unsigned char>(b1); bytes[2] = static_cast<unsigned char>(b2); bytes[3] = static_cast<unsigned char>(b3); - ec.assign(0, ec.category()); + asio::error::clear(ec); return 1; } else if (af == ASIO_OS_DEF(AF_INET6)) @@ -2661,7 +2728,7 @@ int inet_pton(int af, const char* src, void* dest, for (int i = 0; i < num_back_bytes; ++i) bytes[16 - num_back_bytes + i] = back_bytes[i]; - ec.assign(0, ec.category()); + asio::error::clear(ec); return 1; } else @@ -2704,12 +2771,12 @@ int inet_pton(int af, const char* src, void* dest, if (result != socket_error_retval) { memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type)); - ec.assign(0, ec.category()); + asio::error::clear(ec); } else if (strcmp(src, "255.255.255.255") == 0) { static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE; - ec.assign(0, ec.category()); + asio::error::clear(ec); } } else // AF_INET6 @@ -2719,7 +2786,7 @@ int inet_pton(int af, const char* src, void* dest, memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type)); if (scope_id) *scope_id = address.v6.sin6_scope_id; - ec.assign(0, ec.category()); + asio::error::clear(ec); } } @@ -2728,7 +2795,7 @@ int inet_pton(int af, const char* src, void* dest, ec = asio::error::invalid_argument; if (result != socket_error_retval) - ec.assign(0, ec.category()); + asio::error::clear(ec); return result == socket_error_retval ? -1 : 1; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__) @@ -3622,7 +3689,9 @@ inline asio::error_code getnameinfo_emulation( { return ec = asio::error::no_buffer_space; } -#if defined(ASIO_HAS_SECURE_RTL) +#if defined(ASIO_HAS_SNPRINTF) + snprintf(serv, servlen, "%u", ntohs(port)); +#elif defined(ASIO_HAS_SECURE_RTL) sprintf_s(serv, servlen, "%u", ntohs(port)); #else // defined(ASIO_HAS_SECURE_RTL) sprintf(serv, "%u", ntohs(port)); @@ -3645,7 +3714,9 @@ inline asio::error_code getnameinfo_emulation( { return ec = asio::error::no_buffer_space; } -#if defined(ASIO_HAS_SECURE_RTL) +#if defined(ASIO_HAS_SNPRINTF) + snprintf(serv, servlen, "%u", ntohs(port)); +#elif defined(ASIO_HAS_SECURE_RTL) sprintf_s(serv, servlen, "%u", ntohs(port)); #else // defined(ASIO_HAS_SECURE_RTL) sprintf(serv, "%u", ntohs(port)); @@ -3657,7 +3728,7 @@ inline asio::error_code getnameinfo_emulation( } } - ec.assign(0, ec.category()); + asio::error::clear(ec); return ec; } @@ -3807,7 +3878,7 @@ void freeaddrinfo(addrinfo_type* ai) #endif } -asio::error_code getnameinfo(const socket_addr_type* addr, +asio::error_code getnameinfo(const void* addr, std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int flags, asio::error_code& ec) { @@ -3815,8 +3886,8 @@ asio::error_code getnameinfo(const socket_addr_type* addr, # if defined(ASIO_HAS_GETADDRINFO) // Building for Windows XP, Windows Server 2003, or later. clear_last_error(); - int error = ::getnameinfo(addr, static_cast<socklen_t>(addrlen), - host, static_cast<DWORD>(hostlen), + int error = ::getnameinfo(static_cast<const socket_addr_type*>(addr), + static_cast<socklen_t>(addrlen), host, static_cast<DWORD>(hostlen), serv, static_cast<DWORD>(servlen), flags); return ec = translate_addrinfo_error(error); # else @@ -3828,34 +3899,34 @@ asio::error_code getnameinfo(const socket_addr_type* addr, if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo")) { clear_last_error(); - int error = gni(addr, static_cast<int>(addrlen), - host, static_cast<DWORD>(hostlen), + int error = gni(static_cast<const socket_addr_type*>(addr), + static_cast<int>(addrlen), host, static_cast<DWORD>(hostlen), serv, static_cast<DWORD>(servlen), flags); return ec = translate_addrinfo_error(error); } } clear_last_error(); - return getnameinfo_emulation(addr, addrlen, - host, hostlen, serv, servlen, flags, ec); + return getnameinfo_emulation(static_cast<const socket_addr_type*>(addr), + addrlen, host, hostlen, serv, servlen, flags, ec); # endif #elif !defined(ASIO_HAS_GETADDRINFO) using namespace std; // For memcpy. sockaddr_storage_type tmp_addr; memcpy(&tmp_addr, addr, addrlen); - addr = reinterpret_cast<socket_addr_type*>(&tmp_addr); + addr = &tmp_addr; clear_last_error(); - return getnameinfo_emulation(addr, addrlen, - host, hostlen, serv, servlen, flags, ec); + return getnameinfo_emulation(static_cast<const socket_addr_type*>(addr), + addrlen, host, hostlen, serv, servlen, flags, ec); #else clear_last_error(); - int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags); + int error = ::getnameinfo(static_cast<const socket_addr_type*>(addr), + addrlen, host, hostlen, serv, servlen, flags); return ec = translate_addrinfo_error(error); #endif } -asio::error_code sync_getnameinfo( - const socket_addr_type* addr, std::size_t addrlen, - char* host, std::size_t hostlen, char* serv, +asio::error_code sync_getnameinfo(const void* addr, + std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int sock_type, asio::error_code& ec) { // First try resolving with the service name. If that fails try resolving @@ -3874,7 +3945,7 @@ asio::error_code sync_getnameinfo( asio::error_code background_getnameinfo( const weak_cancel_token_type& cancel_token, - const socket_addr_type* addr, std::size_t addrlen, + const void* addr, std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int sock_type, asio::error_code& ec) { diff --git a/3rdparty/asio/include/asio/detail/impl/socket_select_interrupter.ipp b/3rdparty/asio/include/asio/detail/impl/socket_select_interrupter.ipp index 81813db0b7a..a5b29581eb0 100644 --- a/3rdparty/asio/include/asio/detail/impl/socket_select_interrupter.ipp +++ b/3rdparty/asio/include/asio/detail/impl/socket_select_interrupter.ipp @@ -2,7 +2,7 @@ // detail/impl/socket_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -60,11 +60,11 @@ void socket_select_interrupter::open_descriptors() addr.sin_family = AF_INET; addr.sin_addr.s_addr = socket_ops::host_to_network_long(INADDR_LOOPBACK); addr.sin_port = 0; - if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr, + if (socket_ops::bind(acceptor.get(), &addr, addr_len, ec) == socket_error_retval) asio::detail::throw_error(ec, "socket_select_interrupter"); - if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr, + if (socket_ops::getsockname(acceptor.get(), &addr, &addr_len, ec) == socket_error_retval) asio::detail::throw_error(ec, "socket_select_interrupter"); @@ -83,7 +83,7 @@ void socket_select_interrupter::open_descriptors() if (client.get() == invalid_socket) asio::detail::throw_error(ec, "socket_select_interrupter"); - if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr, + if (socket_ops::connect(client.get(), &addr, addr_len, ec) == socket_error_retval) asio::detail::throw_error(ec, "socket_select_interrupter"); diff --git a/3rdparty/asio/include/asio/detail/impl/strand_executor_service.hpp b/3rdparty/asio/include/asio/detail/impl/strand_executor_service.hpp index b66b6747f01..3ffb398dcf6 100644 --- a/3rdparty/asio/include/asio/detail/impl/strand_executor_service.hpp +++ b/3rdparty/asio/include/asio/detail/impl/strand_executor_service.hpp @@ -2,7 +2,7 @@ // detail/impl/strand_executor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,7 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/fenced_block.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/recycling_allocator.hpp" #include "asio/executor_work_guard.hpp" #include "asio/defer.hpp" @@ -34,8 +33,8 @@ class strand_executor_service::allocator_binder public: typedef Allocator allocator_type; - allocator_binder(ASIO_MOVE_ARG(F) f, const Allocator& a) - : f_(ASIO_MOVE_CAST(F)(f)), + allocator_binder(F&& f, const Allocator& a) + : f_(static_cast<F&&>(f)), allocator_(a) { } @@ -46,15 +45,13 @@ public: { } -#if defined(ASIO_HAS_MOVE) allocator_binder(allocator_binder&& other) - : f_(ASIO_MOVE_CAST(F)(other.f_)), - allocator_(ASIO_MOVE_CAST(allocator_type)(other.allocator_)) + : f_(static_cast<F&&>(other.f_)), + allocator_(static_cast<allocator_type&&>(other.allocator_)) { } -#endif // defined(ASIO_HAS_MOVE) - allocator_type get_allocator() const ASIO_NOEXCEPT + allocator_type get_allocator() const noexcept { return allocator_; } @@ -71,9 +68,9 @@ private: template <typename Executor> class strand_executor_service::invoker<Executor, - typename enable_if< + enable_if_t< execution::is_executor<Executor>::value - >::type> + >> { public: invoker(const implementation_type& impl, Executor& ex) @@ -88,13 +85,11 @@ public: { } -#if defined(ASIO_HAS_MOVE) invoker(invoker&& other) - : impl_(ASIO_MOVE_CAST(implementation_type)(other.impl_)), - executor_(ASIO_MOVE_CAST(executor_type)(other.executor_)) + : impl_(static_cast<implementation_type&&>(other.impl_)), + executor_(static_cast<executor_type&&>(other.executor_)) { } -#endif // defined(ASIO_HAS_MOVE) struct on_invoker_exit { @@ -106,13 +101,12 @@ public: { recycling_allocator<void> allocator; executor_type ex = this_->executor_; - execution::execute( - asio::prefer( - asio::require( - ASIO_MOVE_CAST(executor_type)(ex), - execution::blocking.never), - execution::allocator(allocator)), - ASIO_MOVE_CAST(invoker)(*this_)); + asio::prefer( + asio::require( + static_cast<executor_type&&>(ex), + execution::blocking.never), + execution::allocator(allocator) + ).execute(static_cast<invoker&&>(*this_)); } } }; @@ -127,12 +121,12 @@ public: } private: - typedef typename decay< - typename prefer_result< + typedef decay_t< + prefer_result_t< Executor, execution::outstanding_work_t::tracked_t - >::type - >::type executor_type; + > + > executor_type; implementation_type impl_; executor_type executor_; @@ -142,9 +136,9 @@ private: template <typename Executor> class strand_executor_service::invoker<Executor, - typename enable_if< + enable_if_t< !execution::is_executor<Executor>::value - >::type> + >> { public: invoker(const implementation_type& impl, Executor& ex) @@ -159,13 +153,11 @@ public: { } -#if defined(ASIO_HAS_MOVE) invoker(invoker&& other) - : impl_(ASIO_MOVE_CAST(implementation_type)(other.impl_)), - work_(ASIO_MOVE_CAST(executor_work_guard<Executor>)(other.work_)) + : impl_(static_cast<implementation_type&&>(other.impl_)), + work_(static_cast<executor_work_guard<Executor>&&>(other.work_)) { } -#endif // defined(ASIO_HAS_MOVE) struct on_invoker_exit { @@ -177,7 +169,7 @@ public: { Executor ex(this_->work_.get_executor()); recycling_allocator<void> allocator; - ex.post(ASIO_MOVE_CAST(invoker)(*this_), allocator); + ex.post(static_cast<invoker&&>(*this_), allocator); } } }; @@ -200,33 +192,33 @@ private: template <typename Executor, typename Function> inline void strand_executor_service::execute(const implementation_type& impl, - Executor& ex, ASIO_MOVE_ARG(Function) function, - typename enable_if< - can_query<Executor, execution::allocator_t<void> >::value - >::type*) + Executor& ex, Function&& function, + enable_if_t< + can_query<Executor, execution::allocator_t<void>>::value + >*) { return strand_executor_service::do_execute(impl, ex, - ASIO_MOVE_CAST(Function)(function), + static_cast<Function&&>(function), asio::query(ex, execution::allocator)); } template <typename Executor, typename Function> inline void strand_executor_service::execute(const implementation_type& impl, - Executor& ex, ASIO_MOVE_ARG(Function) function, - typename enable_if< - !can_query<Executor, execution::allocator_t<void> >::value - >::type*) + Executor& ex, Function&& function, + enable_if_t< + !can_query<Executor, execution::allocator_t<void>>::value + >*) { return strand_executor_service::do_execute(impl, ex, - ASIO_MOVE_CAST(Function)(function), + static_cast<Function&&>(function), std::allocator<void>()); } template <typename Executor, typename Function, typename Allocator> void strand_executor_service::do_execute(const implementation_type& impl, - Executor& ex, ASIO_MOVE_ARG(Function) function, const Allocator& a) + Executor& ex, Function&& function, const Allocator& a) { - typedef typename decay<Function>::type function_type; + typedef decay_t<Function> function_type; // If the executor is not never-blocking, and we are already in the strand, // then the function can run immediately. @@ -234,17 +226,17 @@ void strand_executor_service::do_execute(const implementation_type& impl, && running_in_this_thread(impl)) { // Make a local, non-const copy of the function. - function_type tmp(ASIO_MOVE_CAST(Function)(function)); + function_type tmp(static_cast<Function&&>(function)); fenced_block b(fenced_block::full); - asio_handler_invoke_helpers::invoke(tmp, tmp); + static_cast<function_type&&>(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(ASIO_MOVE_CAST(Function)(function), a); + p.p = new (p.v) op(static_cast<Function&&>(function), a); ASIO_HANDLER_CREATION((impl->service_->context(), *p.p, "strand_executor", impl.get(), 0, "execute")); @@ -254,31 +246,31 @@ void strand_executor_service::do_execute(const implementation_type& impl, p.v = p.p = 0; if (first) { - execution::execute(ex, invoker<Executor>(impl, ex)); + ex.execute(invoker<Executor>(impl, ex)); } } template <typename Executor, typename Function, typename Allocator> void strand_executor_service::dispatch(const implementation_type& impl, - Executor& ex, ASIO_MOVE_ARG(Function) function, const Allocator& a) + Executor& ex, Function&& function, const Allocator& a) { - typedef typename decay<Function>::type function_type; + typedef decay_t<Function> function_type; // If we are already in the strand then the function can run immediately. if (running_in_this_thread(impl)) { // Make a local, non-const copy of the function. - function_type tmp(ASIO_MOVE_CAST(Function)(function)); + function_type tmp(static_cast<Function&&>(function)); fenced_block b(fenced_block::full); - asio_handler_invoke_helpers::invoke(tmp, tmp); + static_cast<function_type&&>(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(ASIO_MOVE_CAST(Function)(function), a); + p.p = new (p.v) op(static_cast<Function&&>(function), a); ASIO_HANDLER_CREATION((impl->service_->context(), *p.p, "strand_executor", impl.get(), 0, "dispatch")); @@ -297,14 +289,14 @@ void strand_executor_service::dispatch(const implementation_type& impl, // 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, ASIO_MOVE_ARG(Function) function, const Allocator& a) + Executor& ex, Function&& function, const Allocator& a) { - typedef typename decay<Function>::type function_type; + typedef decay_t<Function> 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(ASIO_MOVE_CAST(Function)(function), a); + p.p = new (p.v) op(static_cast<Function&&>(function), a); ASIO_HANDLER_CREATION((impl->service_->context(), *p.p, "strand_executor", impl.get(), 0, "post")); @@ -323,14 +315,14 @@ void strand_executor_service::post(const implementation_type& impl, // 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, ASIO_MOVE_ARG(Function) function, const Allocator& a) + Executor& ex, Function&& function, const Allocator& a) { - typedef typename decay<Function>::type function_type; + typedef decay_t<Function> 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(ASIO_MOVE_CAST(Function)(function), a); + p.p = new (p.v) op(static_cast<Function&&>(function), a); ASIO_HANDLER_CREATION((impl->service_->context(), *p.p, "strand_executor", impl.get(), 0, "defer")); diff --git a/3rdparty/asio/include/asio/detail/impl/strand_executor_service.ipp b/3rdparty/asio/include/asio/detail/impl/strand_executor_service.ipp index c97b6df5a69..a2dff894cca 100644 --- a/3rdparty/asio/include/asio/detail/impl/strand_executor_service.ipp +++ b/3rdparty/asio/include/asio/detail/impl/strand_executor_service.ipp @@ -2,7 +2,7 @@ // detail/impl/strand_executor_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/strand_service.hpp b/3rdparty/asio/include/asio/detail/impl/strand_service.hpp index 3e395d6c9d6..8249c9eb8d5 100644 --- a/3rdparty/asio/include/asio/detail/impl/strand_service.hpp +++ b/3rdparty/asio/include/asio/detail/impl/strand_service.hpp @@ -2,7 +2,7 @@ // detail/impl/strand_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,7 +18,6 @@ #include "asio/detail/completion_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/push_options.hpp" @@ -40,7 +39,7 @@ void strand_service::dispatch(strand_service::implementation_type& impl, if (running_in_this_thread(impl)) { fenced_block b(fenced_block::full); - asio_handler_invoke_helpers::invoke(handler, handler); + static_cast<Handler&&>(handler)(); return; } diff --git a/3rdparty/asio/include/asio/detail/impl/strand_service.ipp b/3rdparty/asio/include/asio/detail/impl/strand_service.ipp index 58d657c9853..af8929a00c6 100644 --- a/3rdparty/asio/include/asio/detail/impl/strand_service.ipp +++ b/3rdparty/asio/include/asio/detail/impl/strand_service.ipp @@ -2,7 +2,7 @@ // detail/impl/strand_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/thread_context.ipp b/3rdparty/asio/include/asio/detail/impl/thread_context.ipp index 65cc275df24..8e729776362 100644 --- a/3rdparty/asio/include/asio/detail/impl/thread_context.ipp +++ b/3rdparty/asio/include/asio/detail/impl/thread_context.ipp @@ -2,7 +2,7 @@ // detail/impl/thread_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/throw_error.ipp b/3rdparty/asio/include/asio/detail/impl/throw_error.ipp index 9553add22e4..7baf3e729e5 100644 --- a/3rdparty/asio/include/asio/detail/impl/throw_error.ipp +++ b/3rdparty/asio/include/asio/detail/impl/throw_error.ipp @@ -2,7 +2,7 @@ // detail/impl/throw_error.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,7 +17,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/throw_error.hpp" -#include "asio/detail/throw_exception.hpp" #include "asio/system_error.hpp" #include "asio/detail/push_options.hpp" @@ -25,37 +24,21 @@ namespace asio { namespace detail { -void do_throw_error(const asio::error_code& err) +void do_throw_error( + const asio::error_code& err + ASIO_SOURCE_LOCATION_PARAM) { asio::system_error e(err); - asio::detail::throw_exception(e); + asio::detail::throw_exception(e ASIO_SOURCE_LOCATION_ARG); } -void do_throw_error(const asio::error_code& err, const char* location) +void do_throw_error( + const asio::error_code& err, + const char* location + ASIO_SOURCE_LOCATION_PARAM) { - // boostify: non-boost code starts here -#if defined(ASIO_MSVC) \ - && defined(ASIO_HAS_STD_SYSTEM_ERROR) \ - && (_MSC_VER < 1928) - // Microsoft's implementation of std::system_error is non-conformant in that - // it ignores the error code's message when a "what" string is supplied. We'll - // work around this by explicitly formatting the "what" string. - std::string what_msg = location; - what_msg += ": "; - what_msg += err.message(); - asio::system_error e(err, what_msg); - asio::detail::throw_exception(e); -#else // defined(ASIO_MSVC) - // && defined(ASIO_HAS_STD_SYSTEM_ERROR) - // && (_MSC_VER < 1928) - // boostify: non-boost code ends here asio::system_error e(err, location); - asio::detail::throw_exception(e); - // boostify: non-boost code starts here -#endif // defined(ASIO_MSVC) - // && defined(ASIO_HAS_STD_SYSTEM_ERROR) - // && (_MSC_VER < 1928) - // boostify: non-boost code ends here + asio::detail::throw_exception(e ASIO_SOURCE_LOCATION_ARG); } } // namespace detail diff --git a/3rdparty/asio/include/asio/detail/impl/timer_queue_ptime.ipp b/3rdparty/asio/include/asio/detail/impl/timer_queue_ptime.ipp index 8d39edbc1a6..bdf994e3a41 100644 --- a/3rdparty/asio/include/asio/detail/impl/timer_queue_ptime.ipp +++ b/3rdparty/asio/include/asio/detail/impl/timer_queue_ptime.ipp @@ -2,7 +2,7 @@ // detail/impl/timer_queue_ptime.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -26,62 +26,62 @@ namespace asio { namespace detail { -timer_queue<time_traits<boost::posix_time::ptime> >::timer_queue() +timer_queue<time_traits<boost::posix_time::ptime>>::timer_queue() { } -timer_queue<time_traits<boost::posix_time::ptime> >::~timer_queue() +timer_queue<time_traits<boost::posix_time::ptime>>::~timer_queue() { } -bool timer_queue<time_traits<boost::posix_time::ptime> >::enqueue_timer( +bool timer_queue<time_traits<boost::posix_time::ptime>>::enqueue_timer( const time_type& time, per_timer_data& timer, wait_op* op) { return impl_.enqueue_timer(time, timer, op); } -bool timer_queue<time_traits<boost::posix_time::ptime> >::empty() const +bool timer_queue<time_traits<boost::posix_time::ptime>>::empty() const { return impl_.empty(); } -long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_msec( +long timer_queue<time_traits<boost::posix_time::ptime>>::wait_duration_msec( long max_duration) const { return impl_.wait_duration_msec(max_duration); } -long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_usec( +long timer_queue<time_traits<boost::posix_time::ptime>>::wait_duration_usec( long max_duration) const { return impl_.wait_duration_usec(max_duration); } -void timer_queue<time_traits<boost::posix_time::ptime> >::get_ready_timers( +void timer_queue<time_traits<boost::posix_time::ptime>>::get_ready_timers( op_queue<operation>& ops) { impl_.get_ready_timers(ops); } -void timer_queue<time_traits<boost::posix_time::ptime> >::get_all_timers( +void timer_queue<time_traits<boost::posix_time::ptime>>::get_all_timers( op_queue<operation>& ops) { impl_.get_all_timers(ops); } -std::size_t timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer( +std::size_t timer_queue<time_traits<boost::posix_time::ptime>>::cancel_timer( per_timer_data& timer, op_queue<operation>& ops, std::size_t max_cancelled) { return impl_.cancel_timer(timer, ops, max_cancelled); } -void timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer_by_key( +void timer_queue<time_traits<boost::posix_time::ptime>>::cancel_timer_by_key( per_timer_data* timer, op_queue<operation>& ops, void* cancellation_key) { impl_.cancel_timer_by_key(timer, ops, cancellation_key); } -void timer_queue<time_traits<boost::posix_time::ptime> >::move_timer( +void timer_queue<time_traits<boost::posix_time::ptime>>::move_timer( per_timer_data& target, per_timer_data& source) { impl_.move_timer(target, source); diff --git a/3rdparty/asio/include/asio/detail/impl/timer_queue_set.ipp b/3rdparty/asio/include/asio/detail/impl/timer_queue_set.ipp index 04c62c3b5a7..66420e98a7c 100644 --- a/3rdparty/asio/include/asio/detail/impl/timer_queue_set.ipp +++ b/3rdparty/asio/include/asio/detail/impl/timer_queue_set.ipp @@ -2,7 +2,7 @@ // detail/impl/timer_queue_set.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/win_event.ipp b/3rdparty/asio/include/asio/detail/impl/win_event.ipp index d442c4d0ec7..9827e339769 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_event.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_event.ipp @@ -2,7 +2,7 @@ // detail/win_event.ipp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/win_iocp_file_service.ipp b/3rdparty/asio/include/asio/detail/impl/win_iocp_file_service.ipp new file mode 100644 index 00000000000..faaab48ad52 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/impl/win_iocp_file_service.ipp @@ -0,0 +1,280 @@ +// +// detail/impl/win_iocp_file_service.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP +#define ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_FILE) \ + && defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + +#include <cstring> +#include <sys/stat.h> +#include "asio/detail/win_iocp_file_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +win_iocp_file_service::win_iocp_file_service( + execution_context& context) + : execution_context_service_base<win_iocp_file_service>(context), + handle_service_(context), + nt_flush_buffers_file_ex_(0) +{ + if (FARPROC nt_flush_buffers_file_ex_ptr = ::GetProcAddress( + ::GetModuleHandleA("NTDLL"), "NtFlushBuffersFileEx")) + { + nt_flush_buffers_file_ex_ = reinterpret_cast<nt_flush_buffers_file_ex_fn>( + reinterpret_cast<void*>(nt_flush_buffers_file_ex_ptr)); + } +} + +void win_iocp_file_service::shutdown() +{ + handle_service_.shutdown(); +} + +asio::error_code win_iocp_file_service::open( + win_iocp_file_service::implementation_type& impl, + const char* path, file_base::flags open_flags, + asio::error_code& ec) +{ + if (is_open(impl)) + { + ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); + return ec; + } + + DWORD access = 0; + if ((open_flags & file_base::read_only) != 0) + access = GENERIC_READ; + else if ((open_flags & file_base::write_only) != 0) + access = GENERIC_WRITE; + else if ((open_flags & file_base::read_write) != 0) + access = GENERIC_READ | GENERIC_WRITE; + + DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE; + + DWORD disposition = 0; + if ((open_flags & file_base::create) != 0) + { + if ((open_flags & file_base::exclusive) != 0) + disposition = CREATE_NEW; + else + disposition = OPEN_ALWAYS; + } + else + { + if ((open_flags & file_base::truncate) != 0) + disposition = TRUNCATE_EXISTING; + else + disposition = OPEN_EXISTING; + } + + DWORD flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED; + if (impl.is_stream_) + flags |= FILE_FLAG_SEQUENTIAL_SCAN; + else + flags |= FILE_FLAG_RANDOM_ACCESS; + if ((open_flags & file_base::sync_all_on_write) != 0) + flags |= FILE_FLAG_WRITE_THROUGH; + + HANDLE handle = ::CreateFileA(path, access, share, 0, disposition, flags, 0); + if (handle != INVALID_HANDLE_VALUE) + { + if (disposition == OPEN_ALWAYS) + { + if ((open_flags & file_base::truncate) != 0) + { + if (!::SetEndOfFile(handle)) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(handle); + ec.assign(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); + return ec; + } + } + else if ((open_flags & file_base::append) != 0) + { + if (::SetFilePointer(handle, 0, 0, FILE_END) + == INVALID_SET_FILE_POINTER) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(handle); + ec.assign(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); + return ec; + } + } + } + + handle_service_.assign(impl, handle, ec); + if (ec) + ::CloseHandle(handle); + impl.offset_ = 0; + ASIO_ERROR_LOCATION(ec); + return ec; + } + else + { + DWORD last_error = ::GetLastError(); + ec.assign(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); + return ec; + } +} + +uint64_t win_iocp_file_service::size( + const win_iocp_file_service::implementation_type& impl, + asio::error_code& ec) const +{ + LARGE_INTEGER result; + if (::GetFileSizeEx(native_handle(impl), &result)) + { + asio::error::clear(ec); + return static_cast<uint64_t>(result.QuadPart); + } + else + { + DWORD last_error = ::GetLastError(); + ec.assign(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); + return 0; + } +} + +asio::error_code win_iocp_file_service::resize( + win_iocp_file_service::implementation_type& impl, + uint64_t n, asio::error_code& ec) +{ + LARGE_INTEGER distance; + distance.QuadPart = n; + if (::SetFilePointerEx(native_handle(impl), distance, 0, FILE_BEGIN)) + { + BOOL result = ::SetEndOfFile(native_handle(impl)); + DWORD last_error = ::GetLastError(); + + distance.QuadPart = static_cast<LONGLONG>(impl.offset_); + if (!::SetFilePointerEx(native_handle(impl), distance, 0, FILE_BEGIN)) + { + result = FALSE; + last_error = ::GetLastError(); + } + + if (result) + asio::error::clear(ec); + else + ec.assign(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); + return ec; + } + else + { + DWORD last_error = ::GetLastError(); + ec.assign(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); + return ec; + } +} + +asio::error_code win_iocp_file_service::sync_all( + win_iocp_file_service::implementation_type& impl, + asio::error_code& ec) +{ + BOOL result = ::FlushFileBuffers(native_handle(impl)); + if (result) + { + asio::error::clear(ec); + return ec; + } + else + { + DWORD last_error = ::GetLastError(); + ec.assign(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); + return ec; + } +} + +asio::error_code win_iocp_file_service::sync_data( + win_iocp_file_service::implementation_type& impl, + asio::error_code& ec) +{ + if (nt_flush_buffers_file_ex_) + { + io_status_block status = {}; + if (!nt_flush_buffers_file_ex_(native_handle(impl), + flush_flags_file_data_sync_only, 0, 0, &status)) + { + asio::error::clear(ec); + return ec; + } + } + return sync_all(impl, ec); +} + +uint64_t win_iocp_file_service::seek( + win_iocp_file_service::implementation_type& impl, int64_t offset, + file_base::seek_basis whence, asio::error_code& ec) +{ + DWORD method; + switch (whence) + { + case file_base::seek_set: + method = FILE_BEGIN; + break; + case file_base::seek_cur: + method = FILE_BEGIN; + offset = static_cast<int64_t>(impl.offset_) + offset; + break; + case file_base::seek_end: + method = FILE_END; + break; + default: + ec = asio::error::invalid_argument; + ASIO_ERROR_LOCATION(ec); + return 0; + } + + LARGE_INTEGER distance, new_offset; + distance.QuadPart = offset; + if (::SetFilePointerEx(native_handle(impl), distance, &new_offset, method)) + { + impl.offset_ = new_offset.QuadPart; + asio::error::clear(ec); + return impl.offset_; + } + else + { + DWORD last_error = ::GetLastError(); + ec.assign(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); + return 0; + } +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_FILE) + // && defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) + +#endif // ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP diff --git a/3rdparty/asio/include/asio/detail/impl/win_iocp_handle_service.ipp b/3rdparty/asio/include/asio/detail/impl/win_iocp_handle_service.ipp index 7cefc156337..6136e27fb32 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_iocp_handle_service.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_iocp_handle_service.ipp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_handle_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -68,6 +68,7 @@ public: win_iocp_handle_service::win_iocp_handle_service(execution_context& context) : execution_context_service_base<win_iocp_handle_service>(context), iocp_service_(asio::use_service<win_iocp_io_context>(context)), + nt_set_info_(0), mutex_(), impl_list_(0) { @@ -182,11 +183,15 @@ asio::error_code win_iocp_handle_service::assign( if (is_open(impl)) { ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); return ec; } if (iocp_service_.register_handle(handle, ec)) + { + ASIO_ERROR_LOCATION(ec); return ec; + } impl.handle_ = handle; ec = asio::error_code(); @@ -221,9 +226,47 @@ asio::error_code win_iocp_handle_service::close( ec = asio::error_code(); } + ASIO_ERROR_LOCATION(ec); return ec; } +win_iocp_handle_service::native_handle_type win_iocp_handle_service::release( + win_iocp_handle_service::implementation_type& impl, + asio::error_code& ec) +{ + if (!is_open(impl)) + return INVALID_HANDLE_VALUE; + + cancel(impl, ec); + if (ec) + { + ASIO_ERROR_LOCATION(ec); + return INVALID_HANDLE_VALUE; + } + + nt_set_info_fn fn = get_nt_set_info(); + if (fn == 0) + { + ec = asio::error::operation_not_supported; + ASIO_ERROR_LOCATION(ec); + return INVALID_HANDLE_VALUE; + } + + ULONG_PTR iosb[2] = { 0, 0 }; + void* info[2] = { 0, 0 }; + if (fn(impl.handle_, iosb, &info, sizeof(info), + 61 /* FileReplaceCompletionInformation */)) + { + ec = asio::error::operation_not_supported; + ASIO_ERROR_LOCATION(ec); + return INVALID_HANDLE_VALUE; + } + + native_handle_type tmp = impl.handle_; + impl.handle_ = INVALID_HANDLE_VALUE; + return tmp; +} + asio::error_code win_iocp_handle_service::cancel( win_iocp_handle_service::implementation_type& impl, asio::error_code& ec) @@ -231,6 +274,7 @@ asio::error_code win_iocp_handle_service::cancel( if (!is_open(impl)) { ec = asio::error::bad_descriptor; + ASIO_ERROR_LOCATION(ec); return ec; } @@ -292,6 +336,7 @@ asio::error_code win_iocp_handle_service::cancel( ec = asio::error::operation_not_supported; } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -302,6 +347,7 @@ size_t win_iocp_handle_service::do_write( if (!is_open(impl)) { ec = asio::error::bad_descriptor; + ASIO_ERROR_LOCATION(ec); return 0; } @@ -315,6 +361,7 @@ size_t win_iocp_handle_service::do_write( overlapped_wrapper overlapped(ec); if (ec) { + ASIO_ERROR_LOCATION(ec); return 0; } @@ -330,6 +377,7 @@ size_t win_iocp_handle_service::do_write( { ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return 0; } } @@ -343,6 +391,7 @@ size_t win_iocp_handle_service::do_write( DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return 0; } @@ -394,6 +443,7 @@ size_t win_iocp_handle_service::do_read( if (!is_open(impl)) { ec = asio::error::bad_descriptor; + ASIO_ERROR_LOCATION(ec); return 0; } @@ -407,6 +457,7 @@ size_t win_iocp_handle_service::do_read( overlapped_wrapper overlapped(ec); if (ec) { + ASIO_ERROR_LOCATION(ec); return 0; } @@ -429,6 +480,7 @@ size_t win_iocp_handle_service::do_read( ec = asio::error_code(last_error, asio::error::get_system_category()); } + ASIO_ERROR_LOCATION(ec); return 0; } } @@ -449,6 +501,7 @@ size_t win_iocp_handle_service::do_read( ec = asio::error_code(last_error, asio::error::get_system_category()); } + ASIO_ERROR_LOCATION(ec); return (last_error == ERROR_MORE_DATA) ? bytes_transferred : 0; } @@ -515,6 +568,47 @@ void win_iocp_handle_service::close_for_destruction(implementation_type& impl) } } +win_iocp_handle_service::nt_set_info_fn +win_iocp_handle_service::get_nt_set_info() +{ + void* ptr = interlocked_compare_exchange_pointer(&nt_set_info_, 0, 0); + if (!ptr) + { + if (HMODULE h = ::GetModuleHandleA("NTDLL.DLL")) + ptr = reinterpret_cast<void*>(GetProcAddress(h, "NtSetInformationFile")); + + // On failure, set nt_set_info_ to a special value to indicate that the + // NtSetInformationFile function is unavailable. That way we won't bother + // trying to look it up again. + interlocked_exchange_pointer(&nt_set_info_, ptr ? ptr : this); + } + + return reinterpret_cast<nt_set_info_fn>(ptr == this ? 0 : ptr); +} + +void* win_iocp_handle_service::interlocked_compare_exchange_pointer( + void** dest, void* exch, void* cmp) +{ +#if defined(_M_IX86) + return reinterpret_cast<void*>(InterlockedCompareExchange( + reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch), + reinterpret_cast<LONG>(cmp))); +#else + return InterlockedCompareExchangePointer(dest, exch, cmp); +#endif +} + +void* win_iocp_handle_service::interlocked_exchange_pointer( + void** dest, void* val) +{ +#if defined(_M_IX86) + return reinterpret_cast<void*>(InterlockedExchange( + reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val))); +#else + return InterlockedExchangePointer(dest, val); +#endif +} + } // namespace detail } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.hpp b/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.hpp index 224e3c2acd0..6479500184a 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.hpp +++ b/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.hpp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_io_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,7 +22,6 @@ #include "asio/detail/completion_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/push_options.hpp" diff --git a/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.ipp b/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.ipp index 37e32507288..1c7fb28b2d6 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_iocp_io_context.ipp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_io_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,7 +22,6 @@ #include "asio/error.hpp" #include "asio/detail/cstdint.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/limits.hpp" #include "asio/detail/thread.hpp" #include "asio/detail/throw_error.hpp" @@ -51,7 +50,7 @@ struct win_iocp_io_context::thread_function struct win_iocp_io_context::work_finished_on_block_exit { - ~work_finished_on_block_exit() + ~work_finished_on_block_exit() noexcept(false) { io_context_->work_finished(); } @@ -168,7 +167,10 @@ void win_iocp_io_context::shutdown() } if (timer_thread_.get()) + { timer_thread_->join(); + timer_thread_.reset(); + } } asio::error_code win_iocp_io_context::register_handle( @@ -527,6 +529,7 @@ size_t win_iocp_io_context::do_one(DWORD msec, DWORD win_iocp_io_context::get_gqcs_timeout() { +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) OSVERSIONINFOEX osvi; ZeroMemory(&osvi, sizeof(osvi)); osvi.dwOSVersionInfoSize = sizeof(osvi); @@ -539,6 +542,9 @@ DWORD win_iocp_io_context::get_gqcs_timeout() return INFINITE; return default_gqcs_timeout; +#else // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) + return INFINITE; +#endif // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) } void win_iocp_io_context::do_add_timer_queue(timer_queue_base& queue) diff --git a/3rdparty/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp b/3rdparty/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp index 8b47920e654..abeb3cecb0a 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_serial_port_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -46,6 +46,7 @@ asio::error_code win_iocp_serial_port_service::open( if (is_open(impl)) { ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); return ec; } @@ -61,6 +62,7 @@ asio::error_code win_iocp_serial_port_service::open( DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -75,6 +77,7 @@ asio::error_code win_iocp_serial_port_service::open( ::CloseHandle(handle); ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -101,6 +104,7 @@ asio::error_code win_iocp_serial_port_service::open( ::CloseHandle(handle); ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -119,6 +123,7 @@ asio::error_code win_iocp_serial_port_service::open( ::CloseHandle(handle); ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -143,6 +148,7 @@ asio::error_code win_iocp_serial_port_service::do_set_option( DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -154,6 +160,7 @@ asio::error_code win_iocp_serial_port_service::do_set_option( DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -176,6 +183,7 @@ asio::error_code win_iocp_serial_port_service::do_get_option( DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); return ec; } diff --git a/3rdparty/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp b/3rdparty/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp index 6adcf7e558b..af28718c905 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp @@ -2,7 +2,7 @@ // detail/impl/win_iocp_socket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -72,7 +72,7 @@ void win_iocp_socket_service_base::construct( void win_iocp_socket_service_base::base_move_construct( win_iocp_socket_service_base::base_implementation_type& impl, win_iocp_socket_service_base::base_implementation_type& other_impl) - ASIO_NOEXCEPT + noexcept { impl.socket_ = other_impl.socket_; other_impl.socket_ = invalid_socket; @@ -410,9 +410,8 @@ void win_iocp_socket_service_base::start_send_op( void win_iocp_socket_service_base::start_send_to_op( win_iocp_socket_service_base::base_implementation_type& impl, - WSABUF* buffers, std::size_t buffer_count, - const socket_addr_type* addr, int addrlen, - socket_base::message_flags flags, operation* op) + WSABUF* buffers, std::size_t buffer_count, const void* addr, + int addrlen, socket_base::message_flags flags, operation* op) { update_cancellation_thread_id(impl); iocp_service_.work_started(); @@ -423,8 +422,8 @@ void win_iocp_socket_service_base::start_send_to_op( { DWORD bytes_transferred = 0; int result = ::WSASendTo(impl.socket_, buffers, - static_cast<DWORD>(buffer_count), - &bytes_transferred, flags, addr, addrlen, op, 0); + static_cast<DWORD>(buffer_count), &bytes_transferred, flags, + static_cast<const socket_addr_type*>(addr), addrlen, op, 0); DWORD last_error = ::WSAGetLastError(); if (last_error == ERROR_PORT_UNREACHABLE) last_error = WSAECONNREFUSED; @@ -489,7 +488,7 @@ int win_iocp_socket_service_base::start_null_buffers_receive_op( void win_iocp_socket_service_base::start_receive_from_op( win_iocp_socket_service_base::base_implementation_type& impl, - WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr, + WSABUF* buffers, std::size_t buffer_count, void* addr, socket_base::message_flags flags, int* addrlen, operation* op) { update_cancellation_thread_id(impl); @@ -502,8 +501,8 @@ void win_iocp_socket_service_base::start_receive_from_op( DWORD bytes_transferred = 0; DWORD recv_flags = flags; int result = ::WSARecvFrom(impl.socket_, buffers, - static_cast<DWORD>(buffer_count), - &bytes_transferred, &recv_flags, addr, addrlen, op, 0); + static_cast<DWORD>(buffer_count), &bytes_transferred, &recv_flags, + static_cast<socket_addr_type*>(addr), addrlen, op, 0); DWORD last_error = ::WSAGetLastError(); if (last_error == ERROR_PORT_UNREACHABLE) last_error = WSAECONNREFUSED; @@ -608,7 +607,7 @@ void win_iocp_socket_service_base::start_reactor_op( int win_iocp_socket_service_base::start_connect_op( win_iocp_socket_service_base::base_implementation_type& impl, - int family, int type, const socket_addr_type* addr, std::size_t addrlen, + int family, int type, const void* addr, std::size_t addrlen, win_iocp_socket_connect_op_base* op, operation* iocp_op) { // If ConnectEx is available, use that. @@ -642,7 +641,8 @@ int win_iocp_socket_service_base::start_connect_op( iocp_service_.work_started(); BOOL result = connect_ex(impl.socket_, - addr, static_cast<int>(addrlen), 0, 0, 0, iocp_op); + static_cast<const socket_addr_type*>(addr), + static_cast<int>(addrlen), 0, 0, 0, iocp_op); DWORD last_error = ::WSAGetLastError(); if (!result && last_error != WSA_IO_PENDING) iocp_service_.on_completion(iocp_op, last_error); diff --git a/3rdparty/asio/include/asio/detail/impl/win_mutex.ipp b/3rdparty/asio/include/asio/detail/impl/win_mutex.ipp index 8a2db6f38c1..6340b6e1256 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_mutex.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_mutex.ipp @@ -2,7 +2,7 @@ // detail/impl/win_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/win_object_handle_service.ipp b/3rdparty/asio/include/asio/detail/impl/win_object_handle_service.ipp index 0c44a41236b..d7db3e3f3a1 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_object_handle_service.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_object_handle_service.ipp @@ -2,7 +2,7 @@ // detail/impl/win_object_handle_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -213,6 +213,7 @@ asio::error_code win_object_handle_service::assign( if (is_open(impl)) { ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); return ec; } @@ -270,6 +271,7 @@ asio::error_code win_object_handle_service::close( ec = asio::error_code(); } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -312,6 +314,7 @@ asio::error_code win_object_handle_service::cancel( ec = asio::error::bad_descriptor; } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -326,6 +329,7 @@ void win_object_handle_service::wait( DWORD last_error = ::GetLastError(); ec = asio::error_code(last_error, asio::error::get_system_category()); + ASIO_ERROR_LOCATION(ec); break; } case WAIT_OBJECT_0: diff --git a/3rdparty/asio/include/asio/detail/impl/win_static_mutex.ipp b/3rdparty/asio/include/asio/detail/impl/win_static_mutex.ipp index 070eb5951b5..5b459843338 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_static_mutex.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_static_mutex.ipp @@ -2,7 +2,7 @@ // detail/impl/win_static_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/win_thread.ipp b/3rdparty/asio/include/asio/detail/impl/win_thread.ipp index 142ba67fc56..0ebc5db86b4 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_thread.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_thread.ipp @@ -2,7 +2,7 @@ // detail/impl/win_thread.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/win_tss_ptr.ipp b/3rdparty/asio/include/asio/detail/impl/win_tss_ptr.ipp index c6ece2e20bf..5bc9de2c308 100644 --- a/3rdparty/asio/include/asio/detail/impl/win_tss_ptr.ipp +++ b/3rdparty/asio/include/asio/detail/impl/win_tss_ptr.ipp @@ -2,7 +2,7 @@ // detail/impl/win_tss_ptr.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp b/3rdparty/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp index 92a29f06460..90a03542a9c 100644 --- a/3rdparty/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp +++ b/3rdparty/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp @@ -2,7 +2,7 @@ // detail/impl/winrt_ssocket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -66,7 +66,7 @@ void winrt_ssocket_service_base::construct( void winrt_ssocket_service_base::base_move_construct( winrt_ssocket_service_base::base_implementation_type& impl, winrt_ssocket_service_base::base_implementation_type& other_impl) - ASIO_NOEXCEPT + noexcept { impl.socket_ = other_impl.socket_; other_impl.socket_ = nullptr; @@ -182,7 +182,7 @@ std::size_t winrt_ssocket_service_base::do_get_endpoint( : impl.socket_->Information->RemotePort); unsigned long scope = 0; - switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family) + switch (static_cast<const socket_addr_type*>(addr)->sa_family) { case ASIO_OS_DEF(AF_INET): if (addr_len < sizeof(sockaddr_in4_type)) @@ -351,7 +351,7 @@ asio::error_code winrt_ssocket_service_base::do_connect( char addr_string[max_addr_v6_str_len]; unsigned short port; - switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family) + switch (static_cast<const socket_addr_type*>(addr)->sa_family) { case ASIO_OS_DEF(AF_INET): socket_ops::inet_ntop(ASIO_OS_DEF(AF_INET), @@ -401,7 +401,7 @@ void winrt_ssocket_service_base::start_connect_op( char addr_string[max_addr_v6_str_len]; unsigned short port = 0; - switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family) + switch (static_cast<const socket_addr_type*>(addr)->sa_family) { case ASIO_OS_DEF(AF_INET): socket_ops::inet_ntop(ASIO_OS_DEF(AF_INET), diff --git a/3rdparty/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp b/3rdparty/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp index 7c7da52bb15..9c967508e4f 100644 --- a/3rdparty/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp +++ b/3rdparty/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp @@ -2,7 +2,7 @@ // detail/impl/winrt_timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp b/3rdparty/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp index d3d6103a644..028b5f9f3cb 100644 --- a/3rdparty/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp +++ b/3rdparty/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp @@ -2,7 +2,7 @@ // detail/impl/winrt_timer_scheduler.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/impl/winsock_init.ipp b/3rdparty/asio/include/asio/detail/impl/winsock_init.ipp index f2e8cb51a3f..5b5f56037ea 100644 --- a/3rdparty/asio/include/asio/detail/impl/winsock_init.ipp +++ b/3rdparty/asio/include/asio/detail/impl/winsock_init.ipp @@ -2,7 +2,7 @@ // detail/impl/winsock_init.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/initiate_defer.hpp b/3rdparty/asio/include/asio/detail/initiate_defer.hpp new file mode 100644 index 00000000000..92abb0aa2f0 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/initiate_defer.hpp @@ -0,0 +1,207 @@ +// +// detail/initiate_defer.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_INITIATE_DEFER_HPP +#define ASIO_DETAIL_INITIATE_DEFER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/associated_allocator.hpp" +#include "asio/associated_executor.hpp" +#include "asio/detail/work_dispatcher.hpp" +#include "asio/execution/allocator.hpp" +#include "asio/execution/blocking.hpp" +#include "asio/execution/relationship.hpp" +#include "asio/prefer.hpp" +#include "asio/require.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class initiate_defer +{ +public: + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + execution::is_executor< + associated_executor_t<decay_t<CompletionHandler>> + >::value + >* = 0) const + { + associated_executor_t<decay_t<CompletionHandler>> ex( + (get_associated_executor)(handler)); + + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + asio::prefer( + asio::require(ex, execution::blocking.never), + execution::relationship.continuation, + execution::allocator(alloc) + ).execute( + asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler))); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + !execution::is_executor< + associated_executor_t<decay_t<CompletionHandler>> + >::value + >* = 0) const + { + associated_executor_t<decay_t<CompletionHandler>> ex( + (get_associated_executor)(handler)); + + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + ex.defer(asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler)), alloc); + } +}; + +template <typename Executor> +class initiate_defer_with_executor +{ +public: + typedef Executor executor_type; + + explicit initiate_defer_with_executor(const Executor& ex) + : ex_(ex) + { + } + + executor_type get_executor() const noexcept + { + return ex_; + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + !detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + asio::prefer( + asio::require(ex_, execution::blocking.never), + execution::relationship.continuation, + execution::allocator(alloc) + ).execute( + asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler))); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + typedef decay_t<CompletionHandler> handler_t; + + typedef associated_executor_t<handler_t, Executor> handler_ex_t; + handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); + + associated_allocator_t<handler_t> alloc( + (get_associated_allocator)(handler)); + + asio::prefer( + asio::require(ex_, execution::blocking.never), + execution::relationship.continuation, + execution::allocator(alloc) + ).execute( + detail::work_dispatcher<handler_t, handler_ex_t>( + static_cast<CompletionHandler&&>(handler), handler_ex)); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + !execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + !detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + ex_.defer(asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler)), alloc); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + !execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + typedef decay_t<CompletionHandler> handler_t; + + typedef associated_executor_t<handler_t, Executor> handler_ex_t; + handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); + + associated_allocator_t<handler_t> alloc( + (get_associated_allocator)(handler)); + + ex_.defer(detail::work_dispatcher<handler_t, handler_ex_t>( + static_cast<CompletionHandler&&>(handler), handler_ex), alloc); + } + +private: + Executor ex_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_INITIATE_DEFER_HPP diff --git a/3rdparty/asio/include/asio/detail/initiate_dispatch.hpp b/3rdparty/asio/include/asio/detail/initiate_dispatch.hpp new file mode 100644 index 00000000000..ba2f68f0579 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/initiate_dispatch.hpp @@ -0,0 +1,193 @@ +// +// detail/initiate_dispatch.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_INITIATE_DISPATCH_HPP +#define ASIO_DETAIL_INITIATE_DISPATCH_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/associated_allocator.hpp" +#include "asio/associated_executor.hpp" +#include "asio/detail/work_dispatcher.hpp" +#include "asio/execution/allocator.hpp" +#include "asio/execution/blocking.hpp" +#include "asio/prefer.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class initiate_dispatch +{ +public: + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + execution::is_executor< + associated_executor_t<decay_t<CompletionHandler>> + >::value + >* = 0) const + { + associated_executor_t<decay_t<CompletionHandler>> ex( + (get_associated_executor)(handler)); + + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + asio::prefer(ex, execution::allocator(alloc)).execute( + asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler))); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + !execution::is_executor< + associated_executor_t<decay_t<CompletionHandler>> + >::value + >* = 0) const + { + associated_executor_t<decay_t<CompletionHandler>> ex( + (get_associated_executor)(handler)); + + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + ex.dispatch(asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler)), alloc); + } +}; + +template <typename Executor> +class initiate_dispatch_with_executor +{ +public: + typedef Executor executor_type; + + explicit initiate_dispatch_with_executor(const Executor& ex) + : ex_(ex) + { + } + + executor_type get_executor() const noexcept + { + return ex_; + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + !detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + asio::prefer(ex_, execution::allocator(alloc)).execute( + asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler))); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + typedef decay_t<CompletionHandler> handler_t; + + typedef associated_executor_t<handler_t, Executor> handler_ex_t; + handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); + + associated_allocator_t<handler_t> alloc( + (get_associated_allocator)(handler)); + + asio::prefer(ex_, execution::allocator(alloc)).execute( + detail::work_dispatcher<handler_t, handler_ex_t>( + static_cast<CompletionHandler&&>(handler), handler_ex)); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + !execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + !detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + ex_.dispatch(asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler)), alloc); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + !execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + typedef decay_t<CompletionHandler> handler_t; + + typedef associated_executor_t<handler_t, Executor> handler_ex_t; + handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); + + associated_allocator_t<handler_t> alloc( + (get_associated_allocator)(handler)); + + ex_.dispatch(detail::work_dispatcher<handler_t, handler_ex_t>( + static_cast<CompletionHandler&&>(handler), handler_ex), alloc); + } + +private: + Executor ex_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_INITIATE_DISPATCH_HPP diff --git a/3rdparty/asio/include/asio/detail/initiate_post.hpp b/3rdparty/asio/include/asio/detail/initiate_post.hpp new file mode 100644 index 00000000000..f73c8ee0b81 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/initiate_post.hpp @@ -0,0 +1,207 @@ +// +// detail/initiate_post.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_INITIATE_POST_HPP +#define ASIO_DETAIL_INITIATE_POST_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/associated_allocator.hpp" +#include "asio/associated_executor.hpp" +#include "asio/detail/work_dispatcher.hpp" +#include "asio/execution/allocator.hpp" +#include "asio/execution/blocking.hpp" +#include "asio/execution/relationship.hpp" +#include "asio/prefer.hpp" +#include "asio/require.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class initiate_post +{ +public: + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + execution::is_executor< + associated_executor_t<decay_t<CompletionHandler>> + >::value + >* = 0) const + { + associated_executor_t<decay_t<CompletionHandler>> ex( + (get_associated_executor)(handler)); + + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + asio::prefer( + asio::require(ex, execution::blocking.never), + execution::relationship.fork, + execution::allocator(alloc) + ).execute( + asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler))); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + !execution::is_executor< + associated_executor_t<decay_t<CompletionHandler>> + >::value + >* = 0) const + { + associated_executor_t<decay_t<CompletionHandler>> ex( + (get_associated_executor)(handler)); + + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + ex.post(asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler)), alloc); + } +}; + +template <typename Executor> +class initiate_post_with_executor +{ +public: + typedef Executor executor_type; + + explicit initiate_post_with_executor(const Executor& ex) + : ex_(ex) + { + } + + executor_type get_executor() const noexcept + { + return ex_; + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + !detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + asio::prefer( + asio::require(ex_, execution::blocking.never), + execution::relationship.fork, + execution::allocator(alloc) + ).execute( + asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler))); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + typedef decay_t<CompletionHandler> handler_t; + + typedef associated_executor_t<handler_t, Executor> handler_ex_t; + handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); + + associated_allocator_t<handler_t> alloc( + (get_associated_allocator)(handler)); + + asio::prefer( + asio::require(ex_, execution::blocking.never), + execution::relationship.fork, + execution::allocator(alloc) + ).execute( + detail::work_dispatcher<handler_t, handler_ex_t>( + static_cast<CompletionHandler&&>(handler), handler_ex)); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + !execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + !detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + associated_allocator_t<decay_t<CompletionHandler>> alloc( + (get_associated_allocator)(handler)); + + ex_.post(asio::detail::bind_handler( + static_cast<CompletionHandler&&>(handler)), alloc); + } + + template <typename CompletionHandler> + void operator()(CompletionHandler&& handler, + enable_if_t< + !execution::is_executor< + conditional_t<true, executor_type, CompletionHandler> + >::value + >* = 0, + enable_if_t< + detail::is_work_dispatcher_required< + decay_t<CompletionHandler>, + Executor + >::value + >* = 0) const + { + typedef decay_t<CompletionHandler> handler_t; + + typedef associated_executor_t<handler_t, Executor> handler_ex_t; + handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); + + associated_allocator_t<handler_t> alloc( + (get_associated_allocator)(handler)); + + ex_.post(detail::work_dispatcher<handler_t, handler_ex_t>( + static_cast<CompletionHandler&&>(handler), handler_ex), alloc); + } + +private: + Executor ex_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_INITIATE_POST_HPP diff --git a/3rdparty/asio/include/asio/detail/io_control.hpp b/3rdparty/asio/include/asio/detail/io_control.hpp index 2b6d593891f..14daf85730a 100644 --- a/3rdparty/asio/include/asio/detail/io_control.hpp +++ b/3rdparty/asio/include/asio/detail/io_control.hpp @@ -2,7 +2,7 @@ // detail/io_control.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/io_object_impl.hpp b/3rdparty/asio/include/asio/detail/io_object_impl.hpp index 9efd0d62047..bd7312b8491 100644 --- a/3rdparty/asio/include/asio/detail/io_object_impl.hpp +++ b/3rdparty/asio/include/asio/detail/io_object_impl.hpp @@ -1,8 +1,8 @@ // -// io_object_impl.hpp -// ~~~~~~~~~~~~~~~~~~ +// detail/io_object_impl.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -60,7 +60,6 @@ public: service_->construct(implementation_); } -#if defined(ASIO_HAS_MOVE) // Move-construct an I/O object. io_object_impl(io_object_impl&& other) : service_(&other.get_service()), @@ -69,7 +68,16 @@ public: service_->move_construct(implementation_, other.implementation_); } - // Perform a converting move-construction of an I/O object. + // Perform converting move-construction of an I/O object on the same service. + template <typename Executor1> + io_object_impl(io_object_impl<IoObjectService, Executor1>&& other) + : service_(&other.get_service()), + executor_(other.get_executor()) + { + service_->move_construct(implementation_, other.get_implementation()); + } + + // Perform converting move-construction of an I/O object on another service. template <typename IoObjectService1, typename Executor1> io_object_impl(io_object_impl<IoObjectService1, Executor1>&& other) : service_(&asio::use_service<IoObjectService>( @@ -79,7 +87,6 @@ public: service_->converting_move_construct(implementation_, other.get_service(), other.get_implementation()); } -#endif // defined(ASIO_HAS_MOVE) // Destructor. ~io_object_impl() @@ -87,7 +94,6 @@ public: service_->destroy(implementation_); } -#if defined(ASIO_HAS_MOVE) // Move-assign an I/O object. io_object_impl& operator=(io_object_impl&& other) { @@ -101,10 +107,9 @@ public: } return *this; } -#endif // defined(ASIO_HAS_MOVE) // Get the executor associated with the object. - const executor_type& get_executor() ASIO_NOEXCEPT + const executor_type& get_executor() noexcept { return executor_; } @@ -137,7 +142,7 @@ private: // Helper function to get an executor's context. template <typename T> static execution_context& get_context(const T& t, - typename enable_if<execution::is_executor<T>::value>::type* = 0) + enable_if_t<execution::is_executor<T>::value>* = 0) { return asio::query(t, execution::context); } @@ -145,7 +150,7 @@ private: // Helper function to get an executor's context. template <typename T> static execution_context& get_context(const T& t, - typename enable_if<!execution::is_executor<T>::value>::type* = 0) + enable_if_t<!execution::is_executor<T>::value>* = 0) { return t.context(); } diff --git a/3rdparty/asio/include/asio/detail/io_uring_descriptor_read_at_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_descriptor_read_at_op.hpp new file mode 100644 index 00000000000..114bdb54297 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_descriptor_read_at_op.hpp @@ -0,0 +1,195 @@ +// +// detail/io_uring_descriptor_read_at_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_AT_OP_HPP +#define ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_AT_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/cstdint.hpp" +#include "asio/detail/descriptor_ops.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename MutableBufferSequence> +class io_uring_descriptor_read_at_op_base : public io_uring_operation +{ +public: + io_uring_descriptor_read_at_op_base( + const asio::error_code& success_ec, int descriptor, + descriptor_ops::state_type state, uint64_t offset, + const MutableBufferSequence& buffers, func_type complete_func) + : io_uring_operation(success_ec, + &io_uring_descriptor_read_at_op_base::do_prepare, + &io_uring_descriptor_read_at_op_base::do_perform, complete_func), + descriptor_(descriptor), + state_(state), + offset_(offset), + buffers_(buffers), + bufs_(buffers) + { + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_descriptor_read_at_op_base* o( + static_cast<io_uring_descriptor_read_at_op_base*>(base)); + + if ((o->state_ & descriptor_ops::internal_non_blocking) != 0) + { + ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLIN); + } + else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer) + { + ::io_uring_prep_read_fixed(sqe, o->descriptor_, + o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len, + o->offset_, o->bufs_.registered_id().native_handle()); + } + else + { + ::io_uring_prep_readv(sqe, o->descriptor_, + o->bufs_.buffers(), o->bufs_.count(), o->offset_); + } + } + + static bool do_perform(io_uring_operation* base, bool after_completion) + { + ASIO_ASSUME(base != 0); + io_uring_descriptor_read_at_op_base* o( + static_cast<io_uring_descriptor_read_at_op_base*>(base)); + + if ((o->state_ & descriptor_ops::internal_non_blocking) != 0) + { + if (o->bufs_.is_single_buffer) + { + return descriptor_ops::non_blocking_read_at1(o->descriptor_, + o->offset_, o->bufs_.first(o->buffers_).data(), + o->bufs_.first(o->buffers_).size(), o->ec_, + o->bytes_transferred_); + } + else + { + return descriptor_ops::non_blocking_read_at(o->descriptor_, + o->offset_, o->bufs_.buffers(), o->bufs_.count(), + o->ec_, o->bytes_transferred_); + } + } + else if (after_completion) + { + if (!o->ec_ && o->bytes_transferred_ == 0) + o->ec_ = asio::error::eof; + } + + if (o->ec_ && o->ec_ == asio::error::would_block) + { + o->state_ |= descriptor_ops::internal_non_blocking; + return false; + } + + return after_completion; + } + +private: + int descriptor_; + descriptor_ops::state_type state_; + uint64_t offset_; + MutableBufferSequence buffers_; + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs_; +}; + +template <typename MutableBufferSequence, typename Handler, typename IoExecutor> +class io_uring_descriptor_read_at_op + : public io_uring_descriptor_read_at_op_base<MutableBufferSequence> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_read_at_op); + + io_uring_descriptor_read_at_op(const asio::error_code& success_ec, + int descriptor, descriptor_ops::state_type state, uint64_t offset, + const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + : io_uring_descriptor_read_at_op_base<MutableBufferSequence>( + success_ec, descriptor, state, offset, buffers, + &io_uring_descriptor_read_at_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_descriptor_read_at_op* o + (static_cast<io_uring_descriptor_read_at_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_AT_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_descriptor_read_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_descriptor_read_op.hpp new file mode 100644 index 00000000000..9f8cf70bca3 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_descriptor_read_op.hpp @@ -0,0 +1,190 @@ +// +// detail/io_uring_descriptor_read_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_OP_HPP +#define ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/descriptor_ops.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename MutableBufferSequence> +class io_uring_descriptor_read_op_base : public io_uring_operation +{ +public: + io_uring_descriptor_read_op_base(const asio::error_code& success_ec, + int descriptor, descriptor_ops::state_type state, + const MutableBufferSequence& buffers, func_type complete_func) + : io_uring_operation(success_ec, + &io_uring_descriptor_read_op_base::do_prepare, + &io_uring_descriptor_read_op_base::do_perform, complete_func), + descriptor_(descriptor), + state_(state), + buffers_(buffers), + bufs_(buffers) + { + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_descriptor_read_op_base* o( + static_cast<io_uring_descriptor_read_op_base*>(base)); + + if ((o->state_ & descriptor_ops::internal_non_blocking) != 0) + { + ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLIN); + } + else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer) + { + ::io_uring_prep_read_fixed(sqe, o->descriptor_, + o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len, + 0, o->bufs_.registered_id().native_handle()); + } + else + { + ::io_uring_prep_readv(sqe, o->descriptor_, + o->bufs_.buffers(), o->bufs_.count(), -1); + } + } + + static bool do_perform(io_uring_operation* base, bool after_completion) + { + ASIO_ASSUME(base != 0); + io_uring_descriptor_read_op_base* o( + static_cast<io_uring_descriptor_read_op_base*>(base)); + + if ((o->state_ & descriptor_ops::internal_non_blocking) != 0) + { + if (o->bufs_.is_single_buffer) + { + return descriptor_ops::non_blocking_read1( + o->descriptor_, o->bufs_.first(o->buffers_).data(), + o->bufs_.first(o->buffers_).size(), o->ec_, + o->bytes_transferred_); + } + else + { + return descriptor_ops::non_blocking_read( + o->descriptor_, o->bufs_.buffers(), o->bufs_.count(), + o->ec_, o->bytes_transferred_); + } + } + else if (after_completion) + { + if (!o->ec_ && o->bytes_transferred_ == 0) + o->ec_ = asio::error::eof; + } + + if (o->ec_ && o->ec_ == asio::error::would_block) + { + o->state_ |= descriptor_ops::internal_non_blocking; + return false; + } + + return after_completion; + } + +private: + int descriptor_; + descriptor_ops::state_type state_; + MutableBufferSequence buffers_; + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs_; +}; + +template <typename MutableBufferSequence, typename Handler, typename IoExecutor> +class io_uring_descriptor_read_op + : public io_uring_descriptor_read_op_base<MutableBufferSequence> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_read_op); + + io_uring_descriptor_read_op(const asio::error_code& success_ec, + int descriptor, descriptor_ops::state_type state, + const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + : io_uring_descriptor_read_op_base<MutableBufferSequence>(success_ec, + descriptor, state, buffers, &io_uring_descriptor_read_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_descriptor_read_op* o + (static_cast<io_uring_descriptor_read_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_descriptor_service.hpp b/3rdparty/asio/include/asio/detail/io_uring_descriptor_service.hpp new file mode 100644 index 00000000000..04d1e36edd8 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_descriptor_service.hpp @@ -0,0 +1,687 @@ +// +// detail/io_uring_descriptor_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_DESCRIPTOR_SERVICE_HPP +#define ASIO_DETAIL_IO_URING_DESCRIPTOR_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/associated_cancellation_slot.hpp" +#include "asio/buffer.hpp" +#include "asio/cancellation_type.hpp" +#include "asio/execution_context.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/descriptor_ops.hpp" +#include "asio/detail/io_uring_descriptor_read_at_op.hpp" +#include "asio/detail/io_uring_descriptor_read_op.hpp" +#include "asio/detail/io_uring_descriptor_write_at_op.hpp" +#include "asio/detail/io_uring_descriptor_write_op.hpp" +#include "asio/detail/io_uring_null_buffers_op.hpp" +#include "asio/detail/io_uring_service.hpp" +#include "asio/detail/io_uring_wait_op.hpp" +#include "asio/detail/memory.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/posix/descriptor_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class io_uring_descriptor_service : + public execution_context_service_base<io_uring_descriptor_service> +{ +public: + // The native type of a descriptor. + typedef int native_handle_type; + + // The implementation type of the descriptor. + class implementation_type + : private asio::detail::noncopyable + { + public: + // Default constructor. + implementation_type() + : descriptor_(-1), + state_(0) + { + } + + private: + // Only this service will have access to the internal values. + friend class io_uring_descriptor_service; + + // The native descriptor representation. + int descriptor_; + + // The current state of the descriptor. + descriptor_ops::state_type state_; + + // Per I/O object data used by the io_uring_service. + io_uring_service::per_io_object_data io_object_data_; + }; + + // Constructor. + ASIO_DECL io_uring_descriptor_service(execution_context& context); + + // Destroy all user-defined handler objects owned by the service. + ASIO_DECL void shutdown(); + + // Construct a new descriptor implementation. + ASIO_DECL void construct(implementation_type& impl); + + // Move-construct a new descriptor implementation. + ASIO_DECL void move_construct(implementation_type& impl, + implementation_type& other_impl) noexcept; + + // Move-assign from another descriptor implementation. + ASIO_DECL void move_assign(implementation_type& impl, + io_uring_descriptor_service& other_service, + implementation_type& other_impl); + + // Destroy a descriptor implementation. + ASIO_DECL void destroy(implementation_type& impl); + + // Assign a native descriptor to a descriptor implementation. + ASIO_DECL asio::error_code assign(implementation_type& impl, + const native_handle_type& native_descriptor, + asio::error_code& ec); + + // Determine whether the descriptor is open. + bool is_open(const implementation_type& impl) const + { + return impl.descriptor_ != -1; + } + + // Destroy a descriptor implementation. + ASIO_DECL asio::error_code close(implementation_type& impl, + asio::error_code& ec); + + // Get the native descriptor representation. + native_handle_type native_handle(const implementation_type& impl) const + { + return impl.descriptor_; + } + + // Release ownership of the native descriptor representation. + ASIO_DECL native_handle_type release(implementation_type& impl); + + // Release ownership of the native descriptor representation. + native_handle_type release(implementation_type& impl, + asio::error_code& ec) + { + ec = success_ec_; + return release(impl); + } + + // Cancel all operations associated with the descriptor. + ASIO_DECL asio::error_code cancel(implementation_type& impl, + asio::error_code& ec); + + // Perform an IO control command on the descriptor. + template <typename IO_Control_Command> + asio::error_code io_control(implementation_type& impl, + IO_Control_Command& command, asio::error_code& ec) + { + descriptor_ops::ioctl(impl.descriptor_, impl.state_, + command.name(), static_cast<ioctl_arg_type*>(command.data()), ec); + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // Gets the non-blocking mode of the descriptor. + bool non_blocking(const implementation_type& impl) const + { + return (impl.state_ & descriptor_ops::user_set_non_blocking) != 0; + } + + // Sets the non-blocking mode of the descriptor. + asio::error_code non_blocking(implementation_type& impl, + bool mode, asio::error_code& ec) + { + descriptor_ops::set_user_non_blocking( + impl.descriptor_, impl.state_, mode, ec); + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // Gets the non-blocking mode of the native descriptor implementation. + bool native_non_blocking(const implementation_type& impl) const + { + return (impl.state_ & descriptor_ops::internal_non_blocking) != 0; + } + + // Sets the non-blocking mode of the native descriptor implementation. + asio::error_code native_non_blocking(implementation_type& impl, + bool mode, asio::error_code& ec) + { + descriptor_ops::set_internal_non_blocking( + impl.descriptor_, impl.state_, mode, ec); + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // Wait for the descriptor to become ready to read, ready to write, or to have + // pending error conditions. + asio::error_code wait(implementation_type& impl, + posix::descriptor_base::wait_type w, asio::error_code& ec) + { + switch (w) + { + case posix::descriptor_base::wait_read: + descriptor_ops::poll_read(impl.descriptor_, impl.state_, ec); + break; + case posix::descriptor_base::wait_write: + descriptor_ops::poll_write(impl.descriptor_, impl.state_, ec); + break; + case posix::descriptor_base::wait_error: + descriptor_ops::poll_error(impl.descriptor_, impl.state_, ec); + break; + default: + ec = asio::error::invalid_argument; + break; + } + + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // Asynchronously wait for the descriptor to become ready to read, ready to + // write, or to have pending error conditions. + template <typename Handler, typename IoExecutor> + void async_wait(implementation_type& impl, + posix::descriptor_base::wait_type w, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + int op_type; + int poll_flags; + switch (w) + { + case posix::descriptor_base::wait_read: + op_type = io_uring_service::read_op; + poll_flags = POLLIN; + break; + case posix::descriptor_base::wait_write: + op_type = io_uring_service::write_op; + poll_flags = POLLOUT; + break; + case posix::descriptor_base::wait_error: + op_type = io_uring_service::except_op; + poll_flags = POLLPRI | POLLERR | POLLHUP; + break; + default: + op_type = -1; + poll_flags = -1; + return; + } + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_wait_op<Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.descriptor_, + poll_flags, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected() && op_type != -1) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>( + &io_uring_service_, &impl.io_object_data_, op_type); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "descriptor", &impl, impl.descriptor_, "async_wait")); + + start_op(impl, op_type, p.p, is_continuation, op_type == -1); + p.v = p.p = 0; + } + + // Write some data to the descriptor. + template <typename ConstBufferSequence> + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + typedef buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence> bufs_type; + + size_t n; + if (bufs_type::is_single_buffer) + { + n = descriptor_ops::sync_write1(impl.descriptor_, + impl.state_, bufs_type::first(buffers).data(), + bufs_type::first(buffers).size(), ec); + } + else + { + bufs_type bufs(buffers); + + n = descriptor_ops::sync_write(impl.descriptor_, impl.state_, + bufs.buffers(), bufs.count(), bufs.all_empty(), ec); + } + + ASIO_ERROR_LOCATION(ec); + return n; + } + + // Wait until data can be written without blocking. + size_t write_some(implementation_type& impl, + const null_buffers&, asio::error_code& ec) + { + // Wait for descriptor to become ready. + descriptor_ops::poll_write(impl.descriptor_, impl.state_, ec); + + ASIO_ERROR_LOCATION(ec); + return 0; + } + + // Start an asynchronous write. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, Handler& handler, + const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_descriptor_write_op< + ConstBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.descriptor_, + impl.state_, buffers, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::write_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "descriptor", &impl, impl.descriptor_, "async_write_some")); + + start_op(impl, io_uring_service::write_op, p.p, is_continuation, + buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence>::all_empty(buffers)); + p.v = p.p = 0; + } + + // Start an asynchronous wait until data can be written without blocking. + template <typename Handler, typename IoExecutor> + void async_write_some(implementation_type& impl, + const null_buffers&, Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_null_buffers_op<Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.descriptor_, POLLOUT, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::write_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), + *p.p, "descriptor", &impl, impl.descriptor_, + "async_write_some(null_buffers)")); + + start_op(impl, io_uring_service::write_op, p.p, is_continuation, false); + p.v = p.p = 0; + } + + // Write some data to the descriptor at the specified offset. + template <typename ConstBufferSequence> + size_t write_some_at(implementation_type& impl, uint64_t offset, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + typedef buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence> bufs_type; + + size_t n; + if (bufs_type::is_single_buffer) + { + n = descriptor_ops::sync_write_at1(impl.descriptor_, + impl.state_, offset, bufs_type::first(buffers).data(), + bufs_type::first(buffers).size(), ec); + } + else + { + bufs_type bufs(buffers); + + n = descriptor_ops::sync_write_at(impl.descriptor_, impl.state_, + offset, bufs.buffers(), bufs.count(), bufs.all_empty(), ec); + } + + ASIO_ERROR_LOCATION(ec); + return n; + } + + // Wait until data can be written without blocking. + size_t write_some_at(implementation_type& impl, uint64_t, + const null_buffers& buffers, asio::error_code& ec) + { + return write_some(impl, buffers, ec); + } + + // Start an asynchronous write at the specified offset. The data being sent + // must be valid for the lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> + void async_write_some_at(implementation_type& impl, uint64_t offset, + const ConstBufferSequence& buffers, Handler& handler, + const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_descriptor_write_at_op< + ConstBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.descriptor_, + impl.state_, offset, buffers, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::write_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "descriptor", &impl, impl.descriptor_, "async_write_some")); + + start_op(impl, io_uring_service::write_op, p.p, is_continuation, + buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence>::all_empty(buffers)); + p.v = p.p = 0; + } + + // Start an asynchronous wait until data can be written without blocking. + template <typename Handler, typename IoExecutor> + void async_write_some_at(implementation_type& impl, + const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex) + { + return async_write_some(impl, buffers, handler, io_ex); + } + + // Read some data from the stream. Returns the number of bytes read. + template <typename MutableBufferSequence> + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + typedef buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs_type; + + size_t n; + if (bufs_type::is_single_buffer) + { + n = descriptor_ops::sync_read1(impl.descriptor_, + impl.state_, bufs_type::first(buffers).data(), + bufs_type::first(buffers).size(), ec); + } + else + { + bufs_type bufs(buffers); + + n = descriptor_ops::sync_read(impl.descriptor_, impl.state_, + bufs.buffers(), bufs.count(), bufs.all_empty(), ec); + } + + ASIO_ERROR_LOCATION(ec); + return n; + } + + // Wait until data can be read without blocking. + size_t read_some(implementation_type& impl, + const null_buffers&, asio::error_code& ec) + { + // Wait for descriptor to become ready. + descriptor_ops::poll_read(impl.descriptor_, impl.state_, ec); + + ASIO_ERROR_LOCATION(ec); + return 0; + } + + // Start an asynchronous read. The buffer for the data being read must be + // valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_descriptor_read_op< + MutableBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.descriptor_, + impl.state_, buffers, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::read_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "descriptor", &impl, impl.descriptor_, "async_read_some")); + + start_op(impl, io_uring_service::read_op, p.p, is_continuation, + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence>::all_empty(buffers)); + p.v = p.p = 0; + } + + // Wait until data can be read without blocking. + template <typename Handler, typename IoExecutor> + void async_read_some(implementation_type& impl, + const null_buffers&, Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_null_buffers_op<Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.descriptor_, POLLIN, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::read_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), + *p.p, "descriptor", &impl, impl.descriptor_, + "async_read_some(null_buffers)")); + + start_op(impl, io_uring_service::read_op, p.p, is_continuation, false); + p.v = p.p = 0; + } + + // Read some data at the specified offset. Returns the number of bytes read. + template <typename MutableBufferSequence> + size_t read_some_at(implementation_type& impl, uint64_t offset, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + typedef buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs_type; + + if (bufs_type::is_single_buffer) + { + return descriptor_ops::sync_read_at1(impl.descriptor_, + impl.state_, offset, bufs_type::first(buffers).data(), + bufs_type::first(buffers).size(), ec); + } + else + { + bufs_type bufs(buffers); + + return descriptor_ops::sync_read_at(impl.descriptor_, impl.state_, + offset, bufs.buffers(), bufs.count(), bufs.all_empty(), ec); + } + } + + // Wait until data can be read without blocking. + size_t read_some_at(implementation_type& impl, uint64_t, + const null_buffers& buffers, asio::error_code& ec) + { + return read_some(impl, buffers, ec); + } + + // Start an asynchronous read. The buffer for the data being read must be + // valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> + void async_read_some_at(implementation_type& impl, + uint64_t offset, const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_descriptor_read_at_op< + MutableBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.descriptor_, + impl.state_, offset, buffers, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::read_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "descriptor", &impl, impl.descriptor_, "async_read_some")); + + start_op(impl, io_uring_service::read_op, p.p, is_continuation, + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence>::all_empty(buffers)); + p.v = p.p = 0; + } + + // Wait until data can be read without blocking. + template <typename Handler, typename IoExecutor> + void async_read_some_at(implementation_type& impl, uint64_t, + const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex) + { + return async_read_some(impl, buffers, handler, io_ex); + } + +private: + // Start the asynchronous operation. + ASIO_DECL void start_op(implementation_type& impl, int op_type, + io_uring_operation* op, bool is_continuation, bool noop); + + // Helper class used to implement per-operation cancellation + class io_uring_op_cancellation + { + public: + io_uring_op_cancellation(io_uring_service* s, + io_uring_service::per_io_object_data* p, int o) + : io_uring_service_(s), + io_object_data_(p), + op_type_(o) + { + } + + void operator()(cancellation_type_t type) + { + if (!!(type & + (cancellation_type::terminal + | cancellation_type::partial + | cancellation_type::total))) + { + io_uring_service_->cancel_ops_by_key(*io_object_data_, op_type_, this); + } + } + + private: + io_uring_service* io_uring_service_; + io_uring_service::per_io_object_data* io_object_data_; + int op_type_; + }; + + // The io_uring_service that performs event demultiplexing for the service. + io_uring_service& io_uring_service_; + + // Cached success value to avoid accessing category singleton. + const asio::error_code success_ec_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#if defined(ASIO_HEADER_ONLY) +# include "asio/detail/impl/io_uring_descriptor_service.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_SERVICE_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_descriptor_write_at_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_descriptor_write_at_op.hpp new file mode 100644 index 00000000000..10a3f7a6c3d --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_descriptor_write_at_op.hpp @@ -0,0 +1,189 @@ +// +// detail/io_uring_descriptor_write_at_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_AT_OP_HPP +#define ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_AT_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/descriptor_ops.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename ConstBufferSequence> +class io_uring_descriptor_write_at_op_base : public io_uring_operation +{ +public: + io_uring_descriptor_write_at_op_base( + const asio::error_code& success_ec, int descriptor, + descriptor_ops::state_type state, uint64_t offset, + const ConstBufferSequence& buffers, func_type complete_func) + : io_uring_operation(success_ec, + &io_uring_descriptor_write_at_op_base::do_prepare, + &io_uring_descriptor_write_at_op_base::do_perform, complete_func), + descriptor_(descriptor), + state_(state), + offset_(offset), + buffers_(buffers), + bufs_(buffers) + { + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_descriptor_write_at_op_base* o( + static_cast<io_uring_descriptor_write_at_op_base*>(base)); + + if ((o->state_ & descriptor_ops::internal_non_blocking) != 0) + { + ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLOUT); + } + else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer) + { + ::io_uring_prep_write_fixed(sqe, o->descriptor_, + o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len, + o->offset_, o->bufs_.registered_id().native_handle()); + } + else + { + ::io_uring_prep_writev(sqe, o->descriptor_, + o->bufs_.buffers(), o->bufs_.count(), o->offset_); + } + } + + static bool do_perform(io_uring_operation* base, bool after_completion) + { + ASIO_ASSUME(base != 0); + io_uring_descriptor_write_at_op_base* o( + static_cast<io_uring_descriptor_write_at_op_base*>(base)); + + if ((o->state_ & descriptor_ops::internal_non_blocking) != 0) + { + if (o->bufs_.is_single_buffer) + { + return descriptor_ops::non_blocking_write_at1(o->descriptor_, + o->offset_, o->bufs_.first(o->buffers_).data(), + o->bufs_.first(o->buffers_).size(), o->ec_, + o->bytes_transferred_); + } + else + { + return descriptor_ops::non_blocking_write_at(o->descriptor_, + o->offset_, o->bufs_.buffers(), o->bufs_.count(), + o->ec_, o->bytes_transferred_); + } + } + + if (o->ec_ && o->ec_ == asio::error::would_block) + { + o->state_ |= descriptor_ops::internal_non_blocking; + return false; + } + + return after_completion; + } + +private: + int descriptor_; + descriptor_ops::state_type state_; + uint64_t offset_; + ConstBufferSequence buffers_; + buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence> bufs_; +}; + +template <typename ConstBufferSequence, typename Handler, typename IoExecutor> +class io_uring_descriptor_write_at_op + : public io_uring_descriptor_write_at_op_base<ConstBufferSequence> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_write_at_op); + + io_uring_descriptor_write_at_op(const asio::error_code& success_ec, + int descriptor, descriptor_ops::state_type state, uint64_t offset, + const ConstBufferSequence& buffers, Handler& handler, + const IoExecutor& io_ex) + : io_uring_descriptor_write_at_op_base<ConstBufferSequence>( + success_ec, descriptor, state, offset, buffers, + &io_uring_descriptor_write_at_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_descriptor_write_at_op* o + (static_cast<io_uring_descriptor_write_at_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_AT_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_descriptor_write_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_descriptor_write_op.hpp new file mode 100644 index 00000000000..090d644c7c8 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_descriptor_write_op.hpp @@ -0,0 +1,185 @@ +// +// detail/io_uring_descriptor_write_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_OP_HPP +#define ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/descriptor_ops.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename ConstBufferSequence> +class io_uring_descriptor_write_op_base : public io_uring_operation +{ +public: + io_uring_descriptor_write_op_base(const asio::error_code& success_ec, + int descriptor, descriptor_ops::state_type state, + const ConstBufferSequence& buffers, func_type complete_func) + : io_uring_operation(success_ec, + &io_uring_descriptor_write_op_base::do_prepare, + &io_uring_descriptor_write_op_base::do_perform, complete_func), + descriptor_(descriptor), + state_(state), + buffers_(buffers), + bufs_(buffers) + { + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_descriptor_write_op_base* o( + static_cast<io_uring_descriptor_write_op_base*>(base)); + + if ((o->state_ & descriptor_ops::internal_non_blocking) != 0) + { + ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLOUT); + } + else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer) + { + ::io_uring_prep_write_fixed(sqe, o->descriptor_, + o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len, + 0, o->bufs_.registered_id().native_handle()); + } + else + { + ::io_uring_prep_writev(sqe, o->descriptor_, + o->bufs_.buffers(), o->bufs_.count(), -1); + } + } + + static bool do_perform(io_uring_operation* base, bool after_completion) + { + ASIO_ASSUME(base != 0); + io_uring_descriptor_write_op_base* o( + static_cast<io_uring_descriptor_write_op_base*>(base)); + + if ((o->state_ & descriptor_ops::internal_non_blocking) != 0) + { + if (o->bufs_.is_single_buffer) + { + return descriptor_ops::non_blocking_write1( + o->descriptor_, o->bufs_.first(o->buffers_).data(), + o->bufs_.first(o->buffers_).size(), o->ec_, + o->bytes_transferred_); + } + else + { + return descriptor_ops::non_blocking_write( + o->descriptor_, o->bufs_.buffers(), o->bufs_.count(), + o->ec_, o->bytes_transferred_); + } + } + + if (o->ec_ && o->ec_ == asio::error::would_block) + { + o->state_ |= descriptor_ops::internal_non_blocking; + return false; + } + + return after_completion; + } + +private: + int descriptor_; + descriptor_ops::state_type state_; + ConstBufferSequence buffers_; + buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence> bufs_; +}; + +template <typename ConstBufferSequence, typename Handler, typename IoExecutor> +class io_uring_descriptor_write_op + : public io_uring_descriptor_write_op_base<ConstBufferSequence> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_write_op); + + io_uring_descriptor_write_op(const asio::error_code& success_ec, + int descriptor, descriptor_ops::state_type state, + const ConstBufferSequence& buffers, Handler& handler, + const IoExecutor& io_ex) + : io_uring_descriptor_write_op_base<ConstBufferSequence>(success_ec, + descriptor, state, buffers, &io_uring_descriptor_write_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_descriptor_write_op* o + (static_cast<io_uring_descriptor_write_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_file_service.hpp b/3rdparty/asio/include/asio/detail/io_uring_file_service.hpp new file mode 100644 index 00000000000..3a0a4538623 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_file_service.hpp @@ -0,0 +1,261 @@ +// +// detail/io_uring_file_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_FILE_SERVICE_HPP +#define ASIO_DETAIL_IO_URING_FILE_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_FILE) \ + && defined(ASIO_HAS_IO_URING) + +#include <string> +#include "asio/detail/cstdint.hpp" +#include "asio/detail/descriptor_ops.hpp" +#include "asio/detail/io_uring_descriptor_service.hpp" +#include "asio/error.hpp" +#include "asio/execution_context.hpp" +#include "asio/file_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Extend the io_uring_descriptor_service to provide file support. +class io_uring_file_service : + public execution_context_service_base<io_uring_file_service> +{ +public: + typedef io_uring_descriptor_service descriptor_service; + + // The native type of a file. + typedef descriptor_service::native_handle_type native_handle_type; + + // The implementation type of the file. + class implementation_type : descriptor_service::implementation_type + { + private: + // Only this service will have access to the internal values. + friend class io_uring_file_service; + + bool is_stream_; + }; + + ASIO_DECL io_uring_file_service(execution_context& context); + + // Destroy all user-defined handler objects owned by the service. + ASIO_DECL void shutdown(); + + // Construct a new file implementation. + void construct(implementation_type& impl) + { + descriptor_service_.construct(impl); + impl.is_stream_ = false; + } + + // Move-construct a new file implementation. + void move_construct(implementation_type& impl, + implementation_type& other_impl) + { + descriptor_service_.move_construct(impl, other_impl); + impl.is_stream_ = other_impl.is_stream_; + } + + // Move-assign from another file implementation. + void move_assign(implementation_type& impl, + io_uring_file_service& other_service, + implementation_type& other_impl) + { + descriptor_service_.move_assign(impl, + other_service.descriptor_service_, other_impl); + impl.is_stream_ = other_impl.is_stream_; + } + + // Destroy a file implementation. + void destroy(implementation_type& impl) + { + descriptor_service_.destroy(impl); + } + + // Open the file using the specified path name. + ASIO_DECL asio::error_code open(implementation_type& impl, + const char* path, file_base::flags open_flags, + asio::error_code& ec); + + // Assign a native descriptor to a file implementation. + asio::error_code assign(implementation_type& impl, + const native_handle_type& native_descriptor, + asio::error_code& ec) + { + return descriptor_service_.assign(impl, native_descriptor, ec); + } + + // Set whether the implementation is stream-oriented. + void set_is_stream(implementation_type& impl, bool is_stream) + { + impl.is_stream_ = is_stream; + } + + // Determine whether the file is open. + bool is_open(const implementation_type& impl) const + { + return descriptor_service_.is_open(impl); + } + + // Destroy a file implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + return descriptor_service_.close(impl, ec); + } + + // Get the native file representation. + native_handle_type native_handle(const implementation_type& impl) const + { + return descriptor_service_.native_handle(impl); + } + + // Release ownership of the native descriptor representation. + native_handle_type release(implementation_type& impl, + asio::error_code& ec) + { + return descriptor_service_.release(impl, ec); + } + + // Cancel all operations associated with the file. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + return descriptor_service_.cancel(impl, ec); + } + + // Get the size of the file. + ASIO_DECL uint64_t size(const implementation_type& impl, + asio::error_code& ec) const; + + // Alter the size of the file. + ASIO_DECL asio::error_code resize(implementation_type& impl, + uint64_t n, asio::error_code& ec); + + // Synchronise the file to disk. + ASIO_DECL asio::error_code sync_all(implementation_type& impl, + asio::error_code& ec); + + // Synchronise the file data to disk. + ASIO_DECL asio::error_code sync_data(implementation_type& impl, + asio::error_code& ec); + + // Seek to a position in the file. + ASIO_DECL uint64_t seek(implementation_type& impl, int64_t offset, + file_base::seek_basis whence, asio::error_code& ec); + + // Write the given data. Returns the number of bytes written. + template <typename ConstBufferSequence> + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return descriptor_service_.write_some(impl, buffers, ec); + } + + // Start an asynchronous write. The data being written must be valid for the + // lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + { + descriptor_service_.async_write_some(impl, buffers, handler, io_ex); + } + + // Write the given data at the specified location. Returns the number of + // bytes written. + template <typename ConstBufferSequence> + size_t write_some_at(implementation_type& impl, uint64_t offset, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return descriptor_service_.write_some_at(impl, offset, buffers, ec); + } + + // Start an asynchronous write at the specified location. The data being + // written must be valid for the lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> + void async_write_some_at(implementation_type& impl, + uint64_t offset, const ConstBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + { + descriptor_service_.async_write_some_at( + impl, offset, buffers, handler, io_ex); + } + + // Read some data. Returns the number of bytes read. + template <typename MutableBufferSequence> + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return descriptor_service_.read_some(impl, buffers, ec); + } + + // Start an asynchronous read. The buffer for the data being read must be + // valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + { + descriptor_service_.async_read_some(impl, buffers, handler, io_ex); + } + + // Read some data. Returns the number of bytes read. + template <typename MutableBufferSequence> + size_t read_some_at(implementation_type& impl, uint64_t offset, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return descriptor_service_.read_some_at(impl, offset, buffers, ec); + } + + // Start an asynchronous read. The buffer for the data being read must be + // valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> + void async_read_some_at(implementation_type& impl, + uint64_t offset, const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + { + descriptor_service_.async_read_some_at( + impl, offset, buffers, handler, io_ex); + } + +private: + // The implementation used for initiating asynchronous operations. + descriptor_service descriptor_service_; + + // Cached success value to avoid accessing category singleton. + const asio::error_code success_ec_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#if defined(ASIO_HEADER_ONLY) +# include "asio/detail/impl/io_uring_file_service.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +#endif // defined(ASIO_HAS_FILE) + // && defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_FILE_SERVICE_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_null_buffers_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_null_buffers_op.hpp new file mode 100644 index 00000000000..61fe6a6aafb --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_null_buffers_op.hpp @@ -0,0 +1,114 @@ +// +// detail/io_uring_null_buffers_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_NULL_BUFFERS_OP_HPP +#define ASIO_DETAIL_IO_URING_NULL_BUFFERS_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Handler, typename IoExecutor> +class io_uring_null_buffers_op : public io_uring_operation +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_null_buffers_op); + + io_uring_null_buffers_op(const asio::error_code& success_ec, + int descriptor, int poll_flags, Handler& handler, const IoExecutor& io_ex) + : io_uring_operation(success_ec, + &io_uring_null_buffers_op::do_prepare, + &io_uring_null_buffers_op::do_perform, + &io_uring_null_buffers_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex), + descriptor_(descriptor), + poll_flags_(poll_flags) + { + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_null_buffers_op* o(static_cast<io_uring_null_buffers_op*>(base)); + + ::io_uring_prep_poll_add(sqe, o->descriptor_, o->poll_flags_); + } + + static bool do_perform(io_uring_operation*, bool after_completion) + { + return after_completion; + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_null_buffers_op* o(static_cast<io_uring_null_buffers_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; + int descriptor_; + int poll_flags_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_IO_URING_NULL_BUFFERS_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_operation.hpp b/3rdparty/asio/include/asio/detail/io_uring_operation.hpp new file mode 100644 index 00000000000..f2635cc4074 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_operation.hpp @@ -0,0 +1,84 @@ +// +// detail/io_uring_operation.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_OPERATION_HPP +#define ASIO_DETAIL_IO_URING_OPERATION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include <liburing.h> +#include "asio/detail/cstdint.hpp" +#include "asio/detail/operation.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class io_uring_operation + : public operation +{ +public: + // The error code to be passed to the completion handler. + asio::error_code ec_; + + // The number of bytes transferred, to be passed to the completion handler. + std::size_t bytes_transferred_; + + // The operation key used for targeted cancellation. + void* cancellation_key_; + + // Prepare the operation. + void prepare(::io_uring_sqe* sqe) + { + return prepare_func_(this, sqe); + } + + // Perform actions associated with the operation. Returns true when complete. + bool perform(bool after_completion) + { + return perform_func_(this, after_completion); + } + +protected: + typedef void (*prepare_func_type)(io_uring_operation*, ::io_uring_sqe*); + typedef bool (*perform_func_type)(io_uring_operation*, bool); + + io_uring_operation(const asio::error_code& success_ec, + prepare_func_type prepare_func, perform_func_type perform_func, + func_type complete_func) + : operation(complete_func), + ec_(success_ec), + bytes_transferred_(0), + cancellation_key_(0), + prepare_func_(prepare_func), + perform_func_(perform_func) + { + } + +private: + prepare_func_type prepare_func_; + perform_func_type perform_func_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_OPERATION_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_service.hpp b/3rdparty/asio/include/asio/detail/io_uring_service.hpp new file mode 100644 index 00000000000..2dd3c0bf14d --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_service.hpp @@ -0,0 +1,319 @@ +// +// detail/io_uring_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_SERVICE_HPP +#define ASIO_DETAIL_IO_URING_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include <liburing.h> +#include "asio/detail/atomic_count.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/conditionally_enabled_mutex.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/limits.hpp" +#include "asio/detail/object_pool.hpp" +#include "asio/detail/op_queue.hpp" +#include "asio/detail/reactor.hpp" +#include "asio/detail/scheduler_task.hpp" +#include "asio/detail/timer_queue_base.hpp" +#include "asio/detail/timer_queue_set.hpp" +#include "asio/detail/wait_op.hpp" +#include "asio/execution_context.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class io_uring_service + : public execution_context_service_base<io_uring_service>, + public scheduler_task +{ +private: + // The mutex type used by this reactor. + typedef conditionally_enabled_mutex mutex; + +public: + enum op_types { read_op = 0, write_op = 1, except_op = 2, max_ops = 3 }; + + class io_object; + + // An I/O queue stores operations that must run serially. + class io_queue : operation + { + friend class io_uring_service; + + io_object* io_object_; + op_queue<io_uring_operation> op_queue_; + bool cancel_requested_; + + ASIO_DECL io_queue(); + void set_result(int r) { task_result_ = static_cast<unsigned>(r); } + ASIO_DECL operation* perform_io(int result); + ASIO_DECL static void do_complete(void* owner, operation* base, + const asio::error_code& ec, std::size_t bytes_transferred); + }; + + // Per I/O object state. + class io_object + { + friend class io_uring_service; + friend class object_pool_access; + + io_object* next_; + io_object* prev_; + + mutex mutex_; + io_uring_service* service_; + io_queue queues_[max_ops]; + bool shutdown_; + + ASIO_DECL io_object(bool locking); + }; + + // Per I/O object data. + typedef io_object* per_io_object_data; + + // Constructor. + ASIO_DECL io_uring_service(asio::execution_context& ctx); + + // Destructor. + ASIO_DECL ~io_uring_service(); + + // Destroy all user-defined handler objects owned by the service. + ASIO_DECL void shutdown(); + + // Recreate internal state following a fork. + ASIO_DECL void notify_fork( + asio::execution_context::fork_event fork_ev); + + // Initialise the task. + ASIO_DECL void init_task(); + + // Register an I/O object with io_uring. + ASIO_DECL void register_io_object(io_object*& io_obj); + + // Register an internal I/O object with io_uring. + ASIO_DECL void register_internal_io_object( + io_object*& io_obj, int op_type, io_uring_operation* op); + + // Register buffers with io_uring. + ASIO_DECL void register_buffers(const ::iovec* v, unsigned n); + + // Unregister buffers from io_uring. + ASIO_DECL void unregister_buffers(); + + // Post an operation for immediate completion. + void post_immediate_completion(operation* op, bool is_continuation); + + // Start a new operation. The operation will be prepared and submitted to the + // io_uring when it is at the head of its I/O operation queue. + ASIO_DECL void start_op(int op_type, per_io_object_data& io_obj, + io_uring_operation* op, bool is_continuation); + + // Cancel all operations associated with the given I/O object. The handlers + // associated with the I/O object will be invoked with the operation_aborted + // error. + ASIO_DECL void cancel_ops(per_io_object_data& io_obj); + + // Cancel all operations associated with the given I/O object and key. The + // handlers associated with the object and key will be invoked with the + // operation_aborted error. + ASIO_DECL void cancel_ops_by_key(per_io_object_data& io_obj, + int op_type, void* cancellation_key); + + // Cancel any operations that are running against the I/O object and remove + // its registration from the service. The service resources associated with + // the I/O object must be released by calling cleanup_io_object. + ASIO_DECL void deregister_io_object(per_io_object_data& io_obj); + + // Perform any post-deregistration cleanup tasks associated with the I/O + // object. + ASIO_DECL void cleanup_io_object(per_io_object_data& io_obj); + + // Add a new timer queue to the reactor. + template <typename Time_Traits> + void add_timer_queue(timer_queue<Time_Traits>& timer_queue); + + // Remove a timer queue from the reactor. + template <typename Time_Traits> + void remove_timer_queue(timer_queue<Time_Traits>& timer_queue); + + // Schedule a new operation in the given timer queue to expire at the + // specified absolute time. + template <typename Time_Traits> + void schedule_timer(timer_queue<Time_Traits>& queue, + const typename Time_Traits::time_type& time, + typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op); + + // Cancel the timer operations associated with the given token. Returns the + // number of operations that have been posted or dispatched. + template <typename Time_Traits> + std::size_t cancel_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& timer, + std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)()); + + // Cancel the timer operations associated with the given key. + template <typename Time_Traits> + void cancel_timer_by_key(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data* timer, + void* cancellation_key); + + // Move the timer operations associated with the given timer. + template <typename Time_Traits> + void move_timer(timer_queue<Time_Traits>& queue, + typename timer_queue<Time_Traits>::per_timer_data& target, + typename timer_queue<Time_Traits>::per_timer_data& source); + + // Wait on io_uring once until interrupted or events are ready to be + // dispatched. + ASIO_DECL void run(long usec, op_queue<operation>& ops); + + // Interrupt the io_uring wait. + ASIO_DECL void interrupt(); + +private: + // The hint to pass to io_uring_queue_init to size its data structures. + enum { ring_size = 16384 }; + + // The number of operations to submit in a batch. + enum { submit_batch_size = 128 }; + + // The number of operations to complete in a batch. + enum { complete_batch_size = 128 }; + + // The type used for processing eventfd readiness notifications. + class event_fd_read_op; + + // Initialise the ring. + ASIO_DECL void init_ring(); + + // Register the eventfd descriptor for readiness notifications. + ASIO_DECL void register_with_reactor(); + + // Allocate a new I/O object. + ASIO_DECL io_object* allocate_io_object(); + + // Free an existing I/O object. + ASIO_DECL void free_io_object(io_object* s); + + // Helper function to cancel all operations associated with the given I/O + // object. This function must be called while the I/O object's mutex is held. + // Returns true if there are operations for which cancellation is pending. + ASIO_DECL bool do_cancel_ops( + per_io_object_data& io_obj, op_queue<operation>& ops); + + // Helper function to add a new timer queue. + ASIO_DECL void do_add_timer_queue(timer_queue_base& queue); + + // Helper function to remove a timer queue. + ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue); + + // Called to recalculate and update the timeout. + ASIO_DECL void update_timeout(); + + // Get the current timeout value. + ASIO_DECL __kernel_timespec get_timeout() const; + + // Get a new submission queue entry, flushing the queue if necessary. + ASIO_DECL ::io_uring_sqe* get_sqe(); + + // Submit pending submission queue entries. + ASIO_DECL void submit_sqes(); + + // Post an operation to submit the pending submission queue entries. + ASIO_DECL void post_submit_sqes_op(mutex::scoped_lock& lock); + + // Push an operation to submit the pending submission queue entries. + ASIO_DECL void push_submit_sqes_op(op_queue<operation>& ops); + + // Helper operation to submit pending submission queue entries. + class submit_sqes_op : operation + { + friend class io_uring_service; + + io_uring_service* service_; + + ASIO_DECL submit_sqes_op(io_uring_service* s); + ASIO_DECL static void do_complete(void* owner, operation* base, + const asio::error_code& ec, std::size_t bytes_transferred); + }; + + // The scheduler implementation used to post completions. + scheduler& scheduler_; + + // Mutex to protect access to internal data. + mutex mutex_; + + // The ring. + ::io_uring ring_; + + // The count of unfinished work. + atomic_count outstanding_work_; + + // The operation used to submit the pending submission queue entries. + submit_sqes_op submit_sqes_op_; + + // The number of pending submission queue entries_. + int pending_sqes_; + + // Whether there is a pending submission operation. + bool pending_submit_sqes_op_; + + // Whether the service has been shut down. + bool shutdown_; + + // The timer queues. + timer_queue_set timer_queues_; + + // The timespec for the pending timeout operation. Must remain valid while the + // operation is outstanding. + __kernel_timespec timeout_; + + // Mutex to protect access to the registered I/O objects. + mutex registration_mutex_; + + // Keep track of all registered I/O objects. + object_pool<io_object> registered_io_objects_; + + // Helper class to do post-perform_io cleanup. + struct perform_io_cleanup_on_block_exit; + friend struct perform_io_cleanup_on_block_exit; + + // The reactor used to register for eventfd readiness. + reactor& reactor_; + + // The per-descriptor reactor data used for the eventfd. + reactor::per_descriptor_data reactor_data_; + + // The eventfd descriptor used to wait for readiness. + int event_fd_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/detail/impl/io_uring_service.hpp" +#if defined(ASIO_HEADER_ONLY) +# include "asio/detail/impl/io_uring_service.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_SERVICE_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_socket_accept_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_socket_accept_op.hpp new file mode 100644 index 00000000000..dbf1a98b536 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_socket_accept_op.hpp @@ -0,0 +1,280 @@ +// +// detail/io_uring_socket_accept_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_SOCKET_ACCEPT_OP_HPP +#define ASIO_DETAIL_IO_URING_SOCKET_ACCEPT_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" +#include "asio/detail/socket_holder.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Socket, typename Protocol> +class io_uring_socket_accept_op_base : public io_uring_operation +{ +public: + io_uring_socket_accept_op_base(const asio::error_code& success_ec, + socket_type socket, socket_ops::state_type state, Socket& peer, + const Protocol& protocol, typename Protocol::endpoint* peer_endpoint, + func_type complete_func) + : io_uring_operation(success_ec, + &io_uring_socket_accept_op_base::do_prepare, + &io_uring_socket_accept_op_base::do_perform, complete_func), + socket_(socket), + state_(state), + peer_(peer), + protocol_(protocol), + peer_endpoint_(peer_endpoint), + addrlen_(peer_endpoint ? peer_endpoint->capacity() : 0) + { + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_socket_accept_op_base* o( + static_cast<io_uring_socket_accept_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + ::io_uring_prep_poll_add(sqe, o->socket_, POLLIN); + } + else + { + ::io_uring_prep_accept(sqe, o->socket_, + o->peer_endpoint_ ? o->peer_endpoint_->data() : 0, + o->peer_endpoint_ ? &o->addrlen_ : 0, 0); + } + } + + static bool do_perform(io_uring_operation* base, bool after_completion) + { + ASIO_ASSUME(base != 0); + io_uring_socket_accept_op_base* o( + static_cast<io_uring_socket_accept_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + socket_type new_socket = invalid_socket; + std::size_t addrlen = static_cast<std::size_t>(o->addrlen_); + bool result = socket_ops::non_blocking_accept(o->socket_, + o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0, + o->peer_endpoint_ ? &addrlen : 0, o->ec_, new_socket); + o->new_socket_.reset(new_socket); + o->addrlen_ = static_cast<socklen_t>(addrlen); + return result; + } + + if (o->ec_ && o->ec_ == asio::error::would_block) + { + o->state_ |= socket_ops::internal_non_blocking; + return false; + } + + if (after_completion && !o->ec_) + o->new_socket_.reset(static_cast<int>(o->bytes_transferred_)); + + return after_completion; + } + + void do_assign() + { + if (new_socket_.get() != invalid_socket) + { + if (peer_endpoint_) + peer_endpoint_->resize(addrlen_); + peer_.assign(protocol_, new_socket_.get(), ec_); + if (!ec_) + new_socket_.release(); + } + } + +private: + socket_type socket_; + socket_ops::state_type state_; + socket_holder new_socket_; + Socket& peer_; + Protocol protocol_; + typename Protocol::endpoint* peer_endpoint_; + socklen_t addrlen_; +}; + +template <typename Socket, typename Protocol, + typename Handler, typename IoExecutor> +class io_uring_socket_accept_op : + public io_uring_socket_accept_op_base<Socket, Protocol> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_socket_accept_op); + + io_uring_socket_accept_op(const asio::error_code& success_ec, + socket_type socket, socket_ops::state_type state, Socket& peer, + const Protocol& protocol, typename Protocol::endpoint* peer_endpoint, + Handler& handler, const IoExecutor& io_ex) + : io_uring_socket_accept_op_base<Socket, Protocol>( + success_ec, socket, state, peer, protocol, peer_endpoint, + &io_uring_socket_accept_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_socket_accept_op* o(static_cast<io_uring_socket_accept_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + // On success, assign new connection to peer socket object. + if (owner) + o->do_assign(); + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder1<Handler, asio::error_code> + handler(o->handler_, o->ec_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +template <typename Protocol, typename PeerIoExecutor, + typename Handler, typename IoExecutor> +class io_uring_socket_move_accept_op : + private Protocol::socket::template rebind_executor<PeerIoExecutor>::other, + public io_uring_socket_accept_op_base< + typename Protocol::socket::template rebind_executor<PeerIoExecutor>::other, + Protocol> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_socket_move_accept_op); + + io_uring_socket_move_accept_op(const asio::error_code& success_ec, + const PeerIoExecutor& peer_io_ex, socket_type socket, + socket_ops::state_type state, const Protocol& protocol, + typename Protocol::endpoint* peer_endpoint, Handler& handler, + const IoExecutor& io_ex) + : peer_socket_type(peer_io_ex), + io_uring_socket_accept_op_base<peer_socket_type, Protocol>( + success_ec, socket, state, *this, protocol, peer_endpoint, + &io_uring_socket_move_accept_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_socket_move_accept_op* o( + static_cast<io_uring_socket_move_accept_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + // On success, assign new connection to peer socket object. + if (owner) + o->do_assign(); + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::move_binder2<Handler, + asio::error_code, peer_socket_type> + handler(0, static_cast<Handler&&>(o->handler_), o->ec_, + static_cast<peer_socket_type&&>(*o)); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "...")); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + typedef typename Protocol::socket::template + rebind_executor<PeerIoExecutor>::other peer_socket_type; + + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_SOCKET_ACCEPT_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_socket_connect_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_socket_connect_op.hpp new file mode 100644 index 00000000000..45d30c6bb0a --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_socket_connect_op.hpp @@ -0,0 +1,140 @@ +// +// detail/io_uring_socket_connect_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_SOCKET_CONNECT_OP_HPP +#define ASIO_DETAIL_IO_URING_SOCKET_CONNECT_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" +#include "asio/detail/socket_ops.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Protocol> +class io_uring_socket_connect_op_base : public io_uring_operation +{ +public: + io_uring_socket_connect_op_base(const asio::error_code& success_ec, + socket_type socket, const typename Protocol::endpoint& endpoint, + func_type complete_func) + : io_uring_operation(success_ec, + &io_uring_socket_connect_op_base::do_prepare, + &io_uring_socket_connect_op_base::do_perform, complete_func), + socket_(socket), + endpoint_(endpoint) + { + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_socket_connect_op_base* o( + static_cast<io_uring_socket_connect_op_base*>(base)); + + ::io_uring_prep_connect(sqe, o->socket_, + static_cast<sockaddr*>(o->endpoint_.data()), + static_cast<socklen_t>(o->endpoint_.size())); + } + + static bool do_perform(io_uring_operation*, bool after_completion) + { + return after_completion; + } + +private: + socket_type socket_; + typename Protocol::endpoint endpoint_; +}; + +template <typename Protocol, typename Handler, typename IoExecutor> +class io_uring_socket_connect_op : + public io_uring_socket_connect_op_base<Protocol> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_socket_connect_op); + + io_uring_socket_connect_op(const asio::error_code& success_ec, + socket_type socket, const typename Protocol::endpoint& endpoint, + Handler& handler, const IoExecutor& io_ex) + : io_uring_socket_connect_op_base<Protocol>(success_ec, socket, + endpoint, &io_uring_socket_connect_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_socket_connect_op* o + (static_cast<io_uring_socket_connect_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder1<Handler, asio::error_code> + handler(o->handler_, o->ec_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_SOCKET_CONNECT_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_socket_recv_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_socket_recv_op.hpp new file mode 100644 index 00000000000..b1936c1ab93 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_socket_recv_op.hpp @@ -0,0 +1,205 @@ +// +// detail/io_uring_socket_recv_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_SOCKET_RECV_OP_HPP +#define ASIO_DETAIL_IO_URING_SOCKET_RECV_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename MutableBufferSequence> +class io_uring_socket_recv_op_base : public io_uring_operation +{ +public: + io_uring_socket_recv_op_base(const asio::error_code& success_ec, + socket_type socket, socket_ops::state_type state, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, func_type complete_func) + : io_uring_operation(success_ec, + &io_uring_socket_recv_op_base::do_prepare, + &io_uring_socket_recv_op_base::do_perform, complete_func), + socket_(socket), + state_(state), + buffers_(buffers), + flags_(flags), + bufs_(buffers), + msghdr_() + { + msghdr_.msg_iov = bufs_.buffers(); + msghdr_.msg_iovlen = static_cast<int>(bufs_.count()); + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_socket_recv_op_base* o( + static_cast<io_uring_socket_recv_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0; + ::io_uring_prep_poll_add(sqe, o->socket_, except_op ? POLLPRI : POLLIN); + } + else if (o->bufs_.is_single_buffer + && o->bufs_.is_registered_buffer && o->flags_ == 0) + { + ::io_uring_prep_read_fixed(sqe, o->socket_, + o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len, + 0, o->bufs_.registered_id().native_handle()); + } + else + { + ::io_uring_prep_recvmsg(sqe, o->socket_, &o->msghdr_, o->flags_); + } + } + + static bool do_perform(io_uring_operation* base, bool after_completion) + { + ASIO_ASSUME(base != 0); + io_uring_socket_recv_op_base* o( + static_cast<io_uring_socket_recv_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0; + if (after_completion || !except_op) + { + if (o->bufs_.is_single_buffer) + { + return socket_ops::non_blocking_recv1(o->socket_, + o->bufs_.first(o->buffers_).data(), + o->bufs_.first(o->buffers_).size(), o->flags_, + (o->state_ & socket_ops::stream_oriented) != 0, + o->ec_, o->bytes_transferred_); + } + else + { + return socket_ops::non_blocking_recv(o->socket_, + o->bufs_.buffers(), o->bufs_.count(), o->flags_, + (o->state_ & socket_ops::stream_oriented) != 0, + o->ec_, o->bytes_transferred_); + } + } + } + else if (after_completion) + { + if (!o->ec_ && o->bytes_transferred_ == 0) + if ((o->state_ & socket_ops::stream_oriented) != 0) + o->ec_ = asio::error::eof; + } + + if (o->ec_ && o->ec_ == asio::error::would_block) + { + o->state_ |= socket_ops::internal_non_blocking; + return false; + } + + return after_completion; + } + +private: + socket_type socket_; + socket_ops::state_type state_; + MutableBufferSequence buffers_; + socket_base::message_flags flags_; + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs_; + msghdr msghdr_; +}; + +template <typename MutableBufferSequence, typename Handler, typename IoExecutor> +class io_uring_socket_recv_op + : public io_uring_socket_recv_op_base<MutableBufferSequence> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_socket_recv_op); + + io_uring_socket_recv_op(const asio::error_code& success_ec, + int socket, socket_ops::state_type state, + const MutableBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + : io_uring_socket_recv_op_base<MutableBufferSequence>(success_ec, + socket, state, buffers, flags, &io_uring_socket_recv_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_socket_recv_op* o + (static_cast<io_uring_socket_recv_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_SOCKET_RECV_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_socket_recvfrom_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_socket_recvfrom_op.hpp new file mode 100644 index 00000000000..dfd30e4f2a1 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_socket_recvfrom_op.hpp @@ -0,0 +1,206 @@ +// +// detail/io_uring_socket_recvfrom_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_SOCKET_RECVFROM_OP_HPP +#define ASIO_DETAIL_IO_URING_SOCKET_RECVFROM_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename MutableBufferSequence, typename Endpoint> +class io_uring_socket_recvfrom_op_base : public io_uring_operation +{ +public: + io_uring_socket_recvfrom_op_base(const asio::error_code& success_ec, + socket_type socket, socket_ops::state_type state, + const MutableBufferSequence& buffers, Endpoint& endpoint, + socket_base::message_flags flags, func_type complete_func) + : io_uring_operation(success_ec, + &io_uring_socket_recvfrom_op_base::do_prepare, + &io_uring_socket_recvfrom_op_base::do_perform, complete_func), + socket_(socket), + state_(state), + buffers_(buffers), + sender_endpoint_(endpoint), + flags_(flags), + bufs_(buffers), + msghdr_() + { + msghdr_.msg_iov = bufs_.buffers(); + msghdr_.msg_iovlen = static_cast<int>(bufs_.count()); + msghdr_.msg_name = static_cast<sockaddr*>( + static_cast<void*>(sender_endpoint_.data())); + msghdr_.msg_namelen = sender_endpoint_.capacity(); + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_socket_recvfrom_op_base* o( + static_cast<io_uring_socket_recvfrom_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0; + ::io_uring_prep_poll_add(sqe, o->socket_, except_op ? POLLPRI : POLLIN); + } + else + { + ::io_uring_prep_recvmsg(sqe, o->socket_, &o->msghdr_, o->flags_); + } + } + + static bool do_perform(io_uring_operation* base, bool after_completion) + { + ASIO_ASSUME(base != 0); + io_uring_socket_recvfrom_op_base* o( + static_cast<io_uring_socket_recvfrom_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0; + if (after_completion || !except_op) + { + std::size_t addr_len = o->sender_endpoint_.capacity(); + bool result; + if (o->bufs_.is_single_buffer) + { + result = socket_ops::non_blocking_recvfrom1(o->socket_, + o->bufs_.first(o->buffers_).data(), + o->bufs_.first(o->buffers_).size(), o->flags_, + o->sender_endpoint_.data(), &addr_len, + o->ec_, o->bytes_transferred_); + } + else + { + result = socket_ops::non_blocking_recvfrom(o->socket_, + o->bufs_.buffers(), o->bufs_.count(), o->flags_, + o->sender_endpoint_.data(), &addr_len, + o->ec_, o->bytes_transferred_); + } + if (result && !o->ec_) + o->sender_endpoint_.resize(addr_len); + } + } + else if (after_completion && !o->ec_) + o->sender_endpoint_.resize(o->msghdr_.msg_namelen); + + if (o->ec_ && o->ec_ == asio::error::would_block) + { + o->state_ |= socket_ops::internal_non_blocking; + return false; + } + + return after_completion; + } + +private: + socket_type socket_; + socket_ops::state_type state_; + MutableBufferSequence buffers_; + Endpoint& sender_endpoint_; + socket_base::message_flags flags_; + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs_; + msghdr msghdr_; +}; + +template <typename MutableBufferSequence, typename Endpoint, + typename Handler, typename IoExecutor> +class io_uring_socket_recvfrom_op + : public io_uring_socket_recvfrom_op_base<MutableBufferSequence, Endpoint> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_socket_recvfrom_op); + + io_uring_socket_recvfrom_op(const asio::error_code& success_ec, + int socket, socket_ops::state_type state, + const MutableBufferSequence& buffers, Endpoint& endpoint, + socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + : io_uring_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>( + success_ec, socket, state, buffers, endpoint, flags, + &io_uring_socket_recvfrom_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_socket_recvfrom_op* o + (static_cast<io_uring_socket_recvfrom_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_SOCKET_RECVFROM_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_socket_recvmsg_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_socket_recvmsg_op.hpp new file mode 100644 index 00000000000..778d0fa3acf --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_socket_recvmsg_op.hpp @@ -0,0 +1,192 @@ +// +// detail/io_uring_socket_recvmsg_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_SOCKET_RECVMSG_OP_HPP +#define ASIO_DETAIL_IO_URING_SOCKET_RECVMSG_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename MutableBufferSequence> +class io_uring_socket_recvmsg_op_base : public io_uring_operation +{ +public: + io_uring_socket_recvmsg_op_base(const asio::error_code& success_ec, + socket_type socket, socket_ops::state_type state, + const MutableBufferSequence& buffers, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, func_type complete_func) + : io_uring_operation(success_ec, + &io_uring_socket_recvmsg_op_base::do_prepare, + &io_uring_socket_recvmsg_op_base::do_perform, complete_func), + socket_(socket), + state_(state), + buffers_(buffers), + in_flags_(in_flags), + out_flags_(out_flags), + bufs_(buffers), + msghdr_() + { + msghdr_.msg_iov = bufs_.buffers(); + msghdr_.msg_iovlen = static_cast<int>(bufs_.count()); + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_socket_recvmsg_op_base* o( + static_cast<io_uring_socket_recvmsg_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + bool except_op = (o->in_flags_ & socket_base::message_out_of_band) != 0; + ::io_uring_prep_poll_add(sqe, o->socket_, except_op ? POLLPRI : POLLIN); + } + else + { + ::io_uring_prep_recvmsg(sqe, o->socket_, &o->msghdr_, o->in_flags_); + } + } + + static bool do_perform(io_uring_operation* base, bool after_completion) + { + ASIO_ASSUME(base != 0); + io_uring_socket_recvmsg_op_base* o( + static_cast<io_uring_socket_recvmsg_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + bool except_op = (o->in_flags_ & socket_base::message_out_of_band) != 0; + if (after_completion || !except_op) + { + return socket_ops::non_blocking_recvmsg(o->socket_, + o->bufs_.buffers(), o->bufs_.count(), o->in_flags_, + o->out_flags_, o->ec_, o->bytes_transferred_); + } + } + else if (after_completion) + { + if (!o->ec_) + o->out_flags_ = o->msghdr_.msg_flags; + else + o->out_flags_ = 0; + } + + if (o->ec_ && o->ec_ == asio::error::would_block) + { + o->state_ |= socket_ops::internal_non_blocking; + return false; + } + + return after_completion; + } + +private: + socket_type socket_; + socket_ops::state_type state_; + MutableBufferSequence buffers_; + socket_base::message_flags in_flags_; + socket_base::message_flags& out_flags_; + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs_; + msghdr msghdr_; +}; + +template <typename MutableBufferSequence, typename Handler, typename IoExecutor> +class io_uring_socket_recvmsg_op + : public io_uring_socket_recvmsg_op_base<MutableBufferSequence> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_socket_recvmsg_op); + + io_uring_socket_recvmsg_op(const asio::error_code& success_ec, + int socket, socket_ops::state_type state, + const MutableBufferSequence& buffers, + socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, + Handler& handler, const IoExecutor& io_ex) + : io_uring_socket_recvmsg_op_base<MutableBufferSequence>(success_ec, + socket, state, buffers, in_flags, out_flags, + &io_uring_socket_recvmsg_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_socket_recvmsg_op* o + (static_cast<io_uring_socket_recvmsg_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_SOCKET_RECVMSG_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_socket_send_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_socket_send_op.hpp new file mode 100644 index 00000000000..2f57dae920d --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_socket_send_op.hpp @@ -0,0 +1,191 @@ +// +// detail/io_uring_socket_send_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_SOCKET_SEND_OP_HPP +#define ASIO_DETAIL_IO_URING_SOCKET_SEND_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename ConstBufferSequence> +class io_uring_socket_send_op_base : public io_uring_operation +{ +public: + io_uring_socket_send_op_base(const asio::error_code& success_ec, + socket_type socket, socket_ops::state_type state, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, func_type complete_func) + : io_uring_operation(success_ec, + &io_uring_socket_send_op_base::do_prepare, + &io_uring_socket_send_op_base::do_perform, complete_func), + socket_(socket), + state_(state), + buffers_(buffers), + flags_(flags), + bufs_(buffers), + msghdr_() + { + msghdr_.msg_iov = bufs_.buffers(); + msghdr_.msg_iovlen = static_cast<int>(bufs_.count()); + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_socket_send_op_base* o( + static_cast<io_uring_socket_send_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + ::io_uring_prep_poll_add(sqe, o->socket_, POLLOUT); + } + else if (o->bufs_.is_single_buffer + && o->bufs_.is_registered_buffer && o->flags_ == 0) + { + ::io_uring_prep_write_fixed(sqe, o->socket_, + o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len, + 0, o->bufs_.registered_id().native_handle()); + } + else + { + ::io_uring_prep_sendmsg(sqe, o->socket_, &o->msghdr_, o->flags_); + } + } + + static bool do_perform(io_uring_operation* base, bool after_completion) + { + ASIO_ASSUME(base != 0); + io_uring_socket_send_op_base* o( + static_cast<io_uring_socket_send_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + if (o->bufs_.is_single_buffer) + { + return socket_ops::non_blocking_send1(o->socket_, + o->bufs_.first(o->buffers_).data(), + o->bufs_.first(o->buffers_).size(), o->flags_, + o->ec_, o->bytes_transferred_); + } + else + { + return socket_ops::non_blocking_send(o->socket_, + o->bufs_.buffers(), o->bufs_.count(), o->flags_, + o->ec_, o->bytes_transferred_); + } + } + + if (o->ec_ && o->ec_ == asio::error::would_block) + { + o->state_ |= socket_ops::internal_non_blocking; + return false; + } + + return after_completion; + } + +private: + socket_type socket_; + socket_ops::state_type state_; + ConstBufferSequence buffers_; + socket_base::message_flags flags_; + buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs_; + msghdr msghdr_; +}; + +template <typename ConstBufferSequence, typename Handler, typename IoExecutor> +class io_uring_socket_send_op + : public io_uring_socket_send_op_base<ConstBufferSequence> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_socket_send_op); + + io_uring_socket_send_op(const asio::error_code& success_ec, + int socket, socket_ops::state_type state, + const ConstBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + : io_uring_socket_send_op_base<ConstBufferSequence>(success_ec, + socket, state, buffers, flags, &io_uring_socket_send_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_socket_send_op* o + (static_cast<io_uring_socket_send_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_SOCKET_SEND_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_socket_sendto_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_socket_sendto_op.hpp new file mode 100644 index 00000000000..1866938a4b4 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_socket_sendto_op.hpp @@ -0,0 +1,194 @@ +// +// detail/io_uring_socket_sendto_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_SOCKET_SENDTO_OP_HPP +#define ASIO_DETAIL_IO_URING_SOCKET_SENDTO_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename ConstBufferSequence, typename Endpoint> +class io_uring_socket_sendto_op_base : public io_uring_operation +{ +public: + io_uring_socket_sendto_op_base(const asio::error_code& success_ec, + socket_type socket, socket_ops::state_type state, + const ConstBufferSequence& buffers, const Endpoint& endpoint, + socket_base::message_flags flags, func_type complete_func) + : io_uring_operation(success_ec, + &io_uring_socket_sendto_op_base::do_prepare, + &io_uring_socket_sendto_op_base::do_perform, complete_func), + socket_(socket), + state_(state), + buffers_(buffers), + destination_(endpoint), + flags_(flags), + bufs_(buffers), + msghdr_() + { + msghdr_.msg_iov = bufs_.buffers(); + msghdr_.msg_iovlen = static_cast<int>(bufs_.count()); + msghdr_.msg_name = static_cast<sockaddr*>( + static_cast<void*>(destination_.data())); + msghdr_.msg_namelen = destination_.size(); + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_socket_sendto_op_base* o( + static_cast<io_uring_socket_sendto_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + ::io_uring_prep_poll_add(sqe, o->socket_, POLLOUT); + } + else + { + ::io_uring_prep_sendmsg(sqe, o->socket_, &o->msghdr_, o->flags_); + } + } + + static bool do_perform(io_uring_operation* base, bool after_completion) + { + ASIO_ASSUME(base != 0); + io_uring_socket_sendto_op_base* o( + static_cast<io_uring_socket_sendto_op_base*>(base)); + + if ((o->state_ & socket_ops::internal_non_blocking) != 0) + { + if (o->bufs_.is_single_buffer) + { + return socket_ops::non_blocking_sendto1(o->socket_, + o->bufs_.first(o->buffers_).data(), + o->bufs_.first(o->buffers_).size(), o->flags_, + o->destination_.data(), o->destination_.size(), + o->ec_, o->bytes_transferred_); + } + else + { + return socket_ops::non_blocking_sendto(o->socket_, + o->bufs_.buffers(), o->bufs_.count(), o->flags_, + o->destination_.data(), o->destination_.size(), + o->ec_, o->bytes_transferred_); + } + } + + if (o->ec_ && o->ec_ == asio::error::would_block) + { + o->state_ |= socket_ops::internal_non_blocking; + return false; + } + + return after_completion; + } + +private: + socket_type socket_; + socket_ops::state_type state_; + ConstBufferSequence buffers_; + Endpoint destination_; + socket_base::message_flags flags_; + buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs_; + msghdr msghdr_; +}; + +template <typename ConstBufferSequence, typename Endpoint, + typename Handler, typename IoExecutor> +class io_uring_socket_sendto_op + : public io_uring_socket_sendto_op_base<ConstBufferSequence, Endpoint> +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_socket_sendto_op); + + io_uring_socket_sendto_op(const asio::error_code& success_ec, + int socket, socket_ops::state_type state, + const ConstBufferSequence& buffers, const Endpoint& endpoint, + socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + : io_uring_socket_sendto_op_base<ConstBufferSequence, Endpoint>( + success_ec, socket, state, buffers, endpoint, flags, + &io_uring_socket_sendto_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_socket_sendto_op* o + (static_cast<io_uring_socket_sendto_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_SOCKET_SENDTO_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_socket_service.hpp b/3rdparty/asio/include/asio/detail/io_uring_socket_service.hpp new file mode 100644 index 00000000000..3daa22ef797 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_socket_service.hpp @@ -0,0 +1,629 @@ +// +// detail/io_uring_socket_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_SOCKET_SERVICE_HPP +#define ASIO_DETAIL_IO_URING_SOCKET_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/buffer.hpp" +#include "asio/error.hpp" +#include "asio/execution_context.hpp" +#include "asio/socket_base.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/memory.hpp" +#include "asio/detail/noncopyable.hpp" +#include "asio/detail/io_uring_null_buffers_op.hpp" +#include "asio/detail/io_uring_service.hpp" +#include "asio/detail/io_uring_socket_accept_op.hpp" +#include "asio/detail/io_uring_socket_connect_op.hpp" +#include "asio/detail/io_uring_socket_recvfrom_op.hpp" +#include "asio/detail/io_uring_socket_sendto_op.hpp" +#include "asio/detail/io_uring_socket_service_base.hpp" +#include "asio/detail/socket_holder.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/socket_types.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Protocol> +class io_uring_socket_service : + public execution_context_service_base<io_uring_socket_service<Protocol>>, + public io_uring_socket_service_base +{ +public: + // The protocol type. + typedef Protocol protocol_type; + + // The endpoint type. + typedef typename Protocol::endpoint endpoint_type; + + // The native type of a socket. + typedef socket_type native_handle_type; + + // The implementation type of the socket. + struct implementation_type : + io_uring_socket_service_base::base_implementation_type + { + // Default constructor. + implementation_type() + : protocol_(endpoint_type().protocol()) + { + } + + // The protocol associated with the socket. + protocol_type protocol_; + }; + + // Constructor. + io_uring_socket_service(execution_context& context) + : execution_context_service_base< + io_uring_socket_service<Protocol>>(context), + io_uring_socket_service_base(context) + { + } + + // Destroy all user-defined handler objects owned by the service. + void shutdown() + { + this->base_shutdown(); + } + + // Move-construct a new socket implementation. + void move_construct(implementation_type& impl, + implementation_type& other_impl) noexcept + { + this->base_move_construct(impl, other_impl); + + impl.protocol_ = other_impl.protocol_; + other_impl.protocol_ = endpoint_type().protocol(); + } + + // Move-assign from another socket implementation. + void move_assign(implementation_type& impl, + io_uring_socket_service_base& other_service, + implementation_type& other_impl) + { + this->base_move_assign(impl, other_service, other_impl); + + impl.protocol_ = other_impl.protocol_; + other_impl.protocol_ = endpoint_type().protocol(); + } + + // Move-construct a new socket implementation from another protocol type. + template <typename Protocol1> + void converting_move_construct(implementation_type& impl, + io_uring_socket_service<Protocol1>&, + typename io_uring_socket_service< + Protocol1>::implementation_type& other_impl) + { + this->base_move_construct(impl, other_impl); + + impl.protocol_ = protocol_type(other_impl.protocol_); + other_impl.protocol_ = typename Protocol1::endpoint().protocol(); + } + + // Open a new socket implementation. + asio::error_code open(implementation_type& impl, + const protocol_type& protocol, asio::error_code& ec) + { + if (!do_open(impl, protocol.family(), + protocol.type(), protocol.protocol(), ec)) + impl.protocol_ = protocol; + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // Assign a native socket to a socket implementation. + asio::error_code assign(implementation_type& impl, + const protocol_type& protocol, const native_handle_type& native_socket, + asio::error_code& ec) + { + if (!do_assign(impl, protocol.type(), native_socket, ec)) + impl.protocol_ = protocol; + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // Get the native socket representation. + native_handle_type native_handle(implementation_type& impl) + { + return impl.socket_; + } + + // Bind the socket to the specified local endpoint. + asio::error_code bind(implementation_type& impl, + const endpoint_type& endpoint, asio::error_code& ec) + { + socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // Set a socket option. + template <typename Option> + asio::error_code set_option(implementation_type& impl, + const Option& option, asio::error_code& ec) + { + socket_ops::setsockopt(impl.socket_, impl.state_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), option.size(impl.protocol_), ec); + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // Set a socket option. + template <typename Option> + asio::error_code get_option(const implementation_type& impl, + Option& option, asio::error_code& ec) const + { + std::size_t size = option.size(impl.protocol_); + socket_ops::getsockopt(impl.socket_, impl.state_, + option.level(impl.protocol_), option.name(impl.protocol_), + option.data(impl.protocol_), &size, ec); + if (!ec) + option.resize(impl.protocol_, size); + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // Get the local endpoint. + endpoint_type local_endpoint(const implementation_type& impl, + asio::error_code& ec) const + { + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) + { + ASIO_ERROR_LOCATION(ec); + return endpoint_type(); + } + endpoint.resize(addr_len); + return endpoint; + } + + // Get the remote endpoint. + endpoint_type remote_endpoint(const implementation_type& impl, + asio::error_code& ec) const + { + endpoint_type endpoint; + std::size_t addr_len = endpoint.capacity(); + if (socket_ops::getpeername(impl.socket_, + endpoint.data(), &addr_len, false, ec)) + { + ASIO_ERROR_LOCATION(ec); + return endpoint_type(); + } + endpoint.resize(addr_len); + return endpoint; + } + + // Disable sends or receives on the socket. + asio::error_code shutdown(base_implementation_type& impl, + socket_base::shutdown_type what, asio::error_code& ec) + { + socket_ops::shutdown(impl.socket_, what, ec); + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // Send a datagram to the specified endpoint. Returns the number of bytes + // sent. + template <typename ConstBufferSequence> + size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + asio::error_code& ec) + { + typedef buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence> bufs_type; + + size_t n; + if (bufs_type::is_single_buffer) + { + n = socket_ops::sync_sendto1(impl.socket_, impl.state_, + bufs_type::first(buffers).data(), + bufs_type::first(buffers).size(), flags, + destination.data(), destination.size(), ec); + } + else + { + bufs_type bufs(buffers); + n = socket_ops::sync_sendto(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, + destination.data(), destination.size(), ec); + } + + ASIO_ERROR_LOCATION(ec); + return n; + } + + // Wait until data can be sent without blocking. + size_t send_to(implementation_type& impl, const null_buffers&, + const endpoint_type&, socket_base::message_flags, + asio::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); + ASIO_ERROR_LOCATION(ec); + return 0; + } + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> + void async_send_to(implementation_type& impl, + const ConstBufferSequence& buffers, + const endpoint_type& destination, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_socket_sendto_op<ConstBufferSequence, + endpoint_type, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, + buffers, destination, flags, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::write_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "socket", &impl, impl.socket_, "async_send_to")); + + start_op(impl, io_uring_service::write_op, p.p, is_continuation, false); + p.v = p.p = 0; + } + + // Start an asynchronous wait until data can be sent without blocking. + template <typename Handler, typename IoExecutor> + void async_send_to(implementation_type& impl, const null_buffers&, + const endpoint_type&, socket_base::message_flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_null_buffers_op<Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, POLLOUT, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::write_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, "socket", + &impl, impl.socket_, "async_send_to(null_buffers)")); + + start_op(impl, io_uring_service::write_op, p.p, is_continuation, false); + p.v = p.p = 0; + } + + // Receive a datagram with the endpoint of the sender. Returns the number of + // bytes received. + template <typename MutableBufferSequence> + size_t receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + asio::error_code& ec) + { + typedef buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs_type; + + std::size_t addr_len = sender_endpoint.capacity(); + std::size_t n; + if (bufs_type::is_single_buffer) + { + n = socket_ops::sync_recvfrom1(impl.socket_, impl.state_, + bufs_type::first(buffers).data(), bufs_type::first(buffers).size(), + flags, sender_endpoint.data(), &addr_len, ec); + } + else + { + bufs_type bufs(buffers); + n = socket_ops::sync_recvfrom(impl.socket_, impl.state_, bufs.buffers(), + bufs.count(), flags, sender_endpoint.data(), &addr_len, ec); + } + + if (!ec) + sender_endpoint.resize(addr_len); + + ASIO_ERROR_LOCATION(ec); + return n; + } + + // Wait until data can be received without blocking. + size_t receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags, + asio::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + ASIO_ERROR_LOCATION(ec); + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received and + // the sender_endpoint object must both be valid for the lifetime of the + // asynchronous operation. + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> + void async_receive_from(implementation_type& impl, + const MutableBufferSequence& buffers, endpoint_type& sender_endpoint, + socket_base::message_flags flags, Handler& handler, + const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + int op_type = (flags & socket_base::message_out_of_band) + ? io_uring_service::except_op : io_uring_service::read_op; + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_socket_recvfrom_op<MutableBufferSequence, + endpoint_type, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, + buffers, sender_endpoint, flags, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>( + &io_uring_service_, &impl.io_object_data_, op_type); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "socket", &impl, impl.socket_, "async_receive_from")); + + start_op(impl, op_type, p.p, is_continuation, false); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template <typename Handler, typename IoExecutor> + void async_receive_from(implementation_type& impl, const null_buffers&, + endpoint_type& sender_endpoint, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + int op_type; + int poll_flags; + if ((flags & socket_base::message_out_of_band) != 0) + { + op_type = io_uring_service::except_op; + poll_flags = POLLPRI; + } + else + { + op_type = io_uring_service::read_op; + poll_flags = POLLIN; + } + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_null_buffers_op<Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, poll_flags, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>( + &io_uring_service_, &impl.io_object_data_, op_type); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_from(null_buffers)")); + + // Reset endpoint since it can be given no sensible value at this time. + sender_endpoint = endpoint_type(); + + start_op(impl, op_type, p.p, is_continuation, false); + p.v = p.p = 0; + } + + // Accept a new connection. + template <typename Socket> + asio::error_code accept(implementation_type& impl, + Socket& peer, endpoint_type* peer_endpoint, asio::error_code& ec) + { + // We cannot accept a socket that is already open. + if (peer.is_open()) + { + ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); + return ec; + } + + std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0; + socket_holder new_socket(socket_ops::sync_accept(impl.socket_, + impl.state_, peer_endpoint ? peer_endpoint->data() : 0, + peer_endpoint ? &addr_len : 0, ec)); + + // On success, assign new connection to peer socket object. + if (new_socket.get() != invalid_socket) + { + if (peer_endpoint) + peer_endpoint->resize(addr_len); + peer.assign(impl.protocol_, new_socket.get(), ec); + if (!ec) + new_socket.release(); + } + + ASIO_ERROR_LOCATION(ec); + return ec; + } + + // Start an asynchronous accept. The peer and peer_endpoint objects must be + // valid until the accept's handler is invoked. + template <typename Socket, typename Handler, typename IoExecutor> + void async_accept(implementation_type& impl, Socket& peer, + endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_socket_accept_op<Socket, Protocol, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, + peer, impl.protocol_, peer_endpoint, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected() && !peer.is_open()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::read_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "socket", &impl, impl.socket_, "async_accept")); + + start_accept_op(impl, p.p, is_continuation, peer.is_open()); + p.v = p.p = 0; + } + + // Start an asynchronous accept. The peer_endpoint object must be valid until + // the accept's handler is invoked. + template <typename PeerIoExecutor, typename Handler, typename IoExecutor> + void async_move_accept(implementation_type& impl, + const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_socket_move_accept_op<Protocol, + PeerIoExecutor, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, peer_io_ex, impl.socket_, + impl.state_, impl.protocol_, peer_endpoint, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::read_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "socket", &impl, impl.socket_, "async_accept")); + + start_accept_op(impl, p.p, is_continuation, false); + p.v = p.p = 0; + } + + // Connect the socket to the specified endpoint. + asio::error_code connect(implementation_type& impl, + const endpoint_type& peer_endpoint, asio::error_code& ec) + { + socket_ops::sync_connect(impl.socket_, + peer_endpoint.data(), peer_endpoint.size(), ec); + return ec; + } + + // Start an asynchronous connect. + template <typename Handler, typename IoExecutor> + void async_connect(implementation_type& impl, + const endpoint_type& peer_endpoint, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_socket_connect_op<Protocol, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, + peer_endpoint, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::write_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "socket", &impl, impl.socket_, "async_connect")); + + start_op(impl, io_uring_service::write_op, p.p, is_continuation, false); + p.v = p.p = 0; + } +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_SOCKET_SERVICE_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_socket_service_base.hpp b/3rdparty/asio/include/asio/detail/io_uring_socket_service_base.hpp new file mode 100644 index 00000000000..99b075c9fe5 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_socket_service_base.hpp @@ -0,0 +1,663 @@ +// +// detail/io_uring_socket_service_base.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_SOCKET_SERVICE_BASE_HPP +#define ASIO_DETAIL_IO_URING_SOCKET_SERVICE_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IO_URING) + +#include "asio/associated_cancellation_slot.hpp" +#include "asio/buffer.hpp" +#include "asio/cancellation_type.hpp" +#include "asio/error.hpp" +#include "asio/execution_context.hpp" +#include "asio/socket_base.hpp" +#include "asio/detail/buffer_sequence_adapter.hpp" +#include "asio/detail/memory.hpp" +#include "asio/detail/io_uring_null_buffers_op.hpp" +#include "asio/detail/io_uring_service.hpp" +#include "asio/detail/io_uring_socket_recv_op.hpp" +#include "asio/detail/io_uring_socket_recvmsg_op.hpp" +#include "asio/detail/io_uring_socket_send_op.hpp" +#include "asio/detail/io_uring_wait_op.hpp" +#include "asio/detail/socket_holder.hpp" +#include "asio/detail/socket_ops.hpp" +#include "asio/detail/socket_types.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class io_uring_socket_service_base +{ +public: + // The native type of a socket. + typedef socket_type native_handle_type; + + // The implementation type of the socket. + struct base_implementation_type + { + // The native socket representation. + socket_type socket_; + + // The current state of the socket. + socket_ops::state_type state_; + + // Per I/O object data used by the io_uring_service. + io_uring_service::per_io_object_data io_object_data_; + }; + + // Constructor. + ASIO_DECL io_uring_socket_service_base(execution_context& context); + + // Destroy all user-defined handler objects owned by the service. + ASIO_DECL void base_shutdown(); + + // Construct a new socket implementation. + ASIO_DECL void construct(base_implementation_type& impl); + + // Move-construct a new socket implementation. + ASIO_DECL void base_move_construct(base_implementation_type& impl, + base_implementation_type& other_impl) noexcept; + + // Move-assign from another socket implementation. + ASIO_DECL void base_move_assign(base_implementation_type& impl, + io_uring_socket_service_base& other_service, + base_implementation_type& other_impl); + + // Destroy a socket implementation. + ASIO_DECL void destroy(base_implementation_type& impl); + + // Determine whether the socket is open. + bool is_open(const base_implementation_type& impl) const + { + return impl.socket_ != invalid_socket; + } + + // Destroy a socket implementation. + ASIO_DECL asio::error_code close( + base_implementation_type& impl, asio::error_code& ec); + + // Release ownership of the socket. + ASIO_DECL socket_type release( + base_implementation_type& impl, asio::error_code& ec); + + // Get the native socket representation. + native_handle_type native_handle(base_implementation_type& impl) + { + return impl.socket_; + } + + // Cancel all operations associated with the socket. + ASIO_DECL asio::error_code cancel( + base_implementation_type& impl, asio::error_code& ec); + + // Determine whether the socket is at the out-of-band data mark. + bool at_mark(const base_implementation_type& impl, + asio::error_code& ec) const + { + return socket_ops::sockatmark(impl.socket_, ec); + } + + // Determine the number of bytes available for reading. + std::size_t available(const base_implementation_type& impl, + asio::error_code& ec) const + { + return socket_ops::available(impl.socket_, ec); + } + + // Place the socket into the state where it will listen for new connections. + asio::error_code listen(base_implementation_type& impl, + int backlog, asio::error_code& ec) + { + socket_ops::listen(impl.socket_, backlog, ec); + return ec; + } + + // Perform an IO control command on the socket. + template <typename IO_Control_Command> + asio::error_code io_control(base_implementation_type& impl, + IO_Control_Command& command, asio::error_code& ec) + { + socket_ops::ioctl(impl.socket_, impl.state_, command.name(), + static_cast<ioctl_arg_type*>(command.data()), ec); + return ec; + } + + // Gets the non-blocking mode of the socket. + bool non_blocking(const base_implementation_type& impl) const + { + return (impl.state_ & socket_ops::user_set_non_blocking) != 0; + } + + // Sets the non-blocking mode of the socket. + asio::error_code non_blocking(base_implementation_type& impl, + bool mode, asio::error_code& ec) + { + socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec); + return ec; + } + + // Gets the non-blocking mode of the native socket implementation. + bool native_non_blocking(const base_implementation_type& impl) const + { + return (impl.state_ & socket_ops::internal_non_blocking) != 0; + } + + // Sets the non-blocking mode of the native socket implementation. + asio::error_code native_non_blocking(base_implementation_type& impl, + bool mode, asio::error_code& ec) + { + socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec); + return ec; + } + + // Wait for the socket to become ready to read, ready to write, or to have + // pending error conditions. + asio::error_code wait(base_implementation_type& impl, + socket_base::wait_type w, asio::error_code& ec) + { + switch (w) + { + case socket_base::wait_read: + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + break; + case socket_base::wait_write: + socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); + break; + case socket_base::wait_error: + socket_ops::poll_error(impl.socket_, impl.state_, -1, ec); + break; + default: + ec = asio::error::invalid_argument; + break; + } + + return ec; + } + + // Asynchronously wait for the socket to become ready to read, ready to + // write, or to have pending error conditions. + template <typename Handler, typename IoExecutor> + void async_wait(base_implementation_type& impl, + socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + int op_type; + int poll_flags; + switch (w) + { + case socket_base::wait_read: + op_type = io_uring_service::read_op; + poll_flags = POLLIN; + break; + case socket_base::wait_write: + op_type = io_uring_service::write_op; + poll_flags = POLLOUT; + break; + case socket_base::wait_error: + op_type = io_uring_service::except_op; + poll_flags = POLLPRI | POLLERR | POLLHUP; + break; + default: + op_type = -1; + poll_flags = -1; + return; + } + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_wait_op<Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, + poll_flags, handler, io_ex); + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "socket", &impl, impl.socket_, "async_wait")); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>( + &io_uring_service_, &impl.io_object_data_, op_type); + } + + start_op(impl, op_type, p.p, is_continuation, op_type == -1); + p.v = p.p = 0; + } + + // Send the given data to the peer. + template <typename ConstBufferSequence> + size_t send(base_implementation_type& impl, + const ConstBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + typedef buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence> bufs_type; + + if (bufs_type::is_single_buffer) + { + return socket_ops::sync_send1(impl.socket_, + impl.state_, bufs_type::first(buffers).data(), + bufs_type::first(buffers).size(), flags, ec); + } + else + { + bufs_type bufs(buffers); + return socket_ops::sync_send(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); + } + } + + // Wait until data can be sent without blocking. + size_t send(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, asio::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); + + return 0; + } + + // Start an asynchronous send. The data being sent must be valid for the + // lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> + void async_send(base_implementation_type& impl, + const ConstBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_socket_send_op< + ConstBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, + impl.state_, buffers, flags, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::write_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "socket", &impl, impl.socket_, "async_send")); + + start_op(impl, io_uring_service::write_op, p.p, is_continuation, + ((impl.state_ & socket_ops::stream_oriented) + && buffer_sequence_adapter<asio::const_buffer, + ConstBufferSequence>::all_empty(buffers))); + p.v = p.p = 0; + } + + // Start an asynchronous wait until data can be sent without blocking. + template <typename Handler, typename IoExecutor> + void async_send(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_null_buffers_op<Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, POLLOUT, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_, + &impl.io_object_data_, io_uring_service::write_op); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "socket", &impl, impl.socket_, "async_send(null_buffers)")); + + start_op(impl, io_uring_service::write_op, p.p, is_continuation, false); + p.v = p.p = 0; + } + + // Receive some data from the peer. Returns the number of bytes received. + template <typename MutableBufferSequence> + size_t receive(base_implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags flags, asio::error_code& ec) + { + typedef buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs_type; + + if (bufs_type::is_single_buffer) + { + return socket_ops::sync_recv1(impl.socket_, + impl.state_, bufs_type::first(buffers).data(), + bufs_type::first(buffers).size(), flags, ec); + } + else + { + bufs_type bufs(buffers); + return socket_ops::sync_recv(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec); + } + } + + // Wait until data can be received without blocking. + size_t receive(base_implementation_type& impl, const null_buffers&, + socket_base::message_flags, asio::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> + void async_receive(base_implementation_type& impl, + const MutableBufferSequence& buffers, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + int op_type = (flags & socket_base::message_out_of_band) + ? io_uring_service::except_op : io_uring_service::read_op; + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_socket_recv_op< + MutableBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, + impl.state_, buffers, flags, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>( + &io_uring_service_, &impl.io_object_data_, op_type); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "socket", &impl, impl.socket_, "async_receive")); + + start_op(impl, op_type, p.p, is_continuation, + ((impl.state_ & socket_ops::stream_oriented) + && buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence>::all_empty(buffers))); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template <typename Handler, typename IoExecutor> + void async_receive(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags flags, + Handler& handler, const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + int op_type; + int poll_flags; + if ((flags & socket_base::message_out_of_band) != 0) + { + op_type = io_uring_service::except_op; + poll_flags = POLLPRI; + } + else + { + op_type = io_uring_service::read_op; + poll_flags = POLLIN; + } + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_null_buffers_op<Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, poll_flags, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>( + &io_uring_service_, &impl.io_object_data_, op_type); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "socket", &impl, impl.socket_, "async_receive(null_buffers)")); + + start_op(impl, op_type, p.p, is_continuation, false); + p.v = p.p = 0; + } + + // Receive some data with associated flags. Returns the number of bytes + // received. + template <typename MutableBufferSequence> + size_t receive_with_flags(base_implementation_type& impl, + const MutableBufferSequence& buffers, + socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, asio::error_code& ec) + { + buffer_sequence_adapter<asio::mutable_buffer, + MutableBufferSequence> bufs(buffers); + + return socket_ops::sync_recvmsg(impl.socket_, impl.state_, + bufs.buffers(), bufs.count(), in_flags, out_flags, ec); + } + + // Wait until data can be received without blocking. + size_t receive_with_flags(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags, + socket_base::message_flags& out_flags, asio::error_code& ec) + { + // Wait for socket to become ready. + socket_ops::poll_read(impl.socket_, impl.state_, -1, ec); + + // Clear out_flags, since we cannot give it any other sensible value when + // performing a null_buffers operation. + out_flags = 0; + + return 0; + } + + // Start an asynchronous receive. The buffer for the data being received + // must be valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> + void async_receive_with_flags(base_implementation_type& impl, + const MutableBufferSequence& buffers, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + int op_type = (in_flags & socket_base::message_out_of_band) + ? io_uring_service::except_op : io_uring_service::read_op; + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_socket_recvmsg_op< + MutableBufferSequence, Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_, + buffers, in_flags, out_flags, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>( + &io_uring_service_, &impl.io_object_data_, op_type); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, + "socket", &impl, impl.socket_, "async_receive_with_flags")); + + start_op(impl, op_type, p.p, is_continuation, false); + p.v = p.p = 0; + } + + // Wait until data can be received without blocking. + template <typename Handler, typename IoExecutor> + void async_receive_with_flags(base_implementation_type& impl, + const null_buffers&, socket_base::message_flags in_flags, + socket_base::message_flags& out_flags, Handler& handler, + const IoExecutor& io_ex) + { + bool is_continuation = + asio_handler_cont_helpers::is_continuation(handler); + + int op_type; + int poll_flags; + if ((in_flags & socket_base::message_out_of_band) != 0) + { + op_type = io_uring_service::except_op; + poll_flags = POLLPRI; + } + else + { + op_type = io_uring_service::read_op; + poll_flags = POLLIN; + } + + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef io_uring_null_buffers_op<Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(success_ec_, impl.socket_, poll_flags, handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<io_uring_op_cancellation>( + &io_uring_service_, &impl.io_object_data_, op_type); + } + + ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, "socket", + &impl, impl.socket_, "async_receive_with_flags(null_buffers)")); + + // Clear out_flags, since we cannot give it any other sensible value when + // performing a null_buffers operation. + out_flags = 0; + + start_op(impl, op_type, p.p, is_continuation, false); + p.v = p.p = 0; + } + +protected: + // Open a new socket implementation. + ASIO_DECL asio::error_code do_open( + base_implementation_type& impl, int af, + int type, int protocol, asio::error_code& ec); + + // Assign a native socket to a socket implementation. + ASIO_DECL asio::error_code do_assign( + base_implementation_type& impl, int type, + const native_handle_type& native_socket, asio::error_code& ec); + + // Start the asynchronous read or write operation. + ASIO_DECL void start_op(base_implementation_type& impl, int op_type, + io_uring_operation* op, bool is_continuation, bool noop); + + // Start the asynchronous accept operation. + ASIO_DECL void start_accept_op(base_implementation_type& impl, + io_uring_operation* op, bool is_continuation, bool peer_is_open); + + // Helper class used to implement per-operation cancellation + class io_uring_op_cancellation + { + public: + io_uring_op_cancellation(io_uring_service* s, + io_uring_service::per_io_object_data* p, int o) + : io_uring_service_(s), + io_object_data_(p), + op_type_(o) + { + } + + void operator()(cancellation_type_t type) + { + if (!!(type & + (cancellation_type::terminal + | cancellation_type::partial + | cancellation_type::total))) + { + io_uring_service_->cancel_ops_by_key(*io_object_data_, op_type_, this); + } + } + + private: + io_uring_service* io_uring_service_; + io_uring_service::per_io_object_data* io_object_data_; + int op_type_; + }; + + // The io_uring_service that performs event demultiplexing for the service. + io_uring_service& io_uring_service_; + + // Cached success value to avoid accessing category singleton. + const asio::error_code success_ec_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#if defined(ASIO_HEADER_ONLY) +# include "asio/detail/impl/io_uring_socket_service_base.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +#endif // defined(ASIO_HAS_IO_URING) + +#endif // ASIO_DETAIL_IO_URING_SOCKET_SERVICE_BASE_HPP diff --git a/3rdparty/asio/include/asio/detail/io_uring_wait_op.hpp b/3rdparty/asio/include/asio/detail/io_uring_wait_op.hpp new file mode 100644 index 00000000000..4dec72ce42c --- /dev/null +++ b/3rdparty/asio/include/asio/detail/io_uring_wait_op.hpp @@ -0,0 +1,112 @@ +// +// detail/io_uring_wait_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_IO_URING_WAIT_OP_HPP +#define ASIO_DETAIL_IO_URING_WAIT_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/fenced_block.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/handler_work.hpp" +#include "asio/detail/io_uring_operation.hpp" +#include "asio/detail/memory.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +template <typename Handler, typename IoExecutor> +class io_uring_wait_op : public io_uring_operation +{ +public: + ASIO_DEFINE_HANDLER_PTR(io_uring_wait_op); + + io_uring_wait_op(const asio::error_code& success_ec, int descriptor, + int poll_flags, Handler& handler, const IoExecutor& io_ex) + : io_uring_operation(success_ec, &io_uring_wait_op::do_prepare, + &io_uring_wait_op::do_perform, &io_uring_wait_op::do_complete), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex), + descriptor_(descriptor), + poll_flags_(poll_flags) + { + } + + static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe) + { + ASIO_ASSUME(base != 0); + io_uring_wait_op* o(static_cast<io_uring_wait_op*>(base)); + + ::io_uring_prep_poll_add(sqe, o->descriptor_, o->poll_flags_); + } + + static bool do_perform(io_uring_operation*, bool after_completion) + { + return after_completion; + } + + static void do_complete(void* owner, operation* base, + const asio::error_code& /*ec*/, + std::size_t /*bytes_transferred*/) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + io_uring_wait_op* o(static_cast<io_uring_wait_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder1<Handler, asio::error_code> + handler(o->handler_, o->ec_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Make the upcall if required. + if (owner) + { + fenced_block b(fenced_block::half); + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + handler_work<Handler, IoExecutor> work_; + int descriptor_; + int poll_flags_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_IO_URING_WAIT_OP_HPP diff --git a/3rdparty/asio/include/asio/detail/is_buffer_sequence.hpp b/3rdparty/asio/include/asio/detail/is_buffer_sequence.hpp index e3d8de3d8f6..c64e7b16824 100644 --- a/3rdparty/asio/include/asio/detail/is_buffer_sequence.hpp +++ b/3rdparty/asio/include/asio/detail/is_buffer_sequence.hpp @@ -2,7 +2,7 @@ // detail/is_buffer_sequence.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -24,6 +24,8 @@ namespace asio { class mutable_buffer; class const_buffer; +class mutable_registered_buffer; +class const_registered_buffer; namespace detail { @@ -53,53 +55,23 @@ struct buffer_sequence_memfns_check { }; -#if defined(ASIO_HAS_DECLTYPE) - template <typename> char buffer_sequence_begin_helper(...); template <typename T> char (&buffer_sequence_begin_helper(T* t, - typename enable_if<!is_same< + enable_if_t<!is_same< decltype(asio::buffer_sequence_begin(*t)), - void>::value>::type*))[2]; - -#else // defined(ASIO_HAS_DECLTYPE) - -template <typename> -char (&buffer_sequence_begin_helper(...))[2]; - -template <typename T> -char buffer_sequence_begin_helper(T* t, - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived<T>::begin>*); - -#endif // defined(ASIO_HAS_DECLTYPE) - -#if defined(ASIO_HAS_DECLTYPE) + void>::value>*))[2]; template <typename> char buffer_sequence_end_helper(...); template <typename T> char (&buffer_sequence_end_helper(T* t, - typename enable_if<!is_same< + enable_if_t<!is_same< decltype(asio::buffer_sequence_end(*t)), - void>::value>::type*))[2]; - -#else // defined(ASIO_HAS_DECLTYPE) - -template <typename> -char (&buffer_sequence_end_helper(...))[2]; - -template <typename T> -char buffer_sequence_end_helper(T* t, - buffer_sequence_memfns_check< - void (buffer_sequence_memfns_base::*)(), - &buffer_sequence_memfns_derived<T>::end>*); - -#endif // defined(ASIO_HAS_DECLTYPE) + void>::value>*))[2]; template <typename> char (&size_memfn_helper(...))[2]; @@ -185,23 +157,11 @@ char shrink_memfn_helper( template <typename, typename> char (&buffer_sequence_element_type_helper(...))[2]; -#if defined(ASIO_HAS_DECLTYPE) - template <typename T, typename Buffer> char buffer_sequence_element_type_helper(T* t, - typename enable_if<is_convertible< + enable_if_t<is_convertible< decltype(*asio::buffer_sequence_begin(*t)), - Buffer>::value>::type*); - -#else // defined(ASIO_HAS_DECLTYPE) - -template <typename T, typename Buffer> -char buffer_sequence_element_type_helper( - typename T::const_iterator*, - typename enable_if<is_convertible< - typename T::value_type, Buffer>::value>::type*); - -#endif // defined(ASIO_HAS_DECLTYPE) + Buffer>::value>*); template <typename> char (&const_buffers_type_typedef_helper(...))[2]; @@ -258,6 +218,30 @@ struct is_buffer_sequence<const_buffer, mutable_buffer> { }; +template <> +struct is_buffer_sequence<mutable_registered_buffer, mutable_buffer> + : true_type +{ +}; + +template <> +struct is_buffer_sequence<mutable_registered_buffer, const_buffer> + : true_type +{ +}; + +template <> +struct is_buffer_sequence<const_registered_buffer, const_buffer> + : true_type +{ +}; + +template <> +struct is_buffer_sequence<const_registered_buffer, mutable_buffer> + : false_type +{ +}; + template <typename T> struct is_dynamic_buffer_class_v1 : integral_constant<bool, diff --git a/3rdparty/asio/include/asio/detail/is_executor.hpp b/3rdparty/asio/include/asio/detail/is_executor.hpp index a099eecff90..2636f9c66f3 100644 --- a/3rdparty/asio/include/asio/detail/is_executor.hpp +++ b/3rdparty/asio/include/asio/detail/is_executor.hpp @@ -2,7 +2,7 @@ // detail/is_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/keyword_tss_ptr.hpp b/3rdparty/asio/include/asio/detail/keyword_tss_ptr.hpp index 9378af3d45c..2e42df8b358 100644 --- a/3rdparty/asio/include/asio/detail/keyword_tss_ptr.hpp +++ b/3rdparty/asio/include/asio/detail/keyword_tss_ptr.hpp @@ -2,7 +2,7 @@ // detail/keyword_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/kqueue_reactor.hpp b/3rdparty/asio/include/asio/detail/kqueue_reactor.hpp index 645f1221cd8..f034410d6d5 100644 --- a/3rdparty/asio/include/asio/detail/kqueue_reactor.hpp +++ b/3rdparty/asio/include/asio/detail/kqueue_reactor.hpp @@ -2,7 +2,7 @@ // detail/kqueue_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -29,6 +29,7 @@ #include "asio/detail/object_pool.hpp" #include "asio/detail/op_queue.hpp" #include "asio/detail/reactor_op.hpp" +#include "asio/detail/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp" @@ -50,7 +51,8 @@ namespace detail { class scheduler; class kqueue_reactor - : public execution_context_service_base<kqueue_reactor> + : public execution_context_service_base<kqueue_reactor>, + public scheduler_task { private: // The mutex type used by this reactor. @@ -114,13 +116,30 @@ public: per_descriptor_data& source_descriptor_data); // Post a reactor operation for immediate completion. - void post_immediate_completion(operation* op, bool is_continuation); + void post_immediate_completion(operation* op, bool is_continuation) const; + + // Post a reactor operation for immediate completion. + ASIO_DECL static void call_post_immediate_completion( + operation* op, bool is_continuation, const void* self); // Start a new operation. The reactor operation will be performed when the // given descriptor is flagged as ready, or an error has occurred. ASIO_DECL void start_op(int op_type, socket_type descriptor, per_descriptor_data& descriptor_data, reactor_op* op, - bool is_continuation, bool allow_speculative); + bool is_continuation, bool allow_speculative, + void (*on_immediate)(operation*, bool, const void*), + const void* immediate_arg); + + // Start a new operation. The reactor operation will be performed when the + // given descriptor is flagged as ready, or an error has occurred. + void start_op(int op_type, socket_type descriptor, + per_descriptor_data& descriptor_data, reactor_op* op, + bool is_continuation, bool allow_speculative) + { + start_op(op_type, descriptor, descriptor_data, + op, is_continuation, allow_speculative, + &kqueue_reactor::call_post_immediate_completion, this); + } // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the diff --git a/3rdparty/asio/include/asio/detail/limits.hpp b/3rdparty/asio/include/asio/detail/limits.hpp index d32470d2d35..323af22b300 100644 --- a/3rdparty/asio/include/asio/detail/limits.hpp +++ b/3rdparty/asio/include/asio/detail/limits.hpp @@ -16,11 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_BOOST_LIMITS) -# include <boost/limits.hpp> -#else // defined(ASIO_HAS_BOOST_LIMITS) -# include <limits> -#endif // defined(ASIO_HAS_BOOST_LIMITS) +#include <limits> #endif // ASIO_DETAIL_LIMITS_HPP diff --git a/3rdparty/asio/include/asio/detail/local_free_on_block_exit.hpp b/3rdparty/asio/include/asio/detail/local_free_on_block_exit.hpp index 9ca4b3f68ab..212f9c1bcd2 100644 --- a/3rdparty/asio/include/asio/detail/local_free_on_block_exit.hpp +++ b/3rdparty/asio/include/asio/detail/local_free_on_block_exit.hpp @@ -2,7 +2,7 @@ // detail/local_free_on_block_exit.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/macos_fenced_block.hpp b/3rdparty/asio/include/asio/detail/macos_fenced_block.hpp deleted file mode 100644 index 54768e51f51..00000000000 --- a/3rdparty/asio/include/asio/detail/macos_fenced_block.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// detail/macos_fenced_block.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP -#define ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#if defined(__MACH__) && defined(__APPLE__) - -#include <libkern/OSAtomic.h> -#include "asio/detail/noncopyable.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class macos_fenced_block - : private noncopyable -{ -public: - enum half_t { half }; - enum full_t { full }; - - // Constructor for a half fenced block. - explicit macos_fenced_block(half_t) - { - } - - // Constructor for a full fenced block. - explicit macos_fenced_block(full_t) - { - OSMemoryBarrier(); - } - - // Destructor. - ~macos_fenced_block() - { - OSMemoryBarrier(); - } -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // defined(__MACH__) && defined(__APPLE__) - -#endif // ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP diff --git a/3rdparty/asio/include/asio/detail/memory.hpp b/3rdparty/asio/include/asio/detail/memory.hpp index d61dfa5788c..173e49fe065 100644 --- a/3rdparty/asio/include/asio/detail/memory.hpp +++ b/3rdparty/asio/include/asio/detail/memory.hpp @@ -2,7 +2,7 @@ // detail/memory.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,48 +20,45 @@ #include <cstdlib> #include <memory> #include <new> +#include "asio/detail/cstdint.hpp" #include "asio/detail/throw_exception.hpp" -#if !defined(ASIO_HAS_STD_SHARED_PTR) -# include <boost/make_shared.hpp> -# include <boost/shared_ptr.hpp> -# include <boost/weak_ptr.hpp> -#endif // !defined(ASIO_HAS_STD_SHARED_PTR) - -#if !defined(ASIO_HAS_STD_ADDRESSOF) -# include <boost/utility/addressof.hpp> -#endif // !defined(ASIO_HAS_STD_ADDRESSOF) - #if !defined(ASIO_HAS_STD_ALIGNED_ALLOC) \ - && defined(ASIO_HAS_BOOST_ALIGN) \ - && defined(ASIO_HAS_ALIGNOF) + && defined(ASIO_HAS_BOOST_ALIGN) # include <boost/align/aligned_alloc.hpp> #endif // !defined(ASIO_HAS_STD_ALIGNED_ALLOC) // && defined(ASIO_HAS_BOOST_ALIGN) - // && defined(ASIO_HAS_ALIGNOF) namespace asio { namespace detail { -#if defined(ASIO_HAS_STD_SHARED_PTR) +using std::allocate_shared; using std::make_shared; using std::shared_ptr; using std::weak_ptr; -#else // defined(ASIO_HAS_STD_SHARED_PTR) -using boost::make_shared; -using boost::shared_ptr; -using boost::weak_ptr; -#endif // defined(ASIO_HAS_STD_SHARED_PTR) - -#if defined(ASIO_HAS_STD_ADDRESSOF) using std::addressof; -#else // defined(ASIO_HAS_STD_ADDRESSOF) -using boost::addressof; -#endif // defined(ASIO_HAS_STD_ADDRESSOF) + +#if defined(ASIO_HAS_STD_TO_ADDRESS) +using std::to_address; +#else // defined(ASIO_HAS_STD_TO_ADDRESS) +template <typename T> +inline T* to_address(T* p) { return p; } +template <typename T> +inline const T* to_address(const T* p) { return p; } +template <typename T> +inline volatile T* to_address(volatile T* p) { return p; } +template <typename T> +inline const volatile T* to_address(const volatile T* p) { return p; } +#endif // defined(ASIO_HAS_STD_TO_ADDRESS) + +inline void* align(std::size_t alignment, + std::size_t size, void*& ptr, std::size_t& space) +{ + return std::align(alignment, size, ptr, space); +} } // namespace detail -#if defined(ASIO_HAS_CXX11_ALLOCATORS) using std::allocator_arg_t; # define ASIO_USES_ALLOCATOR(t) \ namespace std { \ @@ -72,17 +69,11 @@ using std::allocator_arg_t; # define ASIO_REBIND_ALLOC(alloc, t) \ typename std::allocator_traits<alloc>::template rebind_alloc<t> /**/ -#else // defined(ASIO_HAS_CXX11_ALLOCATORS) -struct allocator_arg_t {}; -# define ASIO_USES_ALLOCATOR(t) -# define ASIO_REBIND_ALLOC(alloc, t) \ - typename alloc::template rebind<t>::other - /**/ -#endif // defined(ASIO_HAS_CXX11_ALLOCATORS) inline void* aligned_new(std::size_t align, std::size_t size) { -#if defined(ASIO_HAS_STD_ALIGNED_ALLOC) && defined(ASIO_HAS_ALIGNOF) +#if defined(ASIO_HAS_STD_ALIGNED_ALLOC) + align = (align < ASIO_DEFAULT_ALIGN) ? ASIO_DEFAULT_ALIGN : align; size = (size % align == 0) ? size : size + (align - size % align); void* ptr = std::aligned_alloc(align, size); if (!ptr) @@ -91,7 +82,8 @@ inline void* aligned_new(std::size_t align, std::size_t size) asio::detail::throw_exception(ex); } return ptr; -#elif defined(ASIO_HAS_BOOST_ALIGN) && defined(ASIO_HAS_ALIGNOF) +#elif defined(ASIO_HAS_BOOST_ALIGN) + align = (align < ASIO_DEFAULT_ALIGN) ? ASIO_DEFAULT_ALIGN : align; size = (size % align == 0) ? size : size + (align - size % align); void* ptr = boost::alignment::aligned_alloc(align, size); if (!ptr) @@ -100,7 +92,8 @@ inline void* aligned_new(std::size_t align, std::size_t size) asio::detail::throw_exception(ex); } return ptr; -#elif defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF) +#elif defined(ASIO_MSVC) + align = (align < ASIO_DEFAULT_ALIGN) ? ASIO_DEFAULT_ALIGN : align; size = (size % align == 0) ? size : size + (align - size % align); void* ptr = _aligned_malloc(size, align); if (!ptr) @@ -109,23 +102,23 @@ inline void* aligned_new(std::size_t align, std::size_t size) asio::detail::throw_exception(ex); } return ptr; -#else // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF) +#else // defined(ASIO_MSVC) (void)align; return ::operator new(size); -#endif // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF) +#endif // defined(ASIO_MSVC) } inline void aligned_delete(void* ptr) { -#if defined(ASIO_HAS_STD_ALIGNED_ALLOC) && defined(ASIO_HAS_ALIGNOF) +#if defined(ASIO_HAS_STD_ALIGNED_ALLOC) std::free(ptr); -#elif defined(ASIO_HAS_BOOST_ALIGN) && defined(ASIO_HAS_ALIGNOF) +#elif defined(ASIO_HAS_BOOST_ALIGN) boost::alignment::aligned_free(ptr); -#elif defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF) +#elif defined(ASIO_MSVC) _aligned_free(ptr); -#else // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF) +#else // defined(ASIO_MSVC) ::operator delete(ptr); -#endif // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF) +#endif // defined(ASIO_MSVC) } } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/mutex.hpp b/3rdparty/asio/include/asio/detail/mutex.hpp index 283fade654d..e701c238296 100644 --- a/3rdparty/asio/include/asio/detail/mutex.hpp +++ b/3rdparty/asio/include/asio/detail/mutex.hpp @@ -2,7 +2,7 @@ // detail/mutex.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,10 +23,8 @@ # include "asio/detail/win_mutex.hpp" #elif defined(ASIO_HAS_PTHREADS) # include "asio/detail/posix_mutex.hpp" -#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) -# include "asio/detail/std_mutex.hpp" #else -# error Only Windows, POSIX and std::mutex are supported! +# include "asio/detail/std_mutex.hpp" #endif namespace asio { @@ -38,7 +36,7 @@ typedef null_mutex mutex; typedef win_mutex mutex; #elif defined(ASIO_HAS_PTHREADS) typedef posix_mutex mutex; -#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) +#else typedef std_mutex mutex; #endif diff --git a/3rdparty/asio/include/asio/detail/non_const_lvalue.hpp b/3rdparty/asio/include/asio/detail/non_const_lvalue.hpp index 49603656850..940bf251b71 100644 --- a/3rdparty/asio/include/asio/detail/non_const_lvalue.hpp +++ b/3rdparty/asio/include/asio/detail/non_const_lvalue.hpp @@ -2,7 +2,7 @@ // detail/non_const_lvalue.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -26,24 +26,13 @@ namespace detail { template <typename T> struct non_const_lvalue { -#if defined(ASIO_HAS_MOVE) explicit non_const_lvalue(T& t) - : value(static_cast<typename conditional< - is_same<T, typename decay<T>::type>::value, - typename decay<T>::type&, T&&>::type>(t)) + : value(static_cast<conditional_t< + is_same<T, decay_t<T>>::value, decay_t<T>&, T&&>>(t)) { } - typename conditional<is_same<T, typename decay<T>::type>::value, - typename decay<T>::type&, typename decay<T>::type>::type value; -#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - explicit non_const_lvalue(const typename decay<T>::type& t) - : value(t) - { - } - - typename decay<T>::type value; -#endif // defined(ASIO_HAS_MOVE) + conditional_t<is_same<T, decay_t<T>>::value, decay_t<T>&, decay_t<T>> value; }; } // namespace detail diff --git a/3rdparty/asio/include/asio/detail/noncopyable.hpp b/3rdparty/asio/include/asio/detail/noncopyable.hpp index a148e031cf1..7b80a89457a 100644 --- a/3rdparty/asio/include/asio/detail/noncopyable.hpp +++ b/3rdparty/asio/include/asio/detail/noncopyable.hpp @@ -2,7 +2,7 @@ // detail/noncopyable.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/null_event.hpp b/3rdparty/asio/include/asio/detail/null_event.hpp index 5bff3c46afe..d50724c9e5b 100644 --- a/3rdparty/asio/include/asio/detail/null_event.hpp +++ b/3rdparty/asio/include/asio/detail/null_event.hpp @@ -2,7 +2,7 @@ // detail/null_event.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/null_fenced_block.hpp b/3rdparty/asio/include/asio/detail/null_fenced_block.hpp index 265b3bffd5b..ccf65c3ca78 100644 --- a/3rdparty/asio/include/asio/detail/null_fenced_block.hpp +++ b/3rdparty/asio/include/asio/detail/null_fenced_block.hpp @@ -2,7 +2,7 @@ // detail/null_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/null_global.hpp b/3rdparty/asio/include/asio/detail/null_global.hpp index 7bd12502eb3..ab8b9c87e61 100644 --- a/3rdparty/asio/include/asio/detail/null_global.hpp +++ b/3rdparty/asio/include/asio/detail/null_global.hpp @@ -2,7 +2,7 @@ // detail/null_global.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/null_mutex.hpp b/3rdparty/asio/include/asio/detail/null_mutex.hpp index b5457339843..77e759473f5 100644 --- a/3rdparty/asio/include/asio/detail/null_mutex.hpp +++ b/3rdparty/asio/include/asio/detail/null_mutex.hpp @@ -2,7 +2,7 @@ // detail/null_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,8 +17,6 @@ #include "asio/detail/config.hpp" -#if !defined(ASIO_HAS_THREADS) - #include "asio/detail/noncopyable.hpp" #include "asio/detail/scoped_lock.hpp" @@ -59,6 +57,4 @@ public: #include "asio/detail/pop_options.hpp" -#endif // !defined(ASIO_HAS_THREADS) - #endif // ASIO_DETAIL_NULL_MUTEX_HPP diff --git a/3rdparty/asio/include/asio/detail/null_reactor.hpp b/3rdparty/asio/include/asio/detail/null_reactor.hpp index f05c6ee15d2..128f2b45329 100644 --- a/3rdparty/asio/include/asio/detail/null_reactor.hpp +++ b/3rdparty/asio/include/asio/detail/null_reactor.hpp @@ -2,7 +2,7 @@ // detail/null_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,9 +17,12 @@ #include "asio/detail/config.hpp" -#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME) +#if defined(ASIO_HAS_IOCP) \ + || defined(ASIO_WINDOWS_RUNTIME) \ + || defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/detail/scheduler_operation.hpp" +#include "asio/detail/scheduler_task.hpp" #include "asio/execution_context.hpp" #include "asio/detail/push_options.hpp" @@ -28,9 +31,14 @@ namespace asio { namespace detail { class null_reactor - : public execution_context_service_base<null_reactor> + : public execution_context_service_base<null_reactor>, + public scheduler_task { public: + struct per_descriptor_data + { + }; + // Constructor. null_reactor(asio::execution_context& ctx) : execution_context_service_base<null_reactor>(ctx) @@ -42,6 +50,11 @@ public: { } + // Initialise the task. + void init_task() + { + } + // Destroy all user-defined handler objects owned by the service. void shutdown() { @@ -63,6 +76,8 @@ public: #include "asio/detail/pop_options.hpp" -#endif // defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME) +#endif // defined(ASIO_HAS_IOCP) + // || defined(ASIO_WINDOWS_RUNTIME) + // || defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_NULL_REACTOR_HPP diff --git a/3rdparty/asio/include/asio/detail/null_signal_blocker.hpp b/3rdparty/asio/include/asio/detail/null_signal_blocker.hpp index 8a9bf367a00..1c4030799fa 100644 --- a/3rdparty/asio/include/asio/detail/null_signal_blocker.hpp +++ b/3rdparty/asio/include/asio/detail/null_signal_blocker.hpp @@ -2,7 +2,7 @@ // detail/null_signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/null_socket_service.hpp b/3rdparty/asio/include/asio/detail/null_socket_service.hpp index e6525465c4e..84e21295f63 100644 --- a/3rdparty/asio/include/asio/detail/null_socket_service.hpp +++ b/3rdparty/asio/include/asio/detail/null_socket_service.hpp @@ -2,7 +2,7 @@ // detail/null_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -33,7 +33,7 @@ namespace detail { template <typename Protocol> class null_socket_service : - public execution_context_service_base<null_socket_service<Protocol> > + public execution_context_service_base<null_socket_service<Protocol>> { public: // The protocol type. @@ -52,7 +52,7 @@ public: // Constructor. null_socket_service(execution_context& context) - : execution_context_service_base<null_socket_service<Protocol> >(context) + : execution_context_service_base<null_socket_service<Protocol>>(context) { } diff --git a/3rdparty/asio/include/asio/detail/null_static_mutex.hpp b/3rdparty/asio/include/asio/detail/null_static_mutex.hpp index 4053056aa2f..15d649bb0da 100644 --- a/3rdparty/asio/include/asio/detail/null_static_mutex.hpp +++ b/3rdparty/asio/include/asio/detail/null_static_mutex.hpp @@ -2,7 +2,7 @@ // detail/null_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/null_thread.hpp b/3rdparty/asio/include/asio/detail/null_thread.hpp index bbdba55622f..aca261671c5 100644 --- a/3rdparty/asio/include/asio/detail/null_thread.hpp +++ b/3rdparty/asio/include/asio/detail/null_thread.hpp @@ -2,7 +2,7 @@ // detail/null_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/null_tss_ptr.hpp b/3rdparty/asio/include/asio/detail/null_tss_ptr.hpp index e2b4cf3d607..cf64a2bcdda 100644 --- a/3rdparty/asio/include/asio/detail/null_tss_ptr.hpp +++ b/3rdparty/asio/include/asio/detail/null_tss_ptr.hpp @@ -2,7 +2,7 @@ // detail/null_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/object_pool.hpp b/3rdparty/asio/include/asio/detail/object_pool.hpp index 45524d35501..41254ce52ee 100644 --- a/3rdparty/asio/include/asio/detail/object_pool.hpp +++ b/3rdparty/asio/include/asio/detail/object_pool.hpp @@ -2,7 +2,7 @@ // detail/object_pool.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/old_win_sdk_compat.hpp b/3rdparty/asio/include/asio/detail/old_win_sdk_compat.hpp index 734d72e7833..2c43c1dab80 100644 --- a/3rdparty/asio/include/asio/detail/old_win_sdk_compat.hpp +++ b/3rdparty/asio/include/asio/detail/old_win_sdk_compat.hpp @@ -2,7 +2,7 @@ // detail/old_win_sdk_compat.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/op_queue.hpp b/3rdparty/asio/include/asio/detail/op_queue.hpp index 1261339921f..db6335f40f6 100644 --- a/3rdparty/asio/include/asio/detail/op_queue.hpp +++ b/3rdparty/asio/include/asio/detail/op_queue.hpp @@ -2,7 +2,7 @@ // detail/op_queue.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/operation.hpp b/3rdparty/asio/include/asio/detail/operation.hpp index 6e58117ff0d..8721f397a5c 100644 --- a/3rdparty/asio/include/asio/detail/operation.hpp +++ b/3rdparty/asio/include/asio/detail/operation.hpp @@ -2,7 +2,7 @@ // detail/operation.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/pipe_select_interrupter.hpp b/3rdparty/asio/include/asio/detail/pipe_select_interrupter.hpp index 09b3f3bdb67..f7b219644e4 100644 --- a/3rdparty/asio/include/asio/detail/pipe_select_interrupter.hpp +++ b/3rdparty/asio/include/asio/detail/pipe_select_interrupter.hpp @@ -2,7 +2,7 @@ // detail/pipe_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/pop_options.hpp b/3rdparty/asio/include/asio/detail/pop_options.hpp index 9b14085bd49..93cdb5abb4d 100644 --- a/3rdparty/asio/include/asio/detail/pop_options.hpp +++ b/3rdparty/asio/include/asio/detail/pop_options.hpp @@ -2,7 +2,7 @@ // detail/pop_options.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -29,6 +29,10 @@ # endif // !defined(ASIO_DISABLE_VISIBILITY) # endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# pragma pop_macro ("emit") +# pragma pop_macro ("signal") +# pragma pop_macro ("slot") + #elif defined(__clang__) // Clang @@ -146,4 +150,8 @@ # endif # endif +# pragma pop_macro ("emit") +# pragma pop_macro ("signal") +# pragma pop_macro ("slot") + #endif diff --git a/3rdparty/asio/include/asio/detail/posix_event.hpp b/3rdparty/asio/include/asio/detail/posix_event.hpp index 8a06b422466..0c83bd31a30 100644 --- a/3rdparty/asio/include/asio/detail/posix_event.hpp +++ b/3rdparty/asio/include/asio/detail/posix_event.hpp @@ -2,7 +2,7 @@ // detail/posix_event.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/posix_fd_set_adapter.hpp b/3rdparty/asio/include/asio/detail/posix_fd_set_adapter.hpp index 230160b8e27..bd28a13fb2c 100644 --- a/3rdparty/asio/include/asio/detail/posix_fd_set_adapter.hpp +++ b/3rdparty/asio/include/asio/detail/posix_fd_set_adapter.hpp @@ -2,7 +2,7 @@ // detail/posix_fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/posix_global.hpp b/3rdparty/asio/include/asio/detail/posix_global.hpp index b7b113a4726..aea71e15c82 100644 --- a/3rdparty/asio/include/asio/detail/posix_global.hpp +++ b/3rdparty/asio/include/asio/detail/posix_global.hpp @@ -2,7 +2,7 @@ // detail/posix_global.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/posix_mutex.hpp b/3rdparty/asio/include/asio/detail/posix_mutex.hpp index ee0e8b20242..38ce2867ff5 100644 --- a/3rdparty/asio/include/asio/detail/posix_mutex.hpp +++ b/3rdparty/asio/include/asio/detail/posix_mutex.hpp @@ -2,7 +2,7 @@ // detail/posix_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/reactive_serial_port_service.hpp b/3rdparty/asio/include/asio/detail/posix_serial_port_service.hpp index e5a605c943d..79309549845 100644 --- a/3rdparty/asio/include/asio/detail/reactive_serial_port_service.hpp +++ b/3rdparty/asio/include/asio/detail/posix_serial_port_service.hpp @@ -1,16 +1,16 @@ // -// detail/reactive_serial_port_service.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// detail/posix_serial_port_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // -#ifndef ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP -#define ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP +#ifndef ASIO_DETAIL_POSIX_SERIAL_PORT_SERVICE_HPP +#define ASIO_DETAIL_POSIX_SERIAL_PORT_SERVICE_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once @@ -26,25 +26,36 @@ #include "asio/execution_context.hpp" #include "asio/serial_port_base.hpp" #include "asio/detail/descriptor_ops.hpp" -#include "asio/detail/reactive_descriptor_service.hpp" + +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/io_uring_descriptor_service.hpp" +#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/reactive_descriptor_service.hpp" +#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/detail/push_options.hpp" namespace asio { namespace detail { -// Extend reactive_descriptor_service to provide serial port support. -class reactive_serial_port_service : - public execution_context_service_base<reactive_serial_port_service> +// Extend a descriptor_service to provide serial port support. +class posix_serial_port_service : + public execution_context_service_base<posix_serial_port_service> { public: +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + typedef io_uring_descriptor_service descriptor_service; +#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) + typedef reactive_descriptor_service descriptor_service; +#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) + // The native type of a serial port. - typedef reactive_descriptor_service::native_handle_type native_handle_type; + typedef descriptor_service::native_handle_type native_handle_type; // The implementation type of the serial port. - typedef reactive_descriptor_service::implementation_type implementation_type; + typedef descriptor_service::implementation_type implementation_type; - ASIO_DECL reactive_serial_port_service(execution_context& context); + ASIO_DECL posix_serial_port_service(execution_context& context); // Destroy all user-defined handler objects owned by the service. ASIO_DECL void shutdown(); @@ -64,7 +75,7 @@ public: // Move-assign from another serial port implementation. void move_assign(implementation_type& impl, - reactive_serial_port_service& other_service, + posix_serial_port_service& other_service, implementation_type& other_impl) { descriptor_service_.move_assign(impl, @@ -121,7 +132,7 @@ public: const SettableSerialPortOption& option, asio::error_code& ec) { return do_set_option(impl, - &reactive_serial_port_service::store_option<SettableSerialPortOption>, + &posix_serial_port_service::store_option<SettableSerialPortOption>, &option, ec); } @@ -131,7 +142,7 @@ public: GettableSerialPortOption& option, asio::error_code& ec) const { return do_get_option(impl, - &reactive_serial_port_service::load_option<GettableSerialPortOption>, + &posix_serial_port_service::load_option<GettableSerialPortOption>, &option, ec); } @@ -141,6 +152,7 @@ public: { int result = ::tcsendbreak(descriptor_service_.native_handle(impl), 0); descriptor_ops::get_last_error(ec, result < 0); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -219,7 +231,7 @@ private: void* option, asio::error_code& ec) const; // The implementation used for initiating asynchronous operations. - reactive_descriptor_service descriptor_service_; + descriptor_service descriptor_service_; }; } // namespace detail @@ -228,10 +240,10 @@ private: #include "asio/detail/pop_options.hpp" #if defined(ASIO_HEADER_ONLY) -# include "asio/detail/impl/reactive_serial_port_service.ipp" +# include "asio/detail/impl/posix_serial_port_service.ipp" #endif // defined(ASIO_HEADER_ONLY) #endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__) #endif // defined(ASIO_HAS_SERIAL_PORT) -#endif // ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP +#endif // ASIO_DETAIL_POSIX_SERIAL_PORT_SERVICE_HPP diff --git a/3rdparty/asio/include/asio/detail/posix_signal_blocker.hpp b/3rdparty/asio/include/asio/detail/posix_signal_blocker.hpp index e0a4420bfb8..a57c09687b8 100644 --- a/3rdparty/asio/include/asio/detail/posix_signal_blocker.hpp +++ b/3rdparty/asio/include/asio/detail/posix_signal_blocker.hpp @@ -2,7 +2,7 @@ // detail/posix_signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/posix_static_mutex.hpp b/3rdparty/asio/include/asio/detail/posix_static_mutex.hpp index b9fdd481ae7..38a44c0327a 100644 --- a/3rdparty/asio/include/asio/detail/posix_static_mutex.hpp +++ b/3rdparty/asio/include/asio/detail/posix_static_mutex.hpp @@ -2,7 +2,7 @@ // detail/posix_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/posix_thread.hpp b/3rdparty/asio/include/asio/detail/posix_thread.hpp index cd80af10f1f..9085a0b4a7b 100644 --- a/3rdparty/asio/include/asio/detail/posix_thread.hpp +++ b/3rdparty/asio/include/asio/detail/posix_thread.hpp @@ -2,7 +2,7 @@ // detail/posix_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/posix_tss_ptr.hpp b/3rdparty/asio/include/asio/detail/posix_tss_ptr.hpp index 6d8b29f6581..b0d0653bed5 100644 --- a/3rdparty/asio/include/asio/detail/posix_tss_ptr.hpp +++ b/3rdparty/asio/include/asio/detail/posix_tss_ptr.hpp @@ -2,7 +2,7 @@ // detail/posix_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/push_options.hpp b/3rdparty/asio/include/asio/detail/push_options.hpp index 9786ff90098..d270e9ae13c 100644 --- a/3rdparty/asio/include/asio/detail/push_options.hpp +++ b/3rdparty/asio/include/asio/detail/push_options.hpp @@ -2,7 +2,7 @@ // detail/push_options.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -29,6 +29,15 @@ # endif // !defined(ASIO_DISABLE_VISIBILITY) # endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# pragma push_macro ("emit") +# undef emit + +# pragma push_macro ("signal") +# undef signal + +# pragma push_macro ("slot") +# undef slot + #elif defined(__clang__) // Clang @@ -163,12 +172,13 @@ // // Must remain the last #elif since some other vendors (Metrowerks, for example) // also #define _MSC_VER - # pragma warning (disable:4103) # pragma warning (push) +# pragma warning (disable:4619) // suppress 'there is no warning number XXXX' # pragma warning (disable:4127) # pragma warning (disable:4180) # pragma warning (disable:4244) +# pragma warning (disable:4265) # pragma warning (disable:4355) # pragma warning (disable:4510) # pragma warning (disable:4512) diff --git a/3rdparty/asio/include/asio/detail/reactive_descriptor_service.hpp b/3rdparty/asio/include/asio/detail/reactive_descriptor_service.hpp index 2c557e8b4c7..f7c7e86916d 100644 --- a/3rdparty/asio/include/asio/detail/reactive_descriptor_service.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_descriptor_service.hpp @@ -2,7 +2,7 @@ // detail/reactive_descriptor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,9 +19,11 @@ #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \ - && !defined(__CYGWIN__) + && !defined(__CYGWIN__) \ + && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/associated_cancellation_slot.hpp" +#include "asio/associated_immediate_executor.hpp" #include "asio/buffer.hpp" #include "asio/cancellation_type.hpp" #include "asio/execution_context.hpp" @@ -87,7 +89,7 @@ public: // Move-construct a new descriptor implementation. ASIO_DECL void move_construct(implementation_type& impl, - implementation_type& other_impl) ASIO_NOEXCEPT; + implementation_type& other_impl) noexcept; // Move-assign from another descriptor implementation. ASIO_DECL void move_assign(implementation_type& impl, @@ -121,6 +123,14 @@ public: // Release ownership of the native descriptor representation. ASIO_DECL native_handle_type release(implementation_type& impl); + // Release ownership of the native descriptor representation. + native_handle_type release(implementation_type& impl, + asio::error_code& ec) + { + ec = success_ec_; + return release(impl); + } + // Cancel all operations associated with the descriptor. ASIO_DECL asio::error_code cancel(implementation_type& impl, asio::error_code& ec); @@ -132,6 +142,7 @@ public: { descriptor_ops::ioctl(impl.descriptor_, impl.state_, command.name(), static_cast<ioctl_arg_type*>(command.data()), ec); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -147,6 +158,7 @@ public: { descriptor_ops::set_user_non_blocking( impl.descriptor_, impl.state_, mode, ec); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -186,6 +198,7 @@ public: break; } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -199,7 +212,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -215,19 +228,20 @@ public: switch (w) { case posix::descriptor_base::wait_read: - op_type = reactor::read_op; - break; + op_type = reactor::read_op; + break; case posix::descriptor_base::wait_write: - op_type = reactor::write_op; - break; + op_type = reactor::write_op; + break; case posix::descriptor_base::wait_error: - op_type = reactor::except_op; - break; - default: - p.p->ec_ = asio::error::invalid_argument; - reactor_.post_immediate_completion(p.p, is_continuation); - p.v = p.p = 0; - return; + op_type = reactor::except_op; + break; + default: + p.p->ec_ = asio::error::invalid_argument; + start_op(impl, reactor::read_op, p.p, + is_continuation, false, true, &io_ex, 0); + p.v = p.p = 0; + return; } // Optionally register for per-operation cancellation. @@ -238,7 +252,7 @@ public: &reactor_, &impl.reactor_data_, impl.descriptor_, op_type); } - start_op(impl, op_type, p.p, is_continuation, false, false); + start_op(impl, op_type, p.p, is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -250,9 +264,10 @@ public: typedef buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs_type; + size_t n; if (bufs_type::is_single_buffer) { - return descriptor_ops::sync_write1(impl.descriptor_, + n = descriptor_ops::sync_write1(impl.descriptor_, impl.state_, bufs_type::first(buffers).data(), bufs_type::first(buffers).size(), ec); } @@ -260,9 +275,12 @@ public: { bufs_type bufs(buffers); - return descriptor_ops::sync_write(impl.descriptor_, impl.state_, + n = descriptor_ops::sync_write(impl.descriptor_, impl.state_, bufs.buffers(), bufs.count(), bufs.all_empty(), ec); } + + ASIO_ERROR_LOCATION(ec); + return n; } // Wait until data can be written without blocking. @@ -271,7 +289,7 @@ public: { // Wait for descriptor to become ready. descriptor_ops::poll_write(impl.descriptor_, impl.state_, ec); - + ASIO_ERROR_LOCATION(ec); return 0; } @@ -285,7 +303,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -308,7 +326,7 @@ public: start_op(impl, reactor::write_op, p.p, is_continuation, true, buffer_sequence_adapter<asio::const_buffer, - ConstBufferSequence>::all_empty(buffers)); + ConstBufferSequence>::all_empty(buffers), &io_ex, 0); p.v = p.p = 0; } @@ -320,7 +338,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -341,7 +359,8 @@ public: ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor", &impl, impl.descriptor_, "async_write_some(null_buffers)")); - start_op(impl, reactor::write_op, p.p, is_continuation, false, false); + start_op(impl, reactor::write_op, p.p, + is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -353,9 +372,10 @@ public: typedef buffer_sequence_adapter<asio::mutable_buffer, MutableBufferSequence> bufs_type; + size_t n; if (bufs_type::is_single_buffer) { - return descriptor_ops::sync_read1(impl.descriptor_, + n = descriptor_ops::sync_read1(impl.descriptor_, impl.state_, bufs_type::first(buffers).data(), bufs_type::first(buffers).size(), ec); } @@ -363,9 +383,12 @@ public: { bufs_type bufs(buffers); - return descriptor_ops::sync_read(impl.descriptor_, impl.state_, + n = descriptor_ops::sync_read(impl.descriptor_, impl.state_, bufs.buffers(), bufs.count(), bufs.all_empty(), ec); } + + ASIO_ERROR_LOCATION(ec); + return n; } // Wait until data can be read without blocking. @@ -374,7 +397,7 @@ public: { // Wait for descriptor to become ready. descriptor_ops::poll_read(impl.descriptor_, impl.state_, ec); - + ASIO_ERROR_LOCATION(ec); return 0; } @@ -389,7 +412,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -412,7 +435,7 @@ public: start_op(impl, reactor::read_op, p.p, is_continuation, true, buffer_sequence_adapter<asio::mutable_buffer, - MutableBufferSequence>::all_empty(buffers)); + MutableBufferSequence>::all_empty(buffers), &io_ex, 0); p.v = p.p = 0; } @@ -424,7 +447,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -445,14 +468,47 @@ public: ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor", &impl, impl.descriptor_, "async_read_some(null_buffers)")); - start_op(impl, reactor::read_op, p.p, is_continuation, false, false); + start_op(impl, reactor::read_op, p.p, + is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } private: // Start the asynchronous operation. - ASIO_DECL void start_op(implementation_type& impl, int op_type, - reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop); + ASIO_DECL void do_start_op(implementation_type& impl, int op_type, + reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop, + void (*on_immediate)(operation* op, bool, const void*), + const void* immediate_arg); + + // Start the asynchronous operation for handlers that are specialised for + // immediate completion. + template <typename Op> + void start_op(implementation_type& impl, int op_type, Op* op, + bool is_continuation, bool is_non_blocking, bool noop, + const void* io_ex, ...) + { + return do_start_op(impl, op_type, op, is_continuation, + is_non_blocking, noop, &Op::do_immediate, io_ex); + } + + // Start the asynchronous operation for handlers that are not specialised for + // immediate completion. + template <typename Op> + void start_op(implementation_type& impl, int op_type, Op* op, + bool is_continuation, bool is_non_blocking, bool noop, const void*, + enable_if_t< + is_same< + typename associated_immediate_executor< + typename Op::handler_type, + typename Op::io_executor_type + >::asio_associated_immediate_executor_is_unspecialised, + void + >::value + >*) + { + return do_start_op(impl, op_type, op, is_continuation, is_non_blocking, + noop, &reactor::call_post_immediate_completion, &reactor_); + } // Helper class used to implement per-operation cancellation class reactor_op_cancellation @@ -505,5 +561,6 @@ private: #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__) + // && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP diff --git a/3rdparty/asio/include/asio/detail/reactive_null_buffers_op.hpp b/3rdparty/asio/include/asio/detail/reactive_null_buffers_op.hpp index 48214dcba87..b9a32a91217 100644 --- a/3rdparty/asio/include/asio/detail/reactive_null_buffers_op.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_null_buffers_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_null_buffers_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,7 +19,6 @@ #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -33,13 +32,16 @@ template <typename Handler, typename IoExecutor> class reactive_null_buffers_op : public reactor_op { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(reactive_null_buffers_op); reactive_null_buffers_op(const asio::error_code& success_ec, Handler& handler, const IoExecutor& io_ex) : reactor_op(success_ec, &reactive_null_buffers_op::do_perform, &reactive_null_buffers_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -54,6 +56,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -61,7 +64,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); // Make a copy of the handler so that the memory can be deallocated before @@ -85,6 +88,36 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + private: Handler handler_; handler_work<Handler, IoExecutor> work_; diff --git a/3rdparty/asio/include/asio/detail/reactive_socket_accept_op.hpp b/3rdparty/asio/include/asio/detail/reactive_socket_accept_op.hpp index ac036717e8d..5ae84fd9966 100644 --- a/3rdparty/asio/include/asio/detail/reactive_socket_accept_op.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_socket_accept_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_accept_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,7 +19,6 @@ #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -52,6 +51,7 @@ public: static status do_perform(reactor_op* base) { + ASIO_ASSUME(base != 0); reactive_socket_accept_op_base* o( static_cast<reactive_socket_accept_op_base*>(base)); @@ -95,6 +95,9 @@ class reactive_socket_accept_op : public reactive_socket_accept_op_base<Socket, Protocol> { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(reactive_socket_accept_op); reactive_socket_accept_op(const asio::error_code& success_ec, @@ -104,7 +107,7 @@ public: : reactive_socket_accept_op_base<Socket, Protocol>( success_ec, socket, state, peer, protocol, peer_endpoint, &reactive_socket_accept_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -114,6 +117,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -125,9 +129,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(o->ec_); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -149,13 +155,46 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + // On success, assign new connection to peer socket object. + o->do_assign(); + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder1<Handler, asio::error_code> + handler(o->handler_, o->ec_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_)); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + private: Handler handler_; handler_work<Handler, IoExecutor> work_; }; -#if defined(ASIO_HAS_MOVE) - template <typename Protocol, typename PeerIoExecutor, typename Handler, typename IoExecutor> class reactive_socket_move_accept_op : @@ -165,6 +204,9 @@ class reactive_socket_move_accept_op : Protocol> { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op); reactive_socket_move_accept_op(const asio::error_code& success_ec, @@ -176,7 +218,7 @@ public: reactive_socket_accept_op_base<peer_socket_type, Protocol>( success_ec, socket, state, *this, protocol, peer_endpoint, &reactive_socket_move_accept_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -186,6 +228,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); reactive_socket_move_accept_op* o( static_cast<reactive_socket_move_accept_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -198,9 +241,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(o->ec_); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -209,8 +254,8 @@ public: // deallocated the memory here. detail::move_binder2<Handler, asio::error_code, peer_socket_type> - handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_, - ASIO_MOVE_CAST(peer_socket_type)(*o)); + handler(0, static_cast<Handler&&>(o->handler_), o->ec_, + static_cast<peer_socket_type&&>(*o)); p.h = asio::detail::addressof(handler.handler_); p.reset(); @@ -224,6 +269,44 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + reactive_socket_move_accept_op* o( + static_cast<reactive_socket_move_accept_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + // On success, assign new connection to peer socket object. + o->do_assign(); + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::move_binder2<Handler, + asio::error_code, peer_socket_type> + handler(0, static_cast<Handler&&>(o->handler_), o->ec_, + static_cast<peer_socket_type&&>(*o)); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "...")); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + private: typedef typename Protocol::socket::template rebind_executor<PeerIoExecutor>::other peer_socket_type; @@ -232,8 +315,6 @@ private: handler_work<Handler, IoExecutor> work_; }; -#endif // defined(ASIO_HAS_MOVE) - } // namespace detail } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/reactive_socket_connect_op.hpp b/3rdparty/asio/include/asio/detail/reactive_socket_connect_op.hpp index 956bc522d10..03c0db2e7dd 100644 --- a/3rdparty/asio/include/asio/detail/reactive_socket_connect_op.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_socket_connect_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,7 +19,6 @@ #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -43,6 +42,7 @@ public: static status do_perform(reactor_op* base) { + ASIO_ASSUME(base != 0); reactive_socket_connect_op_base* o( static_cast<reactive_socket_connect_op_base*>(base)); @@ -62,13 +62,16 @@ template <typename Handler, typename IoExecutor> class reactive_socket_connect_op : public reactive_socket_connect_op_base { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(reactive_socket_connect_op); reactive_socket_connect_op(const asio::error_code& success_ec, socket_type socket, Handler& handler, const IoExecutor& io_ex) : reactive_socket_connect_op_base(success_ec, socket, &reactive_socket_connect_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -78,6 +81,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); reactive_socket_connect_op* o (static_cast<reactive_socket_connect_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -86,9 +90,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(o->ec_); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -110,6 +116,39 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + reactive_socket_connect_op* o + (static_cast<reactive_socket_connect_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder1<Handler, asio::error_code> + handler(o->handler_, o->ec_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_)); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + private: Handler handler_; handler_work<Handler, IoExecutor> work_; diff --git a/3rdparty/asio/include/asio/detail/reactive_socket_recv_op.hpp b/3rdparty/asio/include/asio/detail/reactive_socket_recv_op.hpp index d30f4ab315a..b6533655674 100644 --- a/3rdparty/asio/include/asio/detail/reactive_socket_recv_op.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_socket_recv_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,7 +20,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -50,6 +49,7 @@ public: static status do_perform(reactor_op* base) { + ASIO_ASSUME(base != 0); reactive_socket_recv_op_base* o( static_cast<reactive_socket_recv_op_base*>(base)); @@ -97,6 +97,9 @@ class reactive_socket_recv_op : public reactive_socket_recv_op_base<MutableBufferSequence> { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op); reactive_socket_recv_op(const asio::error_code& success_ec, @@ -105,7 +108,7 @@ public: Handler& handler, const IoExecutor& io_ex) : reactive_socket_recv_op_base<MutableBufferSequence>(success_ec, socket, state, buffers, flags, &reactive_socket_recv_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -115,6 +118,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -122,9 +126,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(o->ec_); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -146,6 +152,38 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + private: Handler handler_; handler_work<Handler, IoExecutor> work_; diff --git a/3rdparty/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp b/3rdparty/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp index 0d7673a1120..b84ea61794f 100644 --- a/3rdparty/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_recvfrom_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,7 +20,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -51,6 +50,7 @@ public: static status do_perform(reactor_op* base) { + ASIO_ASSUME(base != 0); reactive_socket_recvfrom_op_base* o( static_cast<reactive_socket_recvfrom_op_base*>(base)); @@ -99,6 +99,9 @@ class reactive_socket_recvfrom_op : public reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint> { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op); reactive_socket_recvfrom_op(const asio::error_code& success_ec, @@ -109,7 +112,7 @@ public: : reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>( success_ec, socket, protocol_type, buffers, endpoint, flags, &reactive_socket_recvfrom_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -119,6 +122,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); reactive_socket_recvfrom_op* o( static_cast<reactive_socket_recvfrom_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -127,9 +131,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(o->ec_); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -151,6 +157,39 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + reactive_socket_recvfrom_op* o( + static_cast<reactive_socket_recvfrom_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + private: Handler handler_; handler_work<Handler, IoExecutor> work_; diff --git a/3rdparty/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp b/3rdparty/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp index b387f048f0c..e4c8117b675 100644 --- a/3rdparty/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_recvmsg_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,7 +20,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -51,6 +50,7 @@ public: static status do_perform(reactor_op* base) { + ASIO_ASSUME(base != 0); reactive_socket_recvmsg_op_base* o( static_cast<reactive_socket_recvmsg_op_base*>(base)); @@ -80,6 +80,9 @@ class reactive_socket_recvmsg_op : public reactive_socket_recvmsg_op_base<MutableBufferSequence> { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op); reactive_socket_recvmsg_op(const asio::error_code& success_ec, @@ -90,7 +93,7 @@ public: : reactive_socket_recvmsg_op_base<MutableBufferSequence>( success_ec, socket, buffers, in_flags, out_flags, &reactive_socket_recvmsg_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -100,6 +103,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); reactive_socket_recvmsg_op* o( static_cast<reactive_socket_recvmsg_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -108,9 +112,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(o->ec_); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -132,6 +138,39 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + reactive_socket_recvmsg_op* o( + static_cast<reactive_socket_recvmsg_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + private: Handler handler_; handler_work<Handler, IoExecutor> work_; diff --git a/3rdparty/asio/include/asio/detail/reactive_socket_send_op.hpp b/3rdparty/asio/include/asio/detail/reactive_socket_send_op.hpp index 5a778566ad8..ef7ec69933b 100644 --- a/3rdparty/asio/include/asio/detail/reactive_socket_send_op.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_socket_send_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,7 +20,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -50,6 +49,7 @@ public: static status do_perform(reactor_op* base) { + ASIO_ASSUME(base != 0); reactive_socket_send_op_base* o( static_cast<reactive_socket_send_op_base*>(base)); @@ -100,6 +100,9 @@ class reactive_socket_send_op : public reactive_socket_send_op_base<ConstBufferSequence> { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(reactive_socket_send_op); reactive_socket_send_op(const asio::error_code& success_ec, @@ -108,7 +111,7 @@ public: Handler& handler, const IoExecutor& io_ex) : reactive_socket_send_op_base<ConstBufferSequence>(success_ec, socket, state, buffers, flags, &reactive_socket_send_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -118,6 +121,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -125,9 +129,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(o->ec_); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -149,6 +155,39 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + + private: Handler handler_; handler_work<Handler, IoExecutor> work_; diff --git a/3rdparty/asio/include/asio/detail/reactive_socket_sendto_op.hpp b/3rdparty/asio/include/asio/detail/reactive_socket_sendto_op.hpp index 28bff66980d..e1bbb70389c 100644 --- a/3rdparty/asio/include/asio/detail/reactive_socket_sendto_op.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_socket_sendto_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_sendto_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,7 +20,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -50,6 +49,7 @@ public: static status do_perform(reactor_op* base) { + ASIO_ASSUME(base != 0); reactive_socket_sendto_op_base* o( static_cast<reactive_socket_sendto_op_base*>(base)); @@ -93,6 +93,9 @@ class reactive_socket_sendto_op : public reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint> { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(reactive_socket_sendto_op); reactive_socket_sendto_op(const asio::error_code& success_ec, @@ -102,7 +105,7 @@ public: : reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint>( success_ec, socket, buffers, endpoint, flags, &reactive_socket_sendto_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -112,6 +115,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -119,9 +123,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(o->ec_); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -143,6 +149,38 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + ASIO_ERROR_LOCATION(o->ec_); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder2<Handler, asio::error_code, std::size_t> + handler(o->handler_, o->ec_, o->bytes_transferred_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_)); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + private: Handler handler_; handler_work<Handler, IoExecutor> work_; diff --git a/3rdparty/asio/include/asio/detail/reactive_socket_service.hpp b/3rdparty/asio/include/asio/detail/reactive_socket_service.hpp index 2124eaf9a9d..c828e7f1f2a 100644 --- a/3rdparty/asio/include/asio/detail/reactive_socket_service.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_socket_service.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,7 +17,8 @@ #include "asio/detail/config.hpp" -#if !defined(ASIO_HAS_IOCP) +#if !defined(ASIO_HAS_IOCP) \ + && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/buffer.hpp" #include "asio/error.hpp" @@ -45,7 +46,7 @@ namespace detail { template <typename Protocol> class reactive_socket_service : - public execution_context_service_base<reactive_socket_service<Protocol> >, + public execution_context_service_base<reactive_socket_service<Protocol>>, public reactive_socket_service_base { public: @@ -75,7 +76,7 @@ public: // Constructor. reactive_socket_service(execution_context& context) : execution_context_service_base< - reactive_socket_service<Protocol> >(context), + reactive_socket_service<Protocol>>(context), reactive_socket_service_base(context) { } @@ -88,7 +89,7 @@ public: // Move-construct a new socket implementation. void move_construct(implementation_type& impl, - implementation_type& other_impl) ASIO_NOEXCEPT + implementation_type& other_impl) noexcept { this->base_move_construct(impl, other_impl); @@ -127,6 +128,8 @@ public: if (!do_open(impl, protocol.family(), protocol.type(), protocol.protocol(), ec)) impl.protocol_ = protocol; + + ASIO_ERROR_LOCATION(ec); return ec; } @@ -137,6 +140,8 @@ public: { if (!do_assign(impl, protocol.type(), native_socket, ec)) impl.protocol_ = protocol; + + ASIO_ERROR_LOCATION(ec); return ec; } @@ -151,6 +156,8 @@ public: const endpoint_type& endpoint, asio::error_code& ec) { socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); + + ASIO_ERROR_LOCATION(ec); return ec; } @@ -162,6 +169,8 @@ public: socket_ops::setsockopt(impl.socket_, impl.state_, option.level(impl.protocol_), option.name(impl.protocol_), option.data(impl.protocol_), option.size(impl.protocol_), ec); + + ASIO_ERROR_LOCATION(ec); return ec; } @@ -176,6 +185,8 @@ public: option.data(impl.protocol_), &size, ec); if (!ec) option.resize(impl.protocol_, size); + + ASIO_ERROR_LOCATION(ec); return ec; } @@ -186,7 +197,10 @@ public: endpoint_type endpoint; std::size_t addr_len = endpoint.capacity(); if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) + { + ASIO_ERROR_LOCATION(ec); return endpoint_type(); + } endpoint.resize(addr_len); return endpoint; } @@ -199,7 +213,10 @@ public: std::size_t addr_len = endpoint.capacity(); if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, false, ec)) + { + ASIO_ERROR_LOCATION(ec); return endpoint_type(); + } endpoint.resize(addr_len); return endpoint; } @@ -209,6 +226,8 @@ public: socket_base::shutdown_type what, asio::error_code& ec) { socket_ops::shutdown(impl.socket_, what, ec); + + ASIO_ERROR_LOCATION(ec); return ec; } @@ -222,9 +241,10 @@ public: typedef buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs_type; + size_t n; if (bufs_type::is_single_buffer) { - return socket_ops::sync_sendto1(impl.socket_, impl.state_, + n = socket_ops::sync_sendto1(impl.socket_, impl.state_, bufs_type::first(buffers).data(), bufs_type::first(buffers).size(), flags, destination.data(), destination.size(), ec); @@ -232,10 +252,13 @@ public: else { bufs_type bufs(buffers); - return socket_ops::sync_sendto(impl.socket_, impl.state_, + n = socket_ops::sync_sendto(impl.socket_, impl.state_, bufs.buffers(), bufs.count(), flags, destination.data(), destination.size(), ec); } + + ASIO_ERROR_LOCATION(ec); + return n; } // Wait until data can be sent without blocking. @@ -246,6 +269,7 @@ public: // Wait for socket to become ready. socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); + ASIO_ERROR_LOCATION(ec); return 0; } @@ -260,7 +284,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -282,7 +306,8 @@ public: ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send_to")); - start_op(impl, reactor::write_op, p.p, is_continuation, true, false); + start_op(impl, reactor::write_op, p.p, + is_continuation, true, false, &io_ex, 0); p.v = p.p = 0; } @@ -295,7 +320,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -315,7 +340,8 @@ public: ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send_to(null_buffers)")); - start_op(impl, reactor::write_op, p.p, is_continuation, false, false); + start_op(impl, reactor::write_op, p.p, + is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -331,26 +357,25 @@ public: MutableBufferSequence> bufs_type; std::size_t addr_len = sender_endpoint.capacity(); - std::size_t bytes_recvd; + std::size_t n; if (bufs_type::is_single_buffer) { - bytes_recvd = socket_ops::sync_recvfrom1(impl.socket_, - impl.state_, bufs_type::first(buffers).data(), - bufs_type::first(buffers).size(), flags, - sender_endpoint.data(), &addr_len, ec); + n = socket_ops::sync_recvfrom1(impl.socket_, impl.state_, + bufs_type::first(buffers).data(), bufs_type::first(buffers).size(), + flags, sender_endpoint.data(), &addr_len, ec); } else { bufs_type bufs(buffers); - bytes_recvd = socket_ops::sync_recvfrom( - impl.socket_, impl.state_, bufs.buffers(), bufs.count(), - flags, sender_endpoint.data(), &addr_len, ec); + n = socket_ops::sync_recvfrom(impl.socket_, impl.state_, bufs.buffers(), + bufs.count(), flags, sender_endpoint.data(), &addr_len, ec); } if (!ec) sender_endpoint.resize(addr_len); - return bytes_recvd; + ASIO_ERROR_LOCATION(ec); + return n; } // Wait until data can be received without blocking. @@ -364,6 +389,7 @@ public: // Reset endpoint since it can be given no sensible value at this time. sender_endpoint = endpoint_type(); + ASIO_ERROR_LOCATION(ec); return 0; } @@ -380,7 +406,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -406,7 +432,7 @@ public: start_op(impl, (flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op, - p.p, is_continuation, true, false); + p.p, is_continuation, true, false, &io_ex, 0); p.v = p.p = 0; } @@ -419,7 +445,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -445,7 +471,7 @@ public: start_op(impl, (flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op, - p.p, is_continuation, false, false); + p.p, is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -458,6 +484,7 @@ public: if (peer.is_open()) { ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); return ec; } @@ -476,6 +503,7 @@ public: new_socket.release(); } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -488,7 +516,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -509,11 +537,10 @@ public: ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_accept")); - start_accept_op(impl, p.p, is_continuation, peer.is_open()); + start_accept_op(impl, p.p, is_continuation, peer.is_open(), &io_ex, 0); p.v = p.p = 0; } -#if defined(ASIO_HAS_MOVE) // Start an asynchronous accept. The peer_endpoint object must be valid until // the accept's handler is invoked. template <typename PeerIoExecutor, typename Handler, typename IoExecutor> @@ -524,7 +551,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -546,10 +573,9 @@ public: ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_accept")); - start_accept_op(impl, p.p, is_continuation, false); + start_accept_op(impl, p.p, is_continuation, false, &io_ex, 0); p.v = p.p = 0; } -#endif // defined(ASIO_HAS_MOVE) // Connect the socket to the specified endpoint. asio::error_code connect(implementation_type& impl, @@ -557,6 +583,7 @@ public: { socket_ops::sync_connect(impl.socket_, peer_endpoint.data(), peer_endpoint.size(), ec); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -569,7 +596,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -590,7 +617,7 @@ public: &impl, impl.socket_, "async_connect")); start_connect_op(impl, p.p, is_continuation, - peer_endpoint.data(), peer_endpoint.size()); + peer_endpoint.data(), peer_endpoint.size(), &io_ex, 0); p.v = p.p = 0; } }; @@ -601,5 +628,6 @@ public: #include "asio/detail/pop_options.hpp" #endif // !defined(ASIO_HAS_IOCP) + // && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP diff --git a/3rdparty/asio/include/asio/detail/reactive_socket_service_base.hpp b/3rdparty/asio/include/asio/detail/reactive_socket_service_base.hpp index c36811b9a99..63dcacad582 100644 --- a/3rdparty/asio/include/asio/detail/reactive_socket_service_base.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_socket_service_base.hpp @@ -2,7 +2,7 @@ // detail/reactive_socket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,7 +18,8 @@ #include "asio/detail/config.hpp" #if !defined(ASIO_HAS_IOCP) \ - && !defined(ASIO_WINDOWS_RUNTIME) + && !defined(ASIO_WINDOWS_RUNTIME) \ + && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/associated_cancellation_slot.hpp" #include "asio/buffer.hpp" @@ -74,7 +75,7 @@ public: // Move-construct a new socket implementation. ASIO_DECL void base_move_construct(base_implementation_type& impl, - base_implementation_type& other_impl) ASIO_NOEXCEPT; + base_implementation_type& other_impl) noexcept; // Move-assign from another socket implementation. ASIO_DECL void base_move_assign(base_implementation_type& impl, @@ -201,7 +202,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -216,20 +217,21 @@ public: int op_type; switch (w) { - case socket_base::wait_read: - op_type = reactor::read_op; - break; - case socket_base::wait_write: - op_type = reactor::write_op; - break; - case socket_base::wait_error: - op_type = reactor::except_op; - break; - default: - p.p->ec_ = asio::error::invalid_argument; - reactor_.post_immediate_completion(p.p, is_continuation); - p.v = p.p = 0; - return; + case socket_base::wait_read: + op_type = reactor::read_op; + break; + case socket_base::wait_write: + op_type = reactor::write_op; + break; + case socket_base::wait_error: + op_type = reactor::except_op; + break; + default: + p.p->ec_ = asio::error::invalid_argument; + start_op(impl, reactor::read_op, p.p, + is_continuation, false, true, &io_ex, 0); + p.v = p.p = 0; + return; } // Optionally register for per-operation cancellation. @@ -240,7 +242,7 @@ public: &reactor_, &impl.reactor_data_, impl.socket_, op_type); } - start_op(impl, op_type, p.p, is_continuation, false, false); + start_op(impl, op_type, p.p, is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -287,7 +289,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -312,7 +314,7 @@ public: start_op(impl, reactor::write_op, p.p, is_continuation, true, ((impl.state_ & socket_ops::stream_oriented) && buffer_sequence_adapter<asio::const_buffer, - ConstBufferSequence>::all_empty(buffers))); + ConstBufferSequence>::all_empty(buffers)), &io_ex, 0); p.v = p.p = 0; } @@ -324,7 +326,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -344,7 +346,8 @@ public: ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket", &impl, impl.socket_, "async_send(null_buffers)")); - start_op(impl, reactor::write_op, p.p, is_continuation, false, false); + start_op(impl, reactor::write_op, p.p, + is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -392,7 +395,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -421,7 +424,7 @@ public: (flags & socket_base::message_out_of_band) == 0, ((impl.state_ & socket_ops::stream_oriented) && buffer_sequence_adapter<asio::mutable_buffer, - MutableBufferSequence>::all_empty(buffers))); + MutableBufferSequence>::all_empty(buffers)), &io_ex, 0); p.v = p.p = 0; } @@ -434,7 +437,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -457,7 +460,7 @@ public: start_op(impl, (flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op, - p.p, is_continuation, false, false); + p.p, is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -503,7 +506,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -529,7 +532,7 @@ public: (in_flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op, p.p, is_continuation, - (in_flags & socket_base::message_out_of_band) == 0, false); + (in_flags & socket_base::message_out_of_band) == 0, false, &io_ex, 0); p.v = p.p = 0; } @@ -543,7 +546,7 @@ public: bool is_continuation = asio_handler_cont_helpers::is_continuation(handler); - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -570,7 +573,7 @@ public: start_op(impl, (in_flags & socket_base::message_out_of_band) ? reactor::except_op : reactor::read_op, - p.p, is_continuation, false, false); + p.p, is_continuation, false, false, &io_ex, 0); p.v = p.p = 0; } @@ -586,24 +589,118 @@ protected: const native_handle_type& native_socket, asio::error_code& ec); // Start the asynchronous read or write operation. - ASIO_DECL void start_op(base_implementation_type& impl, int op_type, - reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop); + ASIO_DECL void do_start_op(base_implementation_type& impl, int op_type, + reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop, + void (*on_immediate)(operation* op, bool, const void*), + const void* immediate_arg); + + // Start the asynchronous operation for handlers that are specialised for + // immediate completion. + template <typename Op> + void start_op(base_implementation_type& impl, int op_type, Op* op, + bool is_continuation, bool is_non_blocking, bool noop, + const void* io_ex, ...) + { + return do_start_op(impl, op_type, op, is_continuation, + is_non_blocking, noop, &Op::do_immediate, io_ex); + } + + // Start the asynchronous operation for handlers that are not specialised for + // immediate completion. + template <typename Op> + void start_op(base_implementation_type& impl, int op_type, Op* op, + bool is_continuation, bool is_non_blocking, bool noop, const void*, + enable_if_t< + is_same< + typename associated_immediate_executor< + typename Op::handler_type, + typename Op::io_executor_type + >::asio_associated_immediate_executor_is_unspecialised, + void + >::value + >*) + { + return do_start_op(impl, op_type, op, is_continuation, is_non_blocking, + noop, &reactor::call_post_immediate_completion, &reactor_); + } // Start the asynchronous accept operation. - ASIO_DECL void start_accept_op(base_implementation_type& impl, - reactor_op* op, bool is_continuation, bool peer_is_open); + ASIO_DECL void do_start_accept_op(base_implementation_type& impl, + reactor_op* op, bool is_continuation, bool peer_is_open, + void (*on_immediate)(operation* op, bool, const void*), + const void* immediate_arg); + + // Start the asynchronous accept operation for handlers that are specialised + // for immediate completion. + template <typename Op> + void start_accept_op(base_implementation_type& impl, Op* op, + bool is_continuation, bool peer_is_open, const void* io_ex, ...) + { + return do_start_accept_op(impl, op, is_continuation, + peer_is_open, &Op::do_immediate, io_ex); + } + + // Start the asynchronous operation for handlers that are not specialised for + // immediate completion. + template <typename Op> + void start_accept_op(base_implementation_type& impl, Op* op, + bool is_continuation, bool peer_is_open, const void*, + enable_if_t< + is_same< + typename associated_immediate_executor< + typename Op::handler_type, + typename Op::io_executor_type + >::asio_associated_immediate_executor_is_unspecialised, + void + >::value + >*) + { + return do_start_accept_op(impl, op, is_continuation, peer_is_open, + &reactor::call_post_immediate_completion, &reactor_); + } // Start the asynchronous connect operation. - ASIO_DECL void start_connect_op(base_implementation_type& impl, - reactor_op* op, bool is_continuation, - const socket_addr_type* addr, size_t addrlen); + ASIO_DECL void do_start_connect_op(base_implementation_type& impl, + reactor_op* op, bool is_continuation, const void* addr, size_t addrlen, + void (*on_immediate)(operation* op, bool, const void*), + const void* immediate_arg); + + // Start the asynchronous operation for handlers that are specialised for + // immediate completion. + template <typename Op> + void start_connect_op(base_implementation_type& impl, + Op* op, bool is_continuation, const void* addr, + size_t addrlen, const void* io_ex, ...) + { + return do_start_connect_op(impl, op, is_continuation, + addr, addrlen, &Op::do_immediate, io_ex); + } + + // Start the asynchronous operation for handlers that are not specialised for + // immediate completion. + template <typename Op> + void start_connect_op(base_implementation_type& impl, Op* op, + bool is_continuation, const void* addr, size_t addrlen, const void*, + enable_if_t< + is_same< + typename associated_immediate_executor< + typename Op::handler_type, + typename Op::io_executor_type + >::asio_associated_immediate_executor_is_unspecialised, + void + >::value + >*) + { + return do_start_connect_op(impl, op, is_continuation, addr, + addrlen, &reactor::call_post_immediate_completion, &reactor_); + } // Helper class used to implement per-operation cancellation class reactor_op_cancellation { public: reactor_op_cancellation(reactor* r, - reactor::per_descriptor_data* p, int d, int o) + reactor::per_descriptor_data* p, socket_type d, int o) : reactor_(r), reactor_data_(p), descriptor_(d), @@ -626,7 +723,7 @@ protected: private: reactor* reactor_; reactor::per_descriptor_data* reactor_data_; - int descriptor_; + socket_type descriptor_; int op_type_; }; @@ -648,5 +745,6 @@ protected: #endif // !defined(ASIO_HAS_IOCP) // && !defined(ASIO_WINDOWS_RUNTIME) + // && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP diff --git a/3rdparty/asio/include/asio/detail/reactive_wait_op.hpp b/3rdparty/asio/include/asio/detail/reactive_wait_op.hpp index c7e2eb8d376..62938e2d83e 100644 --- a/3rdparty/asio/include/asio/detail/reactive_wait_op.hpp +++ b/3rdparty/asio/include/asio/detail/reactive_wait_op.hpp @@ -2,7 +2,7 @@ // detail/reactive_wait_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,7 +19,6 @@ #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -33,13 +32,16 @@ template <typename Handler, typename IoExecutor> class reactive_wait_op : public reactor_op { public: + typedef Handler handler_type; + typedef IoExecutor io_executor_type; + ASIO_DEFINE_HANDLER_PTR(reactive_wait_op); reactive_wait_op(const asio::error_code& success_ec, Handler& handler, const IoExecutor& io_ex) : reactor_op(success_ec, &reactive_wait_op::do_perform, &reactive_wait_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -54,6 +56,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the handler object. + ASIO_ASSUME(base != 0); reactive_wait_op* o(static_cast<reactive_wait_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -61,7 +64,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); // Make a copy of the handler so that the memory can be deallocated before @@ -85,6 +88,36 @@ public: } } + static void do_immediate(operation* base, bool, const void* io_ex) + { + // Take ownership of the handler object. + ASIO_ASSUME(base != 0); + reactive_wait_op* o(static_cast<reactive_wait_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + immediate_handler_work<Handler, IoExecutor> w( + static_cast<handler_work<Handler, IoExecutor>&&>( + o->work_)); + + // Make a copy of the handler so that the memory can be deallocated before + // the upcall is made. Even if we're not about to make an upcall, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + detail::binder1<Handler, asio::error_code> + handler(o->handler_, o->ec_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_)); + w.complete(handler, handler.handler_, io_ex); + ASIO_HANDLER_INVOCATION_END; + } + private: Handler handler_; handler_work<Handler, IoExecutor> work_; diff --git a/3rdparty/asio/include/asio/detail/reactor.hpp b/3rdparty/asio/include/asio/detail/reactor.hpp index 03a601c7d43..054acfdab00 100644 --- a/3rdparty/asio/include/asio/detail/reactor.hpp +++ b/3rdparty/asio/include/asio/detail/reactor.hpp @@ -2,7 +2,7 @@ // detail/reactor.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -15,18 +15,40 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/detail/reactor_fwd.hpp" +#include "asio/detail/config.hpp" -#if defined(ASIO_HAS_EPOLL) +#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME) +# include "asio/detail/null_reactor.hpp" +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/null_reactor.hpp" +#elif defined(ASIO_HAS_EPOLL) # include "asio/detail/epoll_reactor.hpp" #elif defined(ASIO_HAS_KQUEUE) # include "asio/detail/kqueue_reactor.hpp" #elif defined(ASIO_HAS_DEV_POLL) # include "asio/detail/dev_poll_reactor.hpp" -#elif defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME) -# include "asio/detail/null_reactor.hpp" #else # include "asio/detail/select_reactor.hpp" #endif +namespace asio { +namespace detail { + +#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME) +typedef null_reactor reactor; +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) +typedef null_reactor reactor; +#elif defined(ASIO_HAS_EPOLL) +typedef epoll_reactor reactor; +#elif defined(ASIO_HAS_KQUEUE) +typedef kqueue_reactor reactor; +#elif defined(ASIO_HAS_DEV_POLL) +typedef dev_poll_reactor reactor; +#else +typedef select_reactor reactor; +#endif + +} // namespace detail +} // namespace asio + #endif // ASIO_DETAIL_REACTOR_HPP diff --git a/3rdparty/asio/include/asio/detail/reactor_fwd.hpp b/3rdparty/asio/include/asio/detail/reactor_fwd.hpp deleted file mode 100644 index b9c084614ab..00000000000 --- a/3rdparty/asio/include/asio/detail/reactor_fwd.hpp +++ /dev/null @@ -1,40 +0,0 @@ -// -// detail/reactor_fwd.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_REACTOR_FWD_HPP -#define ASIO_DETAIL_REACTOR_FWD_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -namespace asio { -namespace detail { - -#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME) -typedef class null_reactor reactor; -#elif defined(ASIO_HAS_IOCP) -typedef class select_reactor reactor; -#elif defined(ASIO_HAS_EPOLL) -typedef class epoll_reactor reactor; -#elif defined(ASIO_HAS_KQUEUE) -typedef class kqueue_reactor reactor; -#elif defined(ASIO_HAS_DEV_POLL) -typedef class dev_poll_reactor reactor; -#else -typedef class select_reactor reactor; -#endif - -} // namespace detail -} // namespace asio - -#endif // ASIO_DETAIL_REACTOR_FWD_HPP diff --git a/3rdparty/asio/include/asio/detail/reactor_op.hpp b/3rdparty/asio/include/asio/detail/reactor_op.hpp index d38aa7e111e..54d6cd964eb 100644 --- a/3rdparty/asio/include/asio/detail/reactor_op.hpp +++ b/3rdparty/asio/include/asio/detail/reactor_op.hpp @@ -2,7 +2,7 @@ // detail/reactor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/reactor_op_queue.hpp b/3rdparty/asio/include/asio/detail/reactor_op_queue.hpp index 0eb4ca3293a..fae1a52d9e7 100644 --- a/3rdparty/asio/include/asio/detail/reactor_op_queue.hpp +++ b/3rdparty/asio/include/asio/detail/reactor_op_queue.hpp @@ -2,7 +2,7 @@ // detail/reactor_op_queue.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/recycling_allocator.hpp b/3rdparty/asio/include/asio/detail/recycling_allocator.hpp index 8ca2e2ba16b..d556f22a399 100644 --- a/3rdparty/asio/include/asio/detail/recycling_allocator.hpp +++ b/3rdparty/asio/include/asio/detail/recycling_allocator.hpp @@ -2,7 +2,7 @@ // detail/recycling_allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -50,7 +50,7 @@ public: { void* p = thread_info_base::allocate(Purpose(), thread_context::top_of_thread_call_stack(), - sizeof(T) * n, ASIO_ALIGNOF(T)); + sizeof(T) * n, alignof(T)); return static_cast<T*>(p); } diff --git a/3rdparty/asio/include/asio/detail/regex_fwd.hpp b/3rdparty/asio/include/asio/detail/regex_fwd.hpp index bde7402ee66..a5c6c0a9428 100644 --- a/3rdparty/asio/include/asio/detail/regex_fwd.hpp +++ b/3rdparty/asio/include/asio/detail/regex_fwd.hpp @@ -2,7 +2,7 @@ // detail/regex_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,18 +17,6 @@ #if defined(ASIO_HAS_BOOST_REGEX) -#include <boost/regex_fwd.hpp> -#include <boost/version.hpp> -#if BOOST_VERSION >= 107600 -# if defined(BOOST_REGEX_CXX03) -# include <boost/regex/v4/match_flags.hpp> -# else // defined(BOOST_REGEX_CXX03) -# include <boost/regex/v5/match_flags.hpp> -# endif // defined(BOOST_REGEX_CXX03) -#else // BOOST_VERSION >= 107600 -# include <boost/regex/v4/match_flags.hpp> -#endif // BOOST_VERSION >= 107600 - namespace boost { template <class BidiIterator> @@ -37,6 +25,9 @@ struct sub_match; template <class BidiIterator, class Allocator> class match_results; +template <class CharT, class Traits> +class basic_regex; + } // namespace boost #endif // defined(ASIO_HAS_BOOST_REGEX) diff --git a/3rdparty/asio/include/asio/detail/resolve_endpoint_op.hpp b/3rdparty/asio/include/asio/detail/resolve_endpoint_op.hpp index 998bbb8a8cf..c7cb2c4c101 100644 --- a/3rdparty/asio/include/asio/detail/resolve_endpoint_op.hpp +++ b/3rdparty/asio/include/asio/detail/resolve_endpoint_op.hpp @@ -2,7 +2,7 @@ // detail/resolve_endpoint_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,7 +19,6 @@ #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/resolve_op.hpp" @@ -60,7 +59,7 @@ public: cancel_token_(cancel_token), endpoint_(endpoint), scheduler_(sched), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -70,6 +69,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the operation object. + ASIO_ASSUME(base != 0); resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -99,7 +99,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); // Make a copy of the handler so that the memory can be deallocated diff --git a/3rdparty/asio/include/asio/detail/resolve_op.hpp b/3rdparty/asio/include/asio/detail/resolve_op.hpp index e0ac00bd746..5b41ad2fe68 100644 --- a/3rdparty/asio/include/asio/detail/resolve_op.hpp +++ b/3rdparty/asio/include/asio/detail/resolve_op.hpp @@ -2,7 +2,7 @@ // detail/resolve_op.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/resolve_query_op.hpp b/3rdparty/asio/include/asio/detail/resolve_query_op.hpp index 5a2ffa71a7b..b7f9e35cef0 100644 --- a/3rdparty/asio/include/asio/detail/resolve_query_op.hpp +++ b/3rdparty/asio/include/asio/detail/resolve_query_op.hpp @@ -2,7 +2,7 @@ // detail/resolve_query_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,7 +19,6 @@ #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/resolve_op.hpp" @@ -61,7 +60,7 @@ public: cancel_token_(cancel_token), query_(qry), scheduler_(sched), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex), addrinfo_(0) { @@ -78,6 +77,7 @@ public: std::size_t /*bytes_transferred*/) { // Take ownership of the operation object. + ASIO_ASSUME(base != 0); resolve_query_op* o(static_cast<resolve_query_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -104,7 +104,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); // Make a copy of the handler so that the memory can be deallocated diff --git a/3rdparty/asio/include/asio/detail/resolver_service.hpp b/3rdparty/asio/include/asio/detail/resolver_service.hpp index 006b35c7c5a..2d1fe22b62a 100644 --- a/3rdparty/asio/include/asio/detail/resolver_service.hpp +++ b/3rdparty/asio/include/asio/detail/resolver_service.hpp @@ -2,7 +2,7 @@ // detail/resolver_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -34,7 +34,7 @@ namespace detail { template <typename Protocol> class resolver_service : - public execution_context_service_base<resolver_service<Protocol> >, + public execution_context_service_base<resolver_service<Protocol>>, public resolver_service_base { public: @@ -53,7 +53,7 @@ public: // Constructor. resolver_service(execution_context& context) - : execution_context_service_base<resolver_service<Protocol> >(context), + : execution_context_service_base<resolver_service<Protocol>>(context), resolver_service_base(context) { } @@ -80,6 +80,7 @@ public: qry.service_name().c_str(), qry.hints(), &address_info, ec); auto_addrinfo auto_address_info(address_info); + ASIO_ERROR_LOCATION(ec); return ec ? results_type() : results_type::create( address_info, qry.host_name(), qry.service_name()); } @@ -112,6 +113,7 @@ public: host_name, NI_MAXHOST, service_name, NI_MAXSERV, endpoint.protocol().type(), ec); + ASIO_ERROR_LOCATION(ec); return ec ? results_type() : results_type::create( endpoint, host_name, service_name); } diff --git a/3rdparty/asio/include/asio/detail/resolver_service_base.hpp b/3rdparty/asio/include/asio/detail/resolver_service_base.hpp index 0df30f40607..160793c89cb 100644 --- a/3rdparty/asio/include/asio/detail/resolver_service_base.hpp +++ b/3rdparty/asio/include/asio/detail/resolver_service_base.hpp @@ -2,7 +2,7 @@ // detail/resolver_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/scheduler.hpp b/3rdparty/asio/include/asio/detail/scheduler.hpp index ce8a7e17b9b..a73ec141ebc 100644 --- a/3rdparty/asio/include/asio/detail/scheduler.hpp +++ b/3rdparty/asio/include/asio/detail/scheduler.hpp @@ -2,7 +2,7 @@ // detail/scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,8 +23,8 @@ #include "asio/detail/conditionally_enabled_event.hpp" #include "asio/detail/conditionally_enabled_mutex.hpp" #include "asio/detail/op_queue.hpp" -#include "asio/detail/reactor_fwd.hpp" #include "asio/detail/scheduler_operation.hpp" +#include "asio/detail/scheduler_task.hpp" #include "asio/detail/thread.hpp" #include "asio/detail/thread_context.hpp" @@ -42,10 +42,15 @@ class scheduler public: typedef scheduler_operation operation; + // The type of a function used to obtain a task instance. + typedef scheduler_task* (*get_task_func_type)( + asio::execution_context&); + // Constructor. Specifies the number of concurrent threads that are likely to // run the scheduler. If set to 1 certain optimisation are performed. ASIO_DECL scheduler(asio::execution_context& ctx, - int concurrency_hint = 0, bool own_thread = true); + int concurrency_hint = 0, bool own_thread = true, + get_task_func_type get_task = &scheduler::get_default_task); // Destructor. ASIO_DECL ~scheduler(); @@ -165,6 +170,10 @@ private: ASIO_DECL void wake_one_thread_and_unlock( mutex::scoped_lock& lock); + // Get the default task. + ASIO_DECL static scheduler_task* get_default_task( + asio::execution_context& ctx); + // Helper class to run the scheduler in its own thread. class thread_function; friend class thread_function; @@ -187,7 +196,10 @@ private: event wakeup_event_; // The task to be run by this service. - reactor* task_; + scheduler_task* task_; + + // The function used to get the task. + get_task_func_type get_task_; // Operation object to represent the position of the task in the queue. struct task_operation : operation diff --git a/3rdparty/asio/include/asio/detail/scheduler_operation.hpp b/3rdparty/asio/include/asio/detail/scheduler_operation.hpp index 1ca4964f540..1b4ceb36f5c 100644 --- a/3rdparty/asio/include/asio/detail/scheduler_operation.hpp +++ b/3rdparty/asio/include/asio/detail/scheduler_operation.hpp @@ -2,7 +2,7 @@ // detail/scheduler_operation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/scheduler_task.hpp b/3rdparty/asio/include/asio/detail/scheduler_task.hpp new file mode 100644 index 00000000000..a1a4ec1c85f --- /dev/null +++ b/3rdparty/asio/include/asio/detail/scheduler_task.hpp @@ -0,0 +1,49 @@ +// +// detail/scheduler_task.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_SCHEDULER_TASK_HPP +#define ASIO_DETAIL_SCHEDULER_TASK_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/op_queue.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class scheduler_operation; + +// Base class for all tasks that may be run by a scheduler. +class scheduler_task +{ +public: + // Run the task once until interrupted or events are ready to be dispatched. + virtual void run(long usec, op_queue<scheduler_operation>& ops) = 0; + + // Interrupt the task. + virtual void interrupt() = 0; + +protected: + // Prevent deletion through this type. + ~scheduler_task() + { + } +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_DETAIL_SCHEDULER_TASK_HPP diff --git a/3rdparty/asio/include/asio/detail/scheduler_thread_info.hpp b/3rdparty/asio/include/asio/detail/scheduler_thread_info.hpp index 3202e3c5792..410d2866b59 100644 --- a/3rdparty/asio/include/asio/detail/scheduler_thread_info.hpp +++ b/3rdparty/asio/include/asio/detail/scheduler_thread_info.hpp @@ -2,7 +2,7 @@ // detail/scheduler_thread_info.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/scoped_lock.hpp b/3rdparty/asio/include/asio/detail/scoped_lock.hpp index 273d702375a..778832d6350 100644 --- a/3rdparty/asio/include/asio/detail/scoped_lock.hpp +++ b/3rdparty/asio/include/asio/detail/scoped_lock.hpp @@ -2,7 +2,7 @@ // detail/scoped_lock.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/scoped_ptr.hpp b/3rdparty/asio/include/asio/detail/scoped_ptr.hpp index 2eab4c99a36..a517c2b947c 100644 --- a/3rdparty/asio/include/asio/detail/scoped_ptr.hpp +++ b/3rdparty/asio/include/asio/detail/scoped_ptr.hpp @@ -2,7 +2,7 @@ // detail/scoped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/select_interrupter.hpp b/3rdparty/asio/include/asio/detail/select_interrupter.hpp index a542373cc3b..57cb4ce8d71 100644 --- a/3rdparty/asio/include/asio/detail/select_interrupter.hpp +++ b/3rdparty/asio/include/asio/detail/select_interrupter.hpp @@ -2,7 +2,7 @@ // detail/select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/select_reactor.hpp b/3rdparty/asio/include/asio/detail/select_reactor.hpp index cb3e525a1d0..7fe647b7e63 100644 --- a/3rdparty/asio/include/asio/detail/select_reactor.hpp +++ b/3rdparty/asio/include/asio/detail/select_reactor.hpp @@ -2,7 +2,7 @@ // detail/select_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -30,6 +30,7 @@ #include "asio/detail/op_queue.hpp" #include "asio/detail/reactor_op.hpp" #include "asio/detail/reactor_op_queue.hpp" +#include "asio/detail/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp" @@ -48,6 +49,9 @@ namespace detail { class select_reactor : public execution_context_service_base<select_reactor> +#if !defined(ASIO_HAS_IOCP) + , public scheduler_task +#endif // !defined(ASIO_HAS_IOCP) { public: #if defined(ASIO_WINDOWS) || defined(__CYGWIN__) @@ -90,12 +94,29 @@ public: per_descriptor_data& descriptor_data, reactor_op* op); // Post a reactor operation for immediate completion. - void post_immediate_completion(reactor_op* op, bool is_continuation); + void post_immediate_completion(operation* op, bool is_continuation) const; + + // Post a reactor operation for immediate completion. + ASIO_DECL static void call_post_immediate_completion( + operation* op, bool is_continuation, const void* self); // Start a new operation. The reactor operation will be performed when the // given descriptor is flagged as ready, or an error has occurred. ASIO_DECL void start_op(int op_type, socket_type descriptor, - per_descriptor_data&, reactor_op* op, bool is_continuation, bool); + per_descriptor_data&, reactor_op* op, bool is_continuation, bool, + void (*on_immediate)(operation*, bool, const void*), + const void* immediate_arg); + + // Start a new operation. The reactor operation will be performed when the + // given descriptor is flagged as ready, or an error has occurred. + void start_op(int op_type, socket_type descriptor, + per_descriptor_data& descriptor_data, reactor_op* op, + bool is_continuation, bool allow_speculative) + { + start_op(op_type, descriptor, descriptor_data, + op, is_continuation, allow_speculative, + &select_reactor::call_post_immediate_completion, this); + } // Cancel all operations associated with the given descriptor. The // handlers associated with the descriptor will be invoked with the @@ -223,6 +244,28 @@ private: // The thread that is running the reactor loop. asio::detail::thread* thread_; + + // Helper class to join and restart the reactor thread. + class restart_reactor : public operation + { + public: + restart_reactor(select_reactor* r) + : operation(&restart_reactor::do_complete), + reactor_(r) + { + } + + ASIO_DECL static void do_complete(void* owner, operation* base, + const asio::error_code& ec, std::size_t bytes_transferred); + + private: + select_reactor* reactor_; + }; + + friend class restart_reactor; + + // Operation used to join and restart the reactor thread. + restart_reactor restart_reactor_; #endif // defined(ASIO_HAS_IOCP) // Whether the service has been shut down. diff --git a/3rdparty/asio/include/asio/detail/service_registry.hpp b/3rdparty/asio/include/asio/detail/service_registry.hpp index 2c7f4a52068..991b32a4980 100644 --- a/3rdparty/asio/include/asio/detail/service_registry.hpp +++ b/3rdparty/asio/include/asio/detail/service_registry.hpp @@ -2,7 +2,7 @@ // detail/service_registry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -84,8 +84,7 @@ private: // 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*); + enable_if_t<is_base_of<typename Service::key_type, Service>::value>*); #endif // !defined(ASIO_NO_TYPEID) // Initialise a service's key based on its id. diff --git a/3rdparty/asio/include/asio/detail/signal_blocker.hpp b/3rdparty/asio/include/asio/detail/signal_blocker.hpp index bbe7b3fedd5..11d0b0e9633 100644 --- a/3rdparty/asio/include/asio/detail/signal_blocker.hpp +++ b/3rdparty/asio/include/asio/detail/signal_blocker.hpp @@ -2,7 +2,7 @@ // detail/signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/signal_handler.hpp b/3rdparty/asio/include/asio/detail/signal_handler.hpp index 0153133f1de..6d43f578cb9 100644 --- a/3rdparty/asio/include/asio/detail/signal_handler.hpp +++ b/3rdparty/asio/include/asio/detail/signal_handler.hpp @@ -2,7 +2,7 @@ // detail/signal_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -36,7 +36,7 @@ public: signal_handler(Handler& h, const IoExecutor& io_ex) : signal_op(&signal_handler::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(h)), + handler_(static_cast<Handler&&>(h)), work_(handler_, io_ex) { } @@ -53,7 +53,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( h->work_)); // Make a copy of the handler so that the memory can be deallocated before diff --git a/3rdparty/asio/include/asio/detail/signal_init.hpp b/3rdparty/asio/include/asio/detail/signal_init.hpp index 80c7a7adc81..6f2c7c867e2 100644 --- a/3rdparty/asio/include/asio/detail/signal_init.hpp +++ b/3rdparty/asio/include/asio/detail/signal_init.hpp @@ -2,7 +2,7 @@ // detail/signal_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/signal_op.hpp b/3rdparty/asio/include/asio/detail/signal_op.hpp index 297c0d9fa76..5e0071a5d62 100644 --- a/3rdparty/asio/include/asio/detail/signal_op.hpp +++ b/3rdparty/asio/include/asio/detail/signal_op.hpp @@ -2,7 +2,7 @@ // detail/signal_op.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -30,12 +30,16 @@ public: // The error code to be passed to the completion handler. asio::error_code ec_; + // The operation key used for targeted cancellation. + void* cancellation_key_; + // The signal number to be passed to the completion handler. int signal_number_; protected: signal_op(func_type func) : operation(func), + cancellation_key_(0), signal_number_(0) { } diff --git a/3rdparty/asio/include/asio/detail/signal_set_service.hpp b/3rdparty/asio/include/asio/detail/signal_set_service.hpp index 7652fe20064..142ff43851a 100644 --- a/3rdparty/asio/include/asio/detail/signal_set_service.hpp +++ b/3rdparty/asio/include/asio/detail/signal_set_service.hpp @@ -2,7 +2,7 @@ // detail/signal_set_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,8 +19,11 @@ #include <cstddef> #include <signal.h> +#include "asio/associated_cancellation_slot.hpp" +#include "asio/cancellation_type.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" +#include "asio/signal_set_base.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/op_queue.hpp" @@ -35,7 +38,11 @@ #endif // defined(ASIO_HAS_IOCP) #if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__) -# include "asio/detail/reactor.hpp" +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/io_uring_service.hpp" +# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/reactor.hpp" +# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__) #include "asio/detail/push_options.hpp" @@ -134,8 +141,16 @@ public: ASIO_DECL void destroy(implementation_type& impl); // Add a signal to a signal_set. + asio::error_code add(implementation_type& impl, + int signal_number, asio::error_code& ec) + { + return add(impl, signal_number, signal_set_base::flags::dont_care, ec); + } + + // Add a signal to a signal_set with the specified flags. ASIO_DECL asio::error_code add(implementation_type& impl, - int signal_number, asio::error_code& ec); + int signal_number, signal_set_base::flags_t f, + asio::error_code& ec); // Remove a signal to a signal_set. ASIO_DECL asio::error_code remove(implementation_type& impl, @@ -149,17 +164,31 @@ public: ASIO_DECL asio::error_code cancel(implementation_type& impl, asio::error_code& ec); + // Cancel a specific operation associated with the signal set. + ASIO_DECL void cancel_ops_by_key(implementation_type& impl, + void* cancellation_key); + // Start an asynchronous operation to wait for a signal to be delivered. template <typename Handler, typename IoExecutor> void async_wait(implementation_type& impl, Handler& handler, const IoExecutor& io_ex) { + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + // Allocate and construct an operation to wrap the handler. typedef signal_handler<Handler, IoExecutor> op; typename op::ptr p = { asio::detail::addressof(handler), op::ptr::allocate(handler), 0 }; p.p = new (p.v) op(handler, io_ex); + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<signal_op_cancellation>(this, &impl); + } + ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "signal_set", &impl, 0, "async_wait")); @@ -186,6 +215,32 @@ private: // Helper function to start a wait operation. ASIO_DECL void start_wait_op(implementation_type& impl, signal_op* op); + // Helper class used to implement per-operation cancellation + class signal_op_cancellation + { + public: + signal_op_cancellation(signal_set_service* s, implementation_type* i) + : service_(s), + implementation_(i) + { + } + + void operator()(cancellation_type_t type) + { + if (!!(type & + (cancellation_type::terminal + | cancellation_type::partial + | cancellation_type::total))) + { + service_->cancel_ops_by_key(*implementation_, this); + } + } + + private: + signal_set_service* service_; + implementation_type* implementation_; + }; + // The scheduler used for dispatching handlers. #if defined(ASIO_HAS_IOCP) typedef class win_iocp_io_context scheduler_impl; @@ -197,14 +252,22 @@ private: #if !defined(ASIO_WINDOWS) \ && !defined(ASIO_WINDOWS_RUNTIME) \ && !defined(__CYGWIN__) - // The type used for registering for pipe reactor notifications. + // The type used for processing pipe readiness notifications. class pipe_read_op; +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + // The io_uring service used for waiting for pipe readiness. + io_uring_service& io_uring_service_; + + // The per I/O object data used for the pipe. + io_uring_service::per_io_object_data io_object_data_; +# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) // The reactor used for waiting for pipe readiness. reactor& reactor_; // The per-descriptor reactor data used for the pipe. reactor::per_descriptor_data reactor_data_; +# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) // && !defined(ASIO_WINDOWS_RUNTIME) // && !defined(__CYGWIN__) diff --git a/3rdparty/asio/include/asio/detail/socket_holder.hpp b/3rdparty/asio/include/asio/detail/socket_holder.hpp index 571b9f67c27..300e3736636 100644 --- a/3rdparty/asio/include/asio/detail/socket_holder.hpp +++ b/3rdparty/asio/include/asio/detail/socket_holder.hpp @@ -2,7 +2,7 @@ // detail/socket_holder.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/socket_ops.hpp b/3rdparty/asio/include/asio/detail/socket_ops.hpp index a37684e1c62..fd2dc09c094 100644 --- a/3rdparty/asio/include/asio/detail/socket_ops.hpp +++ b/3rdparty/asio/include/asio/detail/socket_ops.hpp @@ -2,7 +2,7 @@ // detail/socket_ops.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -63,29 +63,27 @@ typedef weak_ptr<void> weak_cancel_token_type; #if !defined(ASIO_WINDOWS_RUNTIME) -ASIO_DECL socket_type accept(socket_type s, socket_addr_type* addr, +ASIO_DECL socket_type accept(socket_type s, void* addr, std::size_t* addrlen, asio::error_code& ec); -ASIO_DECL socket_type sync_accept(socket_type s, - state_type state, socket_addr_type* addr, - std::size_t* addrlen, asio::error_code& ec); +ASIO_DECL socket_type sync_accept(socket_type s, state_type state, + void* addr, std::size_t* addrlen, asio::error_code& ec); #if defined(ASIO_HAS_IOCP) -ASIO_DECL void complete_iocp_accept(socket_type s, - void* output_buffer, DWORD address_length, - socket_addr_type* addr, std::size_t* addrlen, +ASIO_DECL void complete_iocp_accept(socket_type s, void* output_buffer, + DWORD address_length, void* addr, std::size_t* addrlen, socket_type new_socket, asio::error_code& ec); #else // defined(ASIO_HAS_IOCP) ASIO_DECL bool non_blocking_accept(socket_type s, - state_type state, socket_addr_type* addr, std::size_t* addrlen, + state_type state, void* addr, std::size_t* addrlen, asio::error_code& ec, socket_type& new_socket); #endif // defined(ASIO_HAS_IOCP) -ASIO_DECL int bind(socket_type s, const socket_addr_type* addr, +ASIO_DECL int bind(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec); ASIO_DECL int close(socket_type s, state_type& state, @@ -100,10 +98,10 @@ ASIO_DECL bool set_internal_non_blocking(socket_type s, ASIO_DECL int shutdown(socket_type s, int what, asio::error_code& ec); -ASIO_DECL int connect(socket_type s, const socket_addr_type* addr, +ASIO_DECL int connect(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec); -ASIO_DECL void sync_connect(socket_type s, const socket_addr_type* addr, +ASIO_DECL void sync_connect(socket_type s, const void* addr, std::size_t addrlen, asio::error_code& ec); #if defined(ASIO_HAS_IOCP) @@ -166,20 +164,20 @@ ASIO_DECL bool non_blocking_recv1(socket_type s, #endif // defined(ASIO_HAS_IOCP) -ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs, - size_t count, int flags, socket_addr_type* addr, +ASIO_DECL signed_size_type recvfrom(socket_type s, + buf* bufs, size_t count, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec); -ASIO_DECL signed_size_type recvfrom1(socket_type s, void* data, - size_t size, int flags, socket_addr_type* addr, +ASIO_DECL signed_size_type recvfrom1(socket_type s, + void* data, size_t size, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec); ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state, - buf* bufs, size_t count, int flags, socket_addr_type* addr, + buf* bufs, size_t count, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec); ASIO_DECL size_t sync_recvfrom1(socket_type s, state_type state, - void* data, size_t size, int flags, socket_addr_type* addr, + void* data, size_t size, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec); #if defined(ASIO_HAS_IOCP) @@ -190,14 +188,12 @@ ASIO_DECL void complete_iocp_recvfrom( #else // defined(ASIO_HAS_IOCP) -ASIO_DECL bool non_blocking_recvfrom(socket_type s, - buf* bufs, size_t count, int flags, - socket_addr_type* addr, std::size_t* addrlen, +ASIO_DECL bool non_blocking_recvfrom(socket_type s, buf* bufs, + size_t count, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec, size_t& bytes_transferred); -ASIO_DECL bool non_blocking_recvfrom1(socket_type s, - void* data, size_t size, int flags, - socket_addr_type* addr, std::size_t* addrlen, +ASIO_DECL bool non_blocking_recvfrom1(socket_type s, void* data, + size_t size, int flags, void* addr, std::size_t* addrlen, asio::error_code& ec, size_t& bytes_transferred); #endif // defined(ASIO_HAS_IOCP) @@ -255,32 +251,30 @@ ASIO_DECL bool non_blocking_send1(socket_type s, #endif // defined(ASIO_HAS_IOCP) -ASIO_DECL signed_size_type sendto(socket_type s, const buf* bufs, - size_t count, int flags, const socket_addr_type* addr, +ASIO_DECL signed_size_type sendto(socket_type s, + const buf* bufs, size_t count, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec); -ASIO_DECL signed_size_type sendto1(socket_type s, const void* data, - size_t size, int flags, const socket_addr_type* addr, +ASIO_DECL signed_size_type sendto1(socket_type s, + const void* data, size_t size, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec); ASIO_DECL size_t sync_sendto(socket_type s, state_type state, - const buf* bufs, size_t count, int flags, const socket_addr_type* addr, + const buf* bufs, size_t count, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec); ASIO_DECL size_t sync_sendto1(socket_type s, state_type state, - const void* data, size_t size, int flags, const socket_addr_type* addr, + const void* data, size_t size, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec); #if !defined(ASIO_HAS_IOCP) -ASIO_DECL bool non_blocking_sendto(socket_type s, - const buf* bufs, size_t count, int flags, - const socket_addr_type* addr, std::size_t addrlen, +ASIO_DECL bool non_blocking_sendto(socket_type s, const buf* bufs, + size_t count, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec, size_t& bytes_transferred); -ASIO_DECL bool non_blocking_sendto1(socket_type s, - const void* data, size_t size, int flags, - const socket_addr_type* addr, std::size_t addrlen, +ASIO_DECL bool non_blocking_sendto1(socket_type s, const void* data, + size_t size, int flags, const void* addr, std::size_t addrlen, asio::error_code& ec, size_t& bytes_transferred); #endif // !defined(ASIO_HAS_IOCP) @@ -296,10 +290,10 @@ ASIO_DECL int getsockopt(socket_type s, state_type state, int level, int optname, void* optval, size_t* optlen, asio::error_code& ec); -ASIO_DECL int getpeername(socket_type s, socket_addr_type* addr, +ASIO_DECL int getpeername(socket_type s, void* addr, std::size_t* addrlen, bool cached, asio::error_code& ec); -ASIO_DECL int getsockname(socket_type s, socket_addr_type* addr, +ASIO_DECL int getsockname(socket_type s, void* addr, std::size_t* addrlen, asio::error_code& ec); ASIO_DECL int ioctl(socket_type s, state_type& state, @@ -344,19 +338,17 @@ ASIO_DECL asio::error_code background_getaddrinfo( ASIO_DECL void freeaddrinfo(addrinfo_type* ai); -ASIO_DECL asio::error_code getnameinfo( - const socket_addr_type* addr, std::size_t addrlen, - char* host, std::size_t hostlen, char* serv, +ASIO_DECL asio::error_code getnameinfo(const void* addr, + std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int flags, asio::error_code& ec); -ASIO_DECL asio::error_code sync_getnameinfo( - const socket_addr_type* addr, std::size_t addrlen, - char* host, std::size_t hostlen, char* serv, +ASIO_DECL asio::error_code sync_getnameinfo(const void* addr, + std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int sock_type, asio::error_code& ec); ASIO_DECL asio::error_code background_getnameinfo( const weak_cancel_token_type& cancel_token, - const socket_addr_type* addr, std::size_t addrlen, + const void* addr, std::size_t addrlen, char* host, std::size_t hostlen, char* serv, std::size_t servlen, int sock_type, asio::error_code& ec); diff --git a/3rdparty/asio/include/asio/detail/socket_option.hpp b/3rdparty/asio/include/asio/detail/socket_option.hpp index 8d8c0d84f47..760713daad8 100644 --- a/3rdparty/asio/include/asio/detail/socket_option.hpp +++ b/3rdparty/asio/include/asio/detail/socket_option.hpp @@ -2,7 +2,7 @@ // detail/socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/socket_select_interrupter.hpp b/3rdparty/asio/include/asio/detail/socket_select_interrupter.hpp index 2e971d2005e..e2432622e47 100644 --- a/3rdparty/asio/include/asio/detail/socket_select_interrupter.hpp +++ b/3rdparty/asio/include/asio/detail/socket_select_interrupter.hpp @@ -2,7 +2,7 @@ // detail/socket_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/socket_types.hpp b/3rdparty/asio/include/asio/detail/socket_types.hpp index 33ad63eec8e..cf4f746a44b 100644 --- a/3rdparty/asio/include/asio/detail/socket_types.hpp +++ b/3rdparty/asio/include/asio/detail/socket_types.hpp @@ -2,7 +2,7 @@ // detail/socket_types.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -89,6 +89,7 @@ # include <sys/filio.h> # include <sys/sockio.h> # endif +# include <signal.h> #endif #include "asio/detail/push_options.hpp" @@ -178,6 +179,9 @@ typedef int signed_size_type; # define ASIO_OS_DEF_AI_V4MAPPED 0x800 # define ASIO_OS_DEF_AI_ALL 0x100 # define ASIO_OS_DEF_AI_ADDRCONFIG 0x400 +# define ASIO_OS_DEF_SA_RESTART 0x1 +# define ASIO_OS_DEF_SA_NOCLDSTOP 0x2 +# define ASIO_OS_DEF_SA_NOCLDWAIT 0x4 #elif defined(ASIO_WINDOWS) || defined(__CYGWIN__) typedef SOCKET socket_type; const SOCKET invalid_socket = INVALID_SOCKET; @@ -285,6 +289,9 @@ const int max_iov_len = 64; # else const int max_iov_len = 16; # endif +# define ASIO_OS_DEF_SA_RESTART 0x1 +# define ASIO_OS_DEF_SA_NOCLDSTOP 0x2 +# define ASIO_OS_DEF_SA_NOCLDWAIT 0x4 #else typedef int socket_type; const int invalid_socket = -1; @@ -404,6 +411,9 @@ const int max_iov_len = IOV_MAX; // POSIX platforms are not required to define IOV_MAX. const int max_iov_len = 16; # endif +# define ASIO_OS_DEF_SA_RESTART SA_RESTART +# define ASIO_OS_DEF_SA_NOCLDSTOP SA_NOCLDSTOP +# define ASIO_OS_DEF_SA_NOCLDWAIT SA_NOCLDWAIT #endif const int custom_socket_option_level = 0xA5100000; const int enable_connection_aborted_option = 1; diff --git a/3rdparty/asio/include/asio/detail/solaris_fenced_block.hpp b/3rdparty/asio/include/asio/detail/solaris_fenced_block.hpp deleted file mode 100644 index 4f6640b3d04..00000000000 --- a/3rdparty/asio/include/asio/detail/solaris_fenced_block.hpp +++ /dev/null @@ -1,62 +0,0 @@ -// -// detail/solaris_fenced_block.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_SOLARIS_FENCED_BLOCK_HPP -#define ASIO_DETAIL_SOLARIS_FENCED_BLOCK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#if defined(__sun) - -#include <atomic.h> -#include "asio/detail/noncopyable.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class solaris_fenced_block - : private noncopyable -{ -public: - enum half_t { half }; - enum full_t { full }; - - // Constructor for a half fenced block. - explicit solaris_fenced_block(half_t) - { - } - - // Constructor for a full fenced block. - explicit solaris_fenced_block(full_t) - { - membar_consumer(); - } - - // Destructor. - ~solaris_fenced_block() - { - membar_producer(); - } -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // defined(__sun) - -#endif // ASIO_DETAIL_SOLARIS_FENCED_BLOCK_HPP diff --git a/3rdparty/asio/include/asio/detail/source_location.hpp b/3rdparty/asio/include/asio/detail/source_location.hpp index a9ac8e83514..14b74f91435 100644 --- a/3rdparty/asio/include/asio/detail/source_location.hpp +++ b/3rdparty/asio/include/asio/detail/source_location.hpp @@ -2,7 +2,7 @@ // detail/source_location.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/static_mutex.hpp b/3rdparty/asio/include/asio/detail/static_mutex.hpp index 5876a99a800..b47d087bf4a 100644 --- a/3rdparty/asio/include/asio/detail/static_mutex.hpp +++ b/3rdparty/asio/include/asio/detail/static_mutex.hpp @@ -2,7 +2,7 @@ // detail/static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,10 +23,8 @@ # include "asio/detail/win_static_mutex.hpp" #elif defined(ASIO_HAS_PTHREADS) # include "asio/detail/posix_static_mutex.hpp" -#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) -# include "asio/detail/std_static_mutex.hpp" #else -# error Only Windows and POSIX are supported! +# include "asio/detail/std_static_mutex.hpp" #endif namespace asio { @@ -41,7 +39,7 @@ typedef win_static_mutex static_mutex; #elif defined(ASIO_HAS_PTHREADS) typedef posix_static_mutex static_mutex; # define ASIO_STATIC_MUTEX_INIT ASIO_POSIX_STATIC_MUTEX_INIT -#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) +#else typedef std_static_mutex static_mutex; # define ASIO_STATIC_MUTEX_INIT ASIO_STD_STATIC_MUTEX_INIT #endif diff --git a/3rdparty/asio/include/asio/detail/std_event.hpp b/3rdparty/asio/include/asio/detail/std_event.hpp index 1fc5177ed8f..97a347ed725 100644 --- a/3rdparty/asio/include/asio/detail/std_event.hpp +++ b/3rdparty/asio/include/asio/detail/std_event.hpp @@ -2,7 +2,7 @@ // detail/std_event.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) - #include <chrono> #include <condition_variable> #include "asio/detail/assert.hpp" @@ -183,6 +180,4 @@ private: #include "asio/detail/pop_options.hpp" -#endif // defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) - #endif // ASIO_DETAIL_STD_EVENT_HPP diff --git a/3rdparty/asio/include/asio/detail/std_fenced_block.hpp b/3rdparty/asio/include/asio/detail/std_fenced_block.hpp index 2361b17fdfd..d1e0c603cbc 100644 --- a/3rdparty/asio/include/asio/detail/std_fenced_block.hpp +++ b/3rdparty/asio/include/asio/detail/std_fenced_block.hpp @@ -2,7 +2,7 @@ // detail/std_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_STD_ATOMIC) - #include <atomic> #include "asio/detail/noncopyable.hpp" @@ -57,6 +54,4 @@ public: #include "asio/detail/pop_options.hpp" -#endif // defined(ASIO_HAS_STD_ATOMIC) - #endif // ASIO_DETAIL_STD_FENCED_BLOCK_HPP diff --git a/3rdparty/asio/include/asio/detail/std_global.hpp b/3rdparty/asio/include/asio/detail/std_global.hpp index cdb3062079b..49ae055ea7d 100644 --- a/3rdparty/asio/include/asio/detail/std_global.hpp +++ b/3rdparty/asio/include/asio/detail/std_global.hpp @@ -2,7 +2,7 @@ // detail/std_global.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_STD_CALL_ONCE) - #include <exception> #include <mutex> @@ -65,6 +62,4 @@ T& std_global() #include "asio/detail/pop_options.hpp" -#endif // defined(ASIO_HAS_STD_CALL_ONCE) - #endif // ASIO_DETAIL_STD_GLOBAL_HPP diff --git a/3rdparty/asio/include/asio/detail/std_mutex.hpp b/3rdparty/asio/include/asio/detail/std_mutex.hpp index 37471bebad5..06839d69ca3 100644 --- a/3rdparty/asio/include/asio/detail/std_mutex.hpp +++ b/3rdparty/asio/include/asio/detail/std_mutex.hpp @@ -2,7 +2,7 @@ // detail/std_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) - #include <mutex> #include "asio/detail/noncopyable.hpp" #include "asio/detail/scoped_lock.hpp" @@ -68,6 +65,4 @@ private: #include "asio/detail/pop_options.hpp" -#endif // defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) - #endif // ASIO_DETAIL_STD_MUTEX_HPP diff --git a/3rdparty/asio/include/asio/detail/std_static_mutex.hpp b/3rdparty/asio/include/asio/detail/std_static_mutex.hpp index ce14133f5ee..302b729037d 100644 --- a/3rdparty/asio/include/asio/detail/std_static_mutex.hpp +++ b/3rdparty/asio/include/asio/detail/std_static_mutex.hpp @@ -2,7 +2,7 @@ // detail/std_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) - #include <mutex> #include "asio/detail/noncopyable.hpp" #include "asio/detail/scoped_lock.hpp" @@ -76,6 +73,4 @@ private: #include "asio/detail/pop_options.hpp" -#endif // defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR) - #endif // ASIO_DETAIL_STD_STATIC_MUTEX_HPP diff --git a/3rdparty/asio/include/asio/detail/std_thread.hpp b/3rdparty/asio/include/asio/detail/std_thread.hpp index 00cd4c902a7..78bbab9ea10 100644 --- a/3rdparty/asio/include/asio/detail/std_thread.hpp +++ b/3rdparty/asio/include/asio/detail/std_thread.hpp @@ -2,7 +2,7 @@ // detail/std_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_STD_THREAD) - #include <thread> #include "asio/detail/noncopyable.hpp" @@ -66,6 +63,4 @@ private: #include "asio/detail/pop_options.hpp" -#endif // defined(ASIO_HAS_STD_THREAD) - #endif // ASIO_DETAIL_STD_THREAD_HPP diff --git a/3rdparty/asio/include/asio/detail/strand_executor_service.hpp b/3rdparty/asio/include/asio/detail/strand_executor_service.hpp index cdbea6ba55b..45536ed5368 100644 --- a/3rdparty/asio/include/asio/detail/strand_executor_service.hpp +++ b/3rdparty/asio/include/asio/detail/strand_executor_service.hpp @@ -2,7 +2,7 @@ // detail/strand_executor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -90,33 +90,33 @@ public: // Request invocation of the given function. template <typename Executor, typename Function> static void execute(const implementation_type& impl, Executor& ex, - ASIO_MOVE_ARG(Function) function, - typename enable_if< - can_query<Executor, execution::allocator_t<void> >::value - >::type* = 0); + Function&& function, + enable_if_t< + can_query<Executor, execution::allocator_t<void>>::value + >* = 0); // Request invocation of the given function. template <typename Executor, typename Function> static void execute(const implementation_type& impl, Executor& ex, - ASIO_MOVE_ARG(Function) function, - typename enable_if< - !can_query<Executor, execution::allocator_t<void> >::value - >::type* = 0); + Function&& function, + enable_if_t< + !can_query<Executor, execution::allocator_t<void>>::value + >* = 0); // Request invocation of the given function. template <typename Executor, typename Function, typename Allocator> static void dispatch(const implementation_type& impl, Executor& ex, - ASIO_MOVE_ARG(Function) function, const Allocator& a); + 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, - ASIO_MOVE_ARG(Function) function, const Allocator& a); + 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, - ASIO_MOVE_ARG(Function) function, const Allocator& a); + Function&& function, const Allocator& a); // Determine whether the strand is running in the current thread. ASIO_DECL static bool running_in_this_thread( @@ -141,7 +141,7 @@ private: // Helper function to request invocation of the given function. template <typename Executor, typename Function, typename Allocator> static void do_execute(const implementation_type& impl, Executor& ex, - ASIO_MOVE_ARG(Function) function, const Allocator& a); + Function&& function, const Allocator& a); // Mutex to protect access to the service-wide state. mutex mutex_; diff --git a/3rdparty/asio/include/asio/detail/strand_service.hpp b/3rdparty/asio/include/asio/detail/strand_service.hpp index 2aec8e5d450..084eb0b3066 100644 --- a/3rdparty/asio/include/asio/detail/strand_service.hpp +++ b/3rdparty/asio/include/asio/detail/strand_service.hpp @@ -2,7 +2,7 @@ // detail/strand_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/string_view.hpp b/3rdparty/asio/include/asio/detail/string_view.hpp index 488e9aa5a59..a4470f1e580 100644 --- a/3rdparty/asio/include/asio/detail/string_view.hpp +++ b/3rdparty/asio/include/asio/detail/string_view.hpp @@ -2,7 +2,7 @@ // detail/string_view.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/thread.hpp b/3rdparty/asio/include/asio/detail/thread.hpp index 8d1b66283db..faa7fad2438 100644 --- a/3rdparty/asio/include/asio/detail/thread.hpp +++ b/3rdparty/asio/include/asio/detail/thread.hpp @@ -2,7 +2,7 @@ // detail/thread.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -29,10 +29,8 @@ # else # include "asio/detail/win_thread.hpp" # endif -#elif defined(ASIO_HAS_STD_THREAD) -# include "asio/detail/std_thread.hpp" #else -# error Only Windows, POSIX and std::thread are supported! +# include "asio/detail/std_thread.hpp" #endif namespace asio { @@ -50,7 +48,7 @@ typedef winapp_thread thread; # else typedef win_thread thread; # endif -#elif defined(ASIO_HAS_STD_THREAD) +#else typedef std_thread thread; #endif diff --git a/3rdparty/asio/include/asio/detail/thread_context.hpp b/3rdparty/asio/include/asio/detail/thread_context.hpp index f17824182b4..bebfc4a43a2 100644 --- a/3rdparty/asio/include/asio/detail/thread_context.hpp +++ b/3rdparty/asio/include/asio/detail/thread_context.hpp @@ -2,7 +2,7 @@ // detail/thread_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/thread_group.hpp b/3rdparty/asio/include/asio/detail/thread_group.hpp index 11965f5a7f2..5ebff5e185f 100644 --- a/3rdparty/asio/include/asio/detail/thread_group.hpp +++ b/3rdparty/asio/include/asio/detail/thread_group.hpp @@ -2,7 +2,7 @@ // detail/thread_group.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/thread_info_base.hpp b/3rdparty/asio/include/asio/detail/thread_info_base.hpp index 2223e8b3faf..5a74cef776a 100644 --- a/3rdparty/asio/include/asio/detail/thread_info_base.hpp +++ b/3rdparty/asio/include/asio/detail/thread_info_base.hpp @@ -2,7 +2,7 @@ // detail/thread_info_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -21,12 +21,10 @@ #include "asio/detail/memory.hpp" #include "asio/detail/noncopyable.hpp" -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \ - && !defined(ASIO_NO_EXCEPTIONS) +#if !defined(ASIO_NO_EXCEPTIONS) # include <exception> # include "asio/multiple_exceptions.hpp" -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - // && !defined(ASIO_NO_EXCEPTIONS) +#endif // !defined(ASIO_NO_EXCEPTIONS) #include "asio/detail/push_options.hpp" @@ -94,11 +92,9 @@ public: enum { max_mem_index = parallel_group_tag::end_mem_index }; thread_info_base() -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \ - && !defined(ASIO_NO_EXCEPTIONS) +#if !defined(ASIO_NO_EXCEPTIONS) : has_pending_exception_(0) -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - // && !defined(ASIO_NO_EXCEPTIONS) +#endif // !defined(ASIO_NO_EXCEPTIONS) { for (int i = 0; i < max_mem_index; ++i) reusable_memory_[i] = 0; @@ -199,8 +195,7 @@ public: void capture_current_exception() { -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \ - && !defined(ASIO_NO_EXCEPTIONS) +#if !defined(ASIO_NO_EXCEPTIONS) switch (has_pending_exception_) { case 0: @@ -216,36 +211,35 @@ public: default: break; } -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - // && !defined(ASIO_NO_EXCEPTIONS) +#endif // !defined(ASIO_NO_EXCEPTIONS) } void rethrow_pending_exception() { -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \ - && !defined(ASIO_NO_EXCEPTIONS) +#if !defined(ASIO_NO_EXCEPTIONS) if (has_pending_exception_ > 0) { has_pending_exception_ = 0; std::exception_ptr ex( - ASIO_MOVE_CAST(std::exception_ptr)( + static_cast<std::exception_ptr&&>( pending_exception_)); std::rethrow_exception(ex); } -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - // && !defined(ASIO_NO_EXCEPTIONS) +#endif // !defined(ASIO_NO_EXCEPTIONS) } private: +#if defined(ASIO_HAS_IO_URING) + enum { chunk_size = 8 }; +#else // defined(ASIO_HAS_IO_URING) enum { chunk_size = 4 }; +#endif // defined(ASIO_HAS_IO_URING) void* reusable_memory_[max_mem_index]; -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \ - && !defined(ASIO_NO_EXCEPTIONS) +#if !defined(ASIO_NO_EXCEPTIONS) int has_pending_exception_; std::exception_ptr pending_exception_; -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - // && !defined(ASIO_NO_EXCEPTIONS) +#endif // !defined(ASIO_NO_EXCEPTIONS) }; } // namespace detail diff --git a/3rdparty/asio/include/asio/detail/throw_error.hpp b/3rdparty/asio/include/asio/detail/throw_error.hpp index d03cad54acd..881c3128576 100644 --- a/3rdparty/asio/include/asio/detail/throw_error.hpp +++ b/3rdparty/asio/include/asio/detail/throw_error.hpp @@ -2,7 +2,7 @@ // detail/throw_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" +#include "asio/detail/throw_exception.hpp" #include "asio/error_code.hpp" #include "asio/detail/push_options.hpp" @@ -23,22 +24,30 @@ namespace asio { namespace detail { -ASIO_DECL void do_throw_error(const asio::error_code& err); +ASIO_DECL void do_throw_error( + const asio::error_code& err + ASIO_SOURCE_LOCATION_PARAM); -ASIO_DECL void do_throw_error(const asio::error_code& err, - const char* location); +ASIO_DECL void do_throw_error( + const asio::error_code& err, + const char* location + ASIO_SOURCE_LOCATION_PARAM); -inline void throw_error(const asio::error_code& err) +inline void throw_error( + const asio::error_code& err + ASIO_SOURCE_LOCATION_DEFAULTED_PARAM) { if (err) - do_throw_error(err); + do_throw_error(err ASIO_SOURCE_LOCATION_ARG); } -inline void throw_error(const asio::error_code& err, - const char* location) +inline void throw_error( + const asio::error_code& err, + const char* location + ASIO_SOURCE_LOCATION_DEFAULTED_PARAM) { if (err) - do_throw_error(err, location); + do_throw_error(err, location ASIO_SOURCE_LOCATION_ARG); } } // namespace detail diff --git a/3rdparty/asio/include/asio/detail/throw_exception.hpp b/3rdparty/asio/include/asio/detail/throw_exception.hpp index bbee22ae963..e939c1093f6 100644 --- a/3rdparty/asio/include/asio/detail/throw_exception.hpp +++ b/3rdparty/asio/include/asio/detail/throw_exception.hpp @@ -2,7 +2,7 @@ // detail/throw_exception.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -30,14 +30,18 @@ using boost::throw_exception; // Declare the throw_exception function for all targets. template <typename Exception> -void throw_exception(const Exception& e); +void throw_exception( + const Exception& e + ASIO_SOURCE_LOCATION_DEFAULTED_PARAM); // Only define the throw_exception function when exceptions are enabled. // Otherwise, it is up to the application to provide a definition of this // function. # if !defined(ASIO_NO_EXCEPTIONS) template <typename Exception> -void throw_exception(const Exception& e) +void throw_exception( + const Exception& e + ASIO_SOURCE_LOCATION_PARAM) { throw e; } diff --git a/3rdparty/asio/include/asio/detail/timer_queue.hpp b/3rdparty/asio/include/asio/detail/timer_queue.hpp index cb5f4fc3caa..843f3614da0 100644 --- a/3rdparty/asio/include/asio/detail/timer_queue.hpp +++ b/3rdparty/asio/include/asio/detail/timer_queue.hpp @@ -2,7 +2,7 @@ // detail/timer_queue.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/timer_queue_base.hpp b/3rdparty/asio/include/asio/detail/timer_queue_base.hpp index 7ab2e6d40a5..ddcf41c1371 100644 --- a/3rdparty/asio/include/asio/detail/timer_queue_base.hpp +++ b/3rdparty/asio/include/asio/detail/timer_queue_base.hpp @@ -2,7 +2,7 @@ // detail/timer_queue_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/timer_queue_ptime.hpp b/3rdparty/asio/include/asio/detail/timer_queue_ptime.hpp index 0886ac96f85..937a4ad85fa 100644 --- a/3rdparty/asio/include/asio/detail/timer_queue_ptime.hpp +++ b/3rdparty/asio/include/asio/detail/timer_queue_ptime.hpp @@ -2,7 +2,7 @@ // detail/timer_queue_ptime.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -31,7 +31,7 @@ struct forwarding_posix_time_traits : time_traits<boost::posix_time::ptime> {}; // Template specialisation for the commonly used instantation. template <> -class timer_queue<time_traits<boost::posix_time::ptime> > +class timer_queue<time_traits<boost::posix_time::ptime>> : public timer_queue_base { public: diff --git a/3rdparty/asio/include/asio/detail/timer_queue_set.hpp b/3rdparty/asio/include/asio/detail/timer_queue_set.hpp index 2cd3826c7d8..7bf50747be1 100644 --- a/3rdparty/asio/include/asio/detail/timer_queue_set.hpp +++ b/3rdparty/asio/include/asio/detail/timer_queue_set.hpp @@ -2,7 +2,7 @@ // detail/timer_queue_set.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/timer_scheduler.hpp b/3rdparty/asio/include/asio/detail/timer_scheduler.hpp index 8d9b4ed7c93..dd34d328c84 100644 --- a/3rdparty/asio/include/asio/detail/timer_scheduler.hpp +++ b/3rdparty/asio/include/asio/detail/timer_scheduler.hpp @@ -2,7 +2,7 @@ // detail/timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,6 +22,8 @@ # include "asio/detail/winrt_timer_scheduler.hpp" #elif defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_io_context.hpp" +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/io_uring_service.hpp" #elif defined(ASIO_HAS_EPOLL) # include "asio/detail/epoll_reactor.hpp" #elif defined(ASIO_HAS_KQUEUE) diff --git a/3rdparty/asio/include/asio/detail/timer_scheduler_fwd.hpp b/3rdparty/asio/include/asio/detail/timer_scheduler_fwd.hpp index 15b5fbdffa1..bbb8a4e8ded 100644 --- a/3rdparty/asio/include/asio/detail/timer_scheduler_fwd.hpp +++ b/3rdparty/asio/include/asio/detail/timer_scheduler_fwd.hpp @@ -2,7 +2,7 @@ // detail/timer_scheduler_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -24,6 +24,8 @@ namespace detail { typedef class winrt_timer_scheduler timer_scheduler; #elif defined(ASIO_HAS_IOCP) typedef class win_iocp_io_context timer_scheduler; +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) +typedef class io_uring_service timer_scheduler; #elif defined(ASIO_HAS_EPOLL) typedef class epoll_reactor timer_scheduler; #elif defined(ASIO_HAS_KQUEUE) diff --git a/3rdparty/asio/include/asio/detail/tss_ptr.hpp b/3rdparty/asio/include/asio/detail/tss_ptr.hpp index 25e4d3d84d1..f7aaa2ec29c 100644 --- a/3rdparty/asio/include/asio/detail/tss_ptr.hpp +++ b/3rdparty/asio/include/asio/detail/tss_ptr.hpp @@ -2,7 +2,7 @@ // detail/tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/type_traits.hpp b/3rdparty/asio/include/asio/detail/type_traits.hpp index 968f19a802e..a4706a5ff1c 100644 --- a/3rdparty/asio/include/asio/detail/type_traits.hpp +++ b/3rdparty/asio/include/asio/detail/type_traits.hpp @@ -2,7 +2,7 @@ // detail/type_traits.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,140 +16,162 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_STD_TYPE_TRAITS) -# include <type_traits> -#else // defined(ASIO_HAS_STD_TYPE_TRAITS) -# include <boost/type_traits/add_const.hpp> -# include <boost/type_traits/add_lvalue_reference.hpp> -# include <boost/type_traits/aligned_storage.hpp> -# include <boost/type_traits/alignment_of.hpp> -# include <boost/type_traits/conditional.hpp> -# include <boost/type_traits/decay.hpp> -# include <boost/type_traits/has_nothrow_copy.hpp> -# include <boost/type_traits/has_nothrow_destructor.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_constructible.hpp> -# include <boost/type_traits/is_copy_constructible.hpp> -# include <boost/type_traits/is_destructible.hpp> -# include <boost/type_traits/is_function.hpp> -# include <boost/type_traits/is_object.hpp> -# include <boost/type_traits/is_same.hpp> -# include <boost/type_traits/remove_cv.hpp> -# include <boost/type_traits/remove_pointer.hpp> -# include <boost/type_traits/remove_reference.hpp> -# include <boost/utility/declval.hpp> -# include <boost/utility/enable_if.hpp> -# include <boost/utility/result_of.hpp> -#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) +#include <type_traits> namespace asio { -#if defined(ASIO_HAS_STD_TYPE_TRAITS) using std::add_const; + +template <typename T> +using add_const_t = typename std::add_const<T>::type; + using std::add_lvalue_reference; -using std::aligned_storage; + +template <typename T> +using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type; + +template <std::size_t N, std::size_t A> +struct aligned_storage +{ + struct type + { + alignas(A) unsigned char data[N]; + }; +}; + +template <std::size_t N, std::size_t A> +using aligned_storage_t = typename aligned_storage<N, A>::type; + using std::alignment_of; + using std::conditional; + +template <bool C, typename T, typename U> +using conditional_t = typename std::conditional<C, T, U>::type; + using std::decay; + +template <typename T> +using decay_t = typename std::decay<T>::type; + using std::declval; + using std::enable_if; + +template <bool C, typename T = void> +using enable_if_t = typename std::enable_if<C, T>::type; + using std::false_type; + using std::integral_constant; + using std::is_base_of; + using std::is_class; + using std::is_const; + using std::is_constructible; + using std::is_convertible; + using std::is_copy_constructible; + using std::is_destructible; + using std::is_function; + using std::is_move_constructible; + using std::is_nothrow_copy_constructible; + using std::is_nothrow_destructible; + using std::is_object; + +using std::is_pointer; + using std::is_reference; + using std::is_same; + using std::is_scalar; + using std::remove_cv; + +template <typename T> +using remove_cv_t = typename std::remove_cv<T>::type; + +template <typename T> +struct remove_cvref : + std::remove_cv<typename std::remove_reference<T>::type> {}; + template <typename T> -struct remove_cvref : remove_cv<typename std::remove_reference<T>::type> {}; +using remove_cvref_t = typename remove_cvref<T>::type; + using std::remove_pointer; + +template <typename T> +using remove_pointer_t = typename std::remove_pointer<T>::type; + using std::remove_reference; + +template <typename T> +using remove_reference_t = typename std::remove_reference<T>::type; + #if defined(ASIO_HAS_STD_INVOKE_RESULT) + template <typename> struct result_of; + template <typename F, typename... Args> struct result_of<F(Args...)> : std::invoke_result<F, Args...> {}; + +template <typename T> +using result_of_t = typename result_of<T>::type; + #else // defined(ASIO_HAS_STD_INVOKE_RESULT) + using std::result_of; + +template <typename T> +using result_of_t = typename std::result_of<T>::type; + #endif // defined(ASIO_HAS_STD_INVOKE_RESULT) + using std::true_type; -#else // defined(ASIO_HAS_STD_TYPE_TRAITS) -using boost::add_const; -using boost::add_lvalue_reference; -using boost::aligned_storage; -using boost::alignment_of; -template <bool Condition, typename Type = void> -struct enable_if : boost::enable_if_c<Condition, Type> {}; -using boost::conditional; -using boost::decay; -using boost::declval; -using boost::false_type; -using boost::integral_constant; -using boost::is_base_of; -using boost::is_class; -using boost::is_const; -using boost::is_constructible; -using boost::is_convertible; -using boost::is_copy_constructible; -using boost::is_destructible; -using boost::is_function; -#if defined(ASIO_HAS_MOVE) -template <typename T> -struct is_move_constructible : false_type {}; -#else // defined(ASIO_HAS_MOVE) -template <typename T> -struct is_move_constructible : is_copy_constructible<T> {}; -#endif // defined(ASIO_HAS_MOVE) -template <typename T> -struct is_nothrow_copy_constructible : boost::has_nothrow_copy<T> {}; -template <typename T> -struct is_nothrow_destructible : boost::has_nothrow_destructor<T> {}; -using boost::is_object; -using boost::is_reference; -using boost::is_same; -using boost::is_scalar; -using boost::remove_cv; -template <typename T> -struct remove_cvref : remove_cv<typename boost::remove_reference<T>::type> {}; -using boost::remove_pointer; -using boost::remove_reference; -using boost::result_of; -using boost::true_type; -#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) -template <typename> struct void_type { typedef void type; }; +template <typename> struct void_type +{ + typedef void type; +}; -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) +template <typename T> +using void_t = typename void_type<T>::type; template <typename...> struct conjunction : true_type {}; + template <typename T> struct conjunction<T> : T {}; -template <typename Head, typename... Tail> struct conjunction<Head, Tail...> : - conditional<Head::value, conjunction<Tail...>, Head>::type {}; -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) +template <typename Head, typename... Tail> +struct conjunction<Head, Tail...> : + conditional_t<Head::value, conjunction<Tail...>, Head> {}; struct defaulted_constraint { - ASIO_CONSTEXPR defaulted_constraint() {} + constexpr defaulted_constraint() {} }; template <bool Condition, typename Type = int> -struct constraint : enable_if<Condition, Type> {}; +struct constraint : std::enable_if<Condition, Type> {}; + +template <bool Condition, typename Type = int> +using constraint_t = typename constraint<Condition, Type>::type; + +template <typename T> +struct type_identity { typedef T type; }; + +template <typename T> +using type_identity_t = typename type_identity<T>::type; } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/utility.hpp b/3rdparty/asio/include/asio/detail/utility.hpp new file mode 100644 index 00000000000..72dd4d43190 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/utility.hpp @@ -0,0 +1,83 @@ +// +// detail/utility.hpp +// ~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_UTILITY_HPP +#define ASIO_DETAIL_UTILITY_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <utility> + +namespace asio { +namespace detail { + +#if defined(ASIO_HAS_STD_INDEX_SEQUENCE) + +using std::index_sequence; +using std::index_sequence_for; +using std::make_index_sequence; + +#else // defined(ASIO_HAS_STD_INDEX_SEQUENCE) + +template <std::size_t...> +struct index_sequence +{ +}; + +template <typename T, typename U> +struct join_index_sequences; + +template <std::size_t... I, std::size_t... J> +struct join_index_sequences<index_sequence<I...>, index_sequence<J...>> +{ + using type = index_sequence<I..., J...>; +}; + +template <std::size_t First, std::size_t Last> +struct index_pack : + join_index_sequences< + typename index_pack<First, First + (Last - First + 1) / 2 - 1>::type, + typename index_pack<First + (Last - First + 1) / 2, Last>::type + > +{ +}; + +template <std::size_t N> +struct index_pack<N, N> +{ + using type = index_sequence<N>; +}; + +template <std::size_t Begin, std::size_t End> +struct index_range : index_pack<Begin, End - 1> +{ +}; + +template <std::size_t N> +struct index_range<N, N> +{ + using type = index_sequence<>; +}; + +template <typename... T> +using index_sequence_for = typename index_range<0, sizeof...(T)>::type; + +template <std::size_t N> +using make_index_sequence = typename index_range<0, N>::type; + +#endif // defined(ASIO_HAS_STD_INDEX_SEQUENCE) + +} // namespace detail +} // namespace asio + +#endif // ASIO_DETAIL_UTILITY_HPP diff --git a/3rdparty/asio/include/asio/detail/variadic_templates.hpp b/3rdparty/asio/include/asio/detail/variadic_templates.hpp deleted file mode 100644 index 3bcc8d27605..00000000000 --- a/3rdparty/asio/include/asio/detail/variadic_templates.hpp +++ /dev/null @@ -1,294 +0,0 @@ -// -// detail/variadic_templates.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_VARIADIC_TEMPLATES_HPP -#define ASIO_DETAIL_VARIADIC_TEMPLATES_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#if !defined(ASIO_HAS_VARIADIC_TEMPLATES) - -# define ASIO_VARIADIC_TPARAMS(n) ASIO_VARIADIC_TPARAMS_##n - -# define ASIO_VARIADIC_TPARAMS_1 \ - typename T1 -# define ASIO_VARIADIC_TPARAMS_2 \ - typename T1, typename T2 -# define ASIO_VARIADIC_TPARAMS_3 \ - typename T1, typename T2, typename T3 -# define ASIO_VARIADIC_TPARAMS_4 \ - typename T1, typename T2, typename T3, typename T4 -# define ASIO_VARIADIC_TPARAMS_5 \ - typename T1, typename T2, typename T3, typename T4, typename T5 -# define ASIO_VARIADIC_TPARAMS_6 \ - typename T1, typename T2, typename T3, typename T4, typename T5, \ - typename T6 -# define ASIO_VARIADIC_TPARAMS_7 \ - typename T1, typename T2, typename T3, typename T4, typename T5, \ - typename T6, typename T7 -# define ASIO_VARIADIC_TPARAMS_8 \ - typename T1, typename T2, typename T3, typename T4, typename T5, \ - typename T6, typename T7, typename T8 - -# define ASIO_VARIADIC_TARGS(n) ASIO_VARIADIC_TARGS_##n - -# define ASIO_VARIADIC_TARGS_1 T1 -# define ASIO_VARIADIC_TARGS_2 T1, T2 -# define ASIO_VARIADIC_TARGS_3 T1, T2, T3 -# define ASIO_VARIADIC_TARGS_4 T1, T2, T3, T4 -# define ASIO_VARIADIC_TARGS_5 T1, T2, T3, T4, T5 -# define ASIO_VARIADIC_TARGS_6 T1, T2, T3, T4, T5, T6 -# define ASIO_VARIADIC_TARGS_7 T1, T2, T3, T4, T5, T6, T7 -# define ASIO_VARIADIC_TARGS_8 T1, T2, T3, T4, T5, T6, T7, T8 - -# define ASIO_VARIADIC_BYVAL_PARAMS(n) \ - ASIO_VARIADIC_BYVAL_PARAMS_##n - -# define ASIO_VARIADIC_BYVAL_PARAMS_1 T1 x1 -# define ASIO_VARIADIC_BYVAL_PARAMS_2 T1 x1, T2 x2 -# define ASIO_VARIADIC_BYVAL_PARAMS_3 T1 x1, T2 x2, T3 x3 -# define ASIO_VARIADIC_BYVAL_PARAMS_4 T1 x1, T2 x2, T3 x3, T4 x4 -# define ASIO_VARIADIC_BYVAL_PARAMS_5 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5 -# define ASIO_VARIADIC_BYVAL_PARAMS_6 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, \ - T6 x6 -# define ASIO_VARIADIC_BYVAL_PARAMS_7 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, \ - T6 x6, T7 x7 -# define ASIO_VARIADIC_BYVAL_PARAMS_8 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, \ - T6 x6, T7 x7, T8 x8 - -# define ASIO_VARIADIC_BYVAL_ARGS(n) \ - ASIO_VARIADIC_BYVAL_ARGS_##n - -# define ASIO_VARIADIC_BYVAL_ARGS_1 x1 -# define ASIO_VARIADIC_BYVAL_ARGS_2 x1, x2 -# define ASIO_VARIADIC_BYVAL_ARGS_3 x1, x2, x3 -# define ASIO_VARIADIC_BYVAL_ARGS_4 x1, x2, x3, x4 -# define ASIO_VARIADIC_BYVAL_ARGS_5 x1, x2, x3, x4, x5 -# define ASIO_VARIADIC_BYVAL_ARGS_6 x1, x2, x3, x4, x5, x6 -# define ASIO_VARIADIC_BYVAL_ARGS_7 x1, x2, x3, x4, x5, x6, x7 -# define ASIO_VARIADIC_BYVAL_ARGS_8 x1, x2, x3, x4, x5, x6, x7, x8 - -# define ASIO_VARIADIC_CONSTREF_PARAMS(n) \ - ASIO_VARIADIC_CONSTREF_PARAMS_##n - -# define ASIO_VARIADIC_CONSTREF_PARAMS_1 \ - const T1& x1 -# define ASIO_VARIADIC_CONSTREF_PARAMS_2 \ - const T1& x1, const T2& x2 -# define ASIO_VARIADIC_CONSTREF_PARAMS_3 \ - const T1& x1, const T2& x2, const T3& x3 -# define ASIO_VARIADIC_CONSTREF_PARAMS_4 \ - const T1& x1, const T2& x2, const T3& x3, const T4& x4 -# define ASIO_VARIADIC_CONSTREF_PARAMS_5 \ - const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5 -# define ASIO_VARIADIC_CONSTREF_PARAMS_6 \ - const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5, \ - const T6& x6 -# define ASIO_VARIADIC_CONSTREF_PARAMS_7 \ - const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5, \ - const T6& x6, const T7& x7 -# define ASIO_VARIADIC_CONSTREF_PARAMS_8 \ - const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5, \ - const T6& x6, const T7& x7, const T8& x8 - -# define ASIO_VARIADIC_MOVE_PARAMS(n) \ - ASIO_VARIADIC_MOVE_PARAMS_##n - -# define ASIO_VARIADIC_MOVE_PARAMS_1 \ - ASIO_MOVE_ARG(T1) x1 -# define ASIO_VARIADIC_MOVE_PARAMS_2 \ - ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2 -# define ASIO_VARIADIC_MOVE_PARAMS_3 \ - ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \ - ASIO_MOVE_ARG(T3) x3 -# define ASIO_VARIADIC_MOVE_PARAMS_4 \ - ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \ - ASIO_MOVE_ARG(T3) x3, ASIO_MOVE_ARG(T4) x4 -# define ASIO_VARIADIC_MOVE_PARAMS_5 \ - ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \ - ASIO_MOVE_ARG(T3) x3, ASIO_MOVE_ARG(T4) x4, \ - ASIO_MOVE_ARG(T5) x5 -# define ASIO_VARIADIC_MOVE_PARAMS_6 \ - ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \ - ASIO_MOVE_ARG(T3) x3, ASIO_MOVE_ARG(T4) x4, \ - ASIO_MOVE_ARG(T5) x5, ASIO_MOVE_ARG(T6) x6 -# define ASIO_VARIADIC_MOVE_PARAMS_7 \ - ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \ - ASIO_MOVE_ARG(T3) x3, ASIO_MOVE_ARG(T4) x4, \ - ASIO_MOVE_ARG(T5) x5, ASIO_MOVE_ARG(T6) x6, \ - ASIO_MOVE_ARG(T7) x7 -# define ASIO_VARIADIC_MOVE_PARAMS_8 \ - ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \ - ASIO_MOVE_ARG(T3) x3, ASIO_MOVE_ARG(T4) x4, \ - ASIO_MOVE_ARG(T5) x5, ASIO_MOVE_ARG(T6) x6, \ - ASIO_MOVE_ARG(T7) x7, ASIO_MOVE_ARG(T8) x8 - -# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS(n) \ - ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_##n - -# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_1 \ - ASIO_MOVE_ARG(T1) -# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_2 \ - ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2) -# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_3 \ - ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \ - ASIO_MOVE_ARG(T3) -# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_4 \ - ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \ - ASIO_MOVE_ARG(T3), ASIO_MOVE_ARG(T4) -# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_5 \ - ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \ - ASIO_MOVE_ARG(T3), ASIO_MOVE_ARG(T4), \ - ASIO_MOVE_ARG(T5) -# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_6 \ - ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \ - ASIO_MOVE_ARG(T3), ASIO_MOVE_ARG(T4), \ - ASIO_MOVE_ARG(T5), ASIO_MOVE_ARG(T6) -# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_7 \ - ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \ - ASIO_MOVE_ARG(T3), ASIO_MOVE_ARG(T4), \ - ASIO_MOVE_ARG(T5), ASIO_MOVE_ARG(T6), \ - ASIO_MOVE_ARG(T7) -# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_8 \ - ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \ - ASIO_MOVE_ARG(T3), ASIO_MOVE_ARG(T4), \ - ASIO_MOVE_ARG(T5), ASIO_MOVE_ARG(T6), \ - ASIO_MOVE_ARG(T7), ASIO_MOVE_ARG(T8) - -# define ASIO_VARIADIC_MOVE_ARGS(n) \ - ASIO_VARIADIC_MOVE_ARGS_##n - -# define ASIO_VARIADIC_MOVE_ARGS_1 \ - ASIO_MOVE_CAST(T1)(x1) -# define ASIO_VARIADIC_MOVE_ARGS_2 \ - ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2) -# define ASIO_VARIADIC_MOVE_ARGS_3 \ - ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \ - ASIO_MOVE_CAST(T3)(x3) -# define ASIO_VARIADIC_MOVE_ARGS_4 \ - ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \ - ASIO_MOVE_CAST(T3)(x3), ASIO_MOVE_CAST(T4)(x4) -# define ASIO_VARIADIC_MOVE_ARGS_5 \ - ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \ - ASIO_MOVE_CAST(T3)(x3), ASIO_MOVE_CAST(T4)(x4), \ - ASIO_MOVE_CAST(T5)(x5) -# define ASIO_VARIADIC_MOVE_ARGS_6 \ - ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \ - ASIO_MOVE_CAST(T3)(x3), ASIO_MOVE_CAST(T4)(x4), \ - ASIO_MOVE_CAST(T5)(x5), ASIO_MOVE_CAST(T6)(x6) -# define ASIO_VARIADIC_MOVE_ARGS_7 \ - ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \ - ASIO_MOVE_CAST(T3)(x3), ASIO_MOVE_CAST(T4)(x4), \ - ASIO_MOVE_CAST(T5)(x5), ASIO_MOVE_CAST(T6)(x6), \ - ASIO_MOVE_CAST(T7)(x7) -# define ASIO_VARIADIC_MOVE_ARGS_8 \ - ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \ - ASIO_MOVE_CAST(T3)(x3), ASIO_MOVE_CAST(T4)(x4), \ - ASIO_MOVE_CAST(T5)(x5), ASIO_MOVE_CAST(T6)(x6), \ - ASIO_MOVE_CAST(T7)(x7), ASIO_MOVE_CAST(T8)(x8) - -# define ASIO_VARIADIC_DECLVAL(n) \ - ASIO_VARIADIC_DECLVAL_##n - -# define ASIO_VARIADIC_DECLVAL_1 \ - declval<T1>() -# define ASIO_VARIADIC_DECLVAL_2 \ - declval<T1>(), declval<T2>() -# define ASIO_VARIADIC_DECLVAL_3 \ - declval<T1>(), declval<T2>(), declval<T3>() -# define ASIO_VARIADIC_DECLVAL_4 \ - declval<T1>(), declval<T2>(), declval<T3>(), declval<T4>() -# define ASIO_VARIADIC_DECLVAL_5 \ - declval<T1>(), declval<T2>(), declval<T3>(), declval<T4>(), \ - declval<T5>() -# define ASIO_VARIADIC_DECLVAL_6 \ - declval<T1>(), declval<T2>(), declval<T3>(), declval<T4>(), \ - declval<T5>(), declval<T6>() -# define ASIO_VARIADIC_DECLVAL_7 \ - declval<T1>(), declval<T2>(), declval<T3>(), declval<T4>(), \ - declval<T5>(), declval<T6>(), declval<T7>() -# define ASIO_VARIADIC_DECLVAL_8 \ - declval<T1>(), declval<T2>(), declval<T3>(), declval<T4>(), \ - declval<T5>(), declval<T6>(), declval<T7>(), declval<T8>() - -# define ASIO_VARIADIC_MOVE_DECLVAL(n) \ - ASIO_VARIADIC_MOVE_DECLVAL_##n - -# define ASIO_VARIADIC_MOVE_DECLVAL_1 \ - declval<ASIO_MOVE_ARG(T1)>() -# define ASIO_VARIADIC_MOVE_DECLVAL_2 \ - declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>() -# define ASIO_VARIADIC_MOVE_DECLVAL_3 \ - declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \ - declval<ASIO_MOVE_ARG(T3)>() -# define ASIO_VARIADIC_MOVE_DECLVAL_4 \ - declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \ - declval<ASIO_MOVE_ARG(T3)>(), declval<ASIO_MOVE_ARG(T4)>() -# define ASIO_VARIADIC_MOVE_DECLVAL_5 \ - declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \ - declval<ASIO_MOVE_ARG(T3)>(), declval<ASIO_MOVE_ARG(T4)>(), \ - declval<ASIO_MOVE_ARG(T5)>() -# define ASIO_VARIADIC_MOVE_DECLVAL_6 \ - declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \ - declval<ASIO_MOVE_ARG(T3)>(), declval<ASIO_MOVE_ARG(T4)>(), \ - declval<ASIO_MOVE_ARG(T5)>(), declval<ASIO_MOVE_ARG(T6)>() -# define ASIO_VARIADIC_MOVE_DECLVAL_7 \ - declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \ - declval<ASIO_MOVE_ARG(T3)>(), declval<ASIO_MOVE_ARG(T4)>(), \ - declval<ASIO_MOVE_ARG(T5)>(), declval<ASIO_MOVE_ARG(T6)>(), \ - declval<ASIO_MOVE_ARG(T7)>() -# define ASIO_VARIADIC_MOVE_DECLVAL_8 \ - declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \ - declval<ASIO_MOVE_ARG(T3)>(), declval<ASIO_MOVE_ARG(T4)>(), \ - declval<ASIO_MOVE_ARG(T5)>(), declval<ASIO_MOVE_ARG(T6)>(), \ - declval<ASIO_MOVE_ARG(T7)>(), declval<ASIO_MOVE_ARG(T8)>() - -# define ASIO_VARIADIC_DECAY(n) \ - ASIO_VARIADIC_DECAY_##n - -# define ASIO_VARIADIC_DECAY_1 \ - typename decay<T1>::type -# define ASIO_VARIADIC_DECAY_2 \ - typename decay<T1>::type, typename decay<T2>::type -# define ASIO_VARIADIC_DECAY_3 \ - typename decay<T1>::type, typename decay<T2>::type, \ - typename decay<T3>::type -# define ASIO_VARIADIC_DECAY_4 \ - typename decay<T1>::type, typename decay<T2>::type, \ - typename decay<T3>::type, typename decay<T4>::type -# define 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 ASIO_VARIADIC_DECAY_6 \ - typename decay<T1>::type, typename decay<T2>::type, \ - typename decay<T3>::type, typename decay<T4>::type, \ - typename decay<T5>::type, typename decay<T6>::type -# define ASIO_VARIADIC_DECAY_7 \ - typename decay<T1>::type, typename decay<T2>::type, \ - typename decay<T3>::type, typename decay<T4>::type, \ - typename decay<T5>::type, typename decay<T6>::type, \ - typename decay<T7>::type -# define ASIO_VARIADIC_DECAY_8 \ - typename decay<T1>::type, typename decay<T2>::type, \ - typename decay<T3>::type, typename decay<T4>::type, \ - typename decay<T5>::type, typename decay<T6>::type, \ - typename decay<T7>::type, typename decay<T8>::type - -# define ASIO_VARIADIC_GENERATE(m) m(1) m(2) m(3) m(4) m(5) m(6) m(7) m(8) -# define ASIO_VARIADIC_GENERATE_5(m) m(1) m(2) m(3) m(4) m(5) - -#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#endif // ASIO_DETAIL_VARIADIC_TEMPLATES_HPP diff --git a/3rdparty/asio/include/asio/detail/wait_handler.hpp b/3rdparty/asio/include/asio/detail/wait_handler.hpp index 6a87a538567..489a968cd77 100644 --- a/3rdparty/asio/include/asio/detail/wait_handler.hpp +++ b/3rdparty/asio/include/asio/detail/wait_handler.hpp @@ -2,7 +2,7 @@ // detail/wait_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -36,7 +36,7 @@ public: wait_handler(Handler& h, const IoExecutor& io_ex) : wait_op(&wait_handler::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(h)), + handler_(static_cast<Handler&&>(h)), work_(handler_, io_ex) { } @@ -53,7 +53,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( h->work_)); // Make a copy of the handler so that the memory can be deallocated before diff --git a/3rdparty/asio/include/asio/detail/wait_op.hpp b/3rdparty/asio/include/asio/detail/wait_op.hpp index e4a62de6170..548232c1c55 100644 --- a/3rdparty/asio/include/asio/detail/wait_op.hpp +++ b/3rdparty/asio/include/asio/detail/wait_op.hpp @@ -2,7 +2,7 @@ // detail/wait_op.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/win_event.hpp b/3rdparty/asio/include/asio/detail/win_event.hpp index 3f00e003289..e61843e5b9d 100644 --- a/3rdparty/asio/include/asio/detail/win_event.hpp +++ b/3rdparty/asio/include/asio/detail/win_event.hpp @@ -2,7 +2,7 @@ // detail/win_event.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/win_fd_set_adapter.hpp b/3rdparty/asio/include/asio/detail/win_fd_set_adapter.hpp index f5e19f01107..0e3e63f0c25 100644 --- a/3rdparty/asio/include/asio/detail/win_fd_set_adapter.hpp +++ b/3rdparty/asio/include/asio/detail/win_fd_set_adapter.hpp @@ -2,7 +2,7 @@ // detail/win_fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/win_fenced_block.hpp b/3rdparty/asio/include/asio/detail/win_fenced_block.hpp deleted file mode 100644 index 77d1eb1506b..00000000000 --- a/3rdparty/asio/include/asio/detail/win_fenced_block.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// detail/win_fenced_block.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_DETAIL_WIN_FENCED_BLOCK_HPP -#define ASIO_DETAIL_WIN_FENCED_BLOCK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#if defined(ASIO_WINDOWS) && !defined(UNDER_CE) - -#include "asio/detail/socket_types.hpp" -#include "asio/detail/noncopyable.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class win_fenced_block - : private noncopyable -{ -public: - enum half_t { half }; - enum full_t { full }; - - // Constructor for a half fenced block. - explicit win_fenced_block(half_t) - { - } - - // Constructor for a full fenced block. - explicit win_fenced_block(full_t) - { -#if defined(__BORLANDC__) - LONG barrier = 0; - ::InterlockedExchange(&barrier, 1); -#elif defined(ASIO_MSVC) \ - && ((ASIO_MSVC < 1400) || !defined(MemoryBarrier)) -# if defined(_M_IX86) -# pragma warning(push) -# pragma warning(disable:4793) - LONG barrier; - __asm { xchg barrier, eax } -# pragma warning(pop) -# endif // defined(_M_IX86) -#else - MemoryBarrier(); -#endif - } - - // Destructor. - ~win_fenced_block() - { -#if defined(__BORLANDC__) - LONG barrier = 0; - ::InterlockedExchange(&barrier, 1); -#elif defined(ASIO_MSVC) \ - && ((ASIO_MSVC < 1400) || !defined(MemoryBarrier)) -# if defined(_M_IX86) -# pragma warning(push) -# pragma warning(disable:4793) - LONG barrier; - __asm { xchg barrier, eax } -# pragma warning(pop) -# endif // defined(_M_IX86) -#else - MemoryBarrier(); -#endif - } -}; - -} // namespace detail -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // defined(ASIO_WINDOWS) && !defined(UNDER_CE) - -#endif // ASIO_DETAIL_WIN_FENCED_BLOCK_HPP diff --git a/3rdparty/asio/include/asio/detail/win_global.hpp b/3rdparty/asio/include/asio/detail/win_global.hpp index f77976e21ed..771f3fcba4b 100644 --- a/3rdparty/asio/include/asio/detail/win_global.hpp +++ b/3rdparty/asio/include/asio/detail/win_global.hpp @@ -2,7 +2,7 @@ // detail/win_global.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/win_iocp_file_service.hpp b/3rdparty/asio/include/asio/detail/win_iocp_file_service.hpp new file mode 100644 index 00000000000..f10a8d3cdf4 --- /dev/null +++ b/3rdparty/asio/include/asio/detail/win_iocp_file_service.hpp @@ -0,0 +1,287 @@ +// +// detail/win_iocp_file_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_DETAIL_WIN_IOCP_FILE_SERVICE_HPP +#define ASIO_DETAIL_WIN_IOCP_FILE_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_FILE) + +#include <string> +#include "asio/detail/cstdint.hpp" +#include "asio/detail/win_iocp_handle_service.hpp" +#include "asio/error.hpp" +#include "asio/execution_context.hpp" +#include "asio/file_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Extend win_iocp_handle_service to provide file support. +class win_iocp_file_service : + public execution_context_service_base<win_iocp_file_service> +{ +public: + // The native type of a file. + typedef win_iocp_handle_service::native_handle_type native_handle_type; + + // The implementation type of the file. + class implementation_type : win_iocp_handle_service::implementation_type + { + private: + // Only this service will have access to the internal values. + friend class win_iocp_file_service; + + uint64_t offset_; + bool is_stream_; + }; + + // Constructor. + ASIO_DECL win_iocp_file_service(execution_context& context); + + // Destroy all user-defined handler objects owned by the service. + ASIO_DECL void shutdown(); + + // Construct a new file implementation. + void construct(implementation_type& impl) + { + handle_service_.construct(impl); + impl.offset_ = 0; + impl.is_stream_ = false; + } + + // Move-construct a new file implementation. + void move_construct(implementation_type& impl, + implementation_type& other_impl) + { + handle_service_.move_construct(impl, other_impl); + impl.offset_ = other_impl.offset_; + impl.is_stream_ = other_impl.is_stream_; + other_impl.offset_ = 0; + } + + // Move-assign from another file implementation. + void move_assign(implementation_type& impl, + win_iocp_file_service& other_service, + implementation_type& other_impl) + { + handle_service_.move_assign(impl, + other_service.handle_service_, other_impl); + impl.offset_ = other_impl.offset_; + impl.is_stream_ = other_impl.is_stream_; + other_impl.offset_ = 0; + } + + // Destroy a file implementation. + void destroy(implementation_type& impl) + { + handle_service_.destroy(impl); + } + + // Set whether the implementation is stream-oriented. + void set_is_stream(implementation_type& impl, bool is_stream) + { + impl.is_stream_ = is_stream; + } + + // Open the file using the specified path name. + ASIO_DECL asio::error_code open(implementation_type& impl, + const char* path, file_base::flags open_flags, + asio::error_code& ec); + + // Assign a native handle to a file implementation. + asio::error_code assign(implementation_type& impl, + const native_handle_type& native_handle, + asio::error_code& ec) + { + return handle_service_.assign(impl, native_handle, ec); + } + + // Determine whether the file is open. + bool is_open(const implementation_type& impl) const + { + return handle_service_.is_open(impl); + } + + // Destroy a file implementation. + asio::error_code close(implementation_type& impl, + asio::error_code& ec) + { + return handle_service_.close(impl, ec); + } + + // Get the native file representation. + native_handle_type native_handle(const implementation_type& impl) const + { + return handle_service_.native_handle(impl); + } + + // Release ownership of a file. + native_handle_type release(implementation_type& impl, + asio::error_code& ec) + { + return handle_service_.release(impl, ec); + } + + // Cancel all operations associated with the file. + asio::error_code cancel(implementation_type& impl, + asio::error_code& ec) + { + return handle_service_.cancel(impl, ec); + } + + // Get the size of the file. + ASIO_DECL uint64_t size(const implementation_type& impl, + asio::error_code& ec) const; + + // Alter the size of the file. + ASIO_DECL asio::error_code resize(implementation_type& impl, + uint64_t n, asio::error_code& ec); + + // Synchronise the file to disk. + ASIO_DECL asio::error_code sync_all(implementation_type& impl, + asio::error_code& ec); + + // Synchronise the file data to disk. + ASIO_DECL asio::error_code sync_data(implementation_type& impl, + asio::error_code& ec); + + // Seek to a position in the file. + ASIO_DECL uint64_t seek(implementation_type& impl, int64_t offset, + file_base::seek_basis whence, asio::error_code& ec); + + // Write the given data. Returns the number of bytes written. + template <typename ConstBufferSequence> + size_t write_some(implementation_type& impl, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + uint64_t offset = impl.offset_; + impl.offset_ += asio::buffer_size(buffers); + return handle_service_.write_some_at(impl, offset, buffers, ec); + } + + // Start an asynchronous write. The data being written must be valid for the + // lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> + void async_write_some(implementation_type& impl, + const ConstBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + { + uint64_t offset = impl.offset_; + impl.offset_ += asio::buffer_size(buffers); + handle_service_.async_write_some_at(impl, offset, buffers, handler, io_ex); + } + + // Write the given data at the specified location. Returns the number of + // bytes written. + template <typename ConstBufferSequence> + size_t write_some_at(implementation_type& impl, uint64_t offset, + const ConstBufferSequence& buffers, asio::error_code& ec) + { + return handle_service_.write_some_at(impl, offset, buffers, ec); + } + + // Start an asynchronous write at the specified location. The data being + // written must be valid for the lifetime of the asynchronous operation. + template <typename ConstBufferSequence, typename Handler, typename IoExecutor> + void async_write_some_at(implementation_type& impl, + uint64_t offset, const ConstBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + { + handle_service_.async_write_some_at(impl, offset, buffers, handler, io_ex); + } + + // Read some data. Returns the number of bytes read. + template <typename MutableBufferSequence> + size_t read_some(implementation_type& impl, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + uint64_t offset = impl.offset_; + impl.offset_ += asio::buffer_size(buffers); + return handle_service_.read_some_at(impl, offset, buffers, ec); + } + + // Start an asynchronous read. The buffer for the data being read must be + // valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> + void async_read_some(implementation_type& impl, + const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + { + uint64_t offset = impl.offset_; + impl.offset_ += asio::buffer_size(buffers); + handle_service_.async_read_some_at(impl, offset, buffers, handler, io_ex); + } + + // Read some data. Returns the number of bytes read. + template <typename MutableBufferSequence> + size_t read_some_at(implementation_type& impl, uint64_t offset, + const MutableBufferSequence& buffers, asio::error_code& ec) + { + return handle_service_.read_some_at(impl, offset, buffers, ec); + } + + // Start an asynchronous read. The buffer for the data being read must be + // valid for the lifetime of the asynchronous operation. + template <typename MutableBufferSequence, + typename Handler, typename IoExecutor> + void async_read_some_at(implementation_type& impl, + uint64_t offset, const MutableBufferSequence& buffers, + Handler& handler, const IoExecutor& io_ex) + { + handle_service_.async_read_some_at(impl, offset, buffers, handler, io_ex); + } + +private: + // The implementation used for initiating asynchronous operations. + win_iocp_handle_service handle_service_; + + // Emulation of Windows IO_STATUS_BLOCK structure. + struct io_status_block + { + union u + { + LONG Status; + void* Pointer; + }; + ULONG_PTR Information; + }; + + // Emulation of flag passed to NtFlushBuffersFileEx. + enum { flush_flags_file_data_sync_only = 4 }; + + // The type of a NtFlushBuffersFileEx function pointer. + typedef LONG (NTAPI *nt_flush_buffers_file_ex_fn)( + HANDLE, ULONG, void*, ULONG, io_status_block*); + + // The NTFlushBuffersFileEx function pointer. + nt_flush_buffers_file_ex_fn nt_flush_buffers_file_ex_; +}; + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#if defined(ASIO_HEADER_ONLY) +# include "asio/detail/impl/win_iocp_file_service.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +#endif // defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_FILE) + +#endif // ASIO_DETAIL_WIN_IOCP_FILE_SERVICE_HPP diff --git a/3rdparty/asio/include/asio/detail/win_iocp_handle_read_op.hpp b/3rdparty/asio/include/asio/detail/win_iocp_handle_read_op.hpp index f11abb122e4..9721bda1c21 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_handle_read_op.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_handle_read_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_handle_read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -24,7 +24,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/operation.hpp" @@ -45,7 +44,7 @@ public: Handler& handler, const IoExecutor& io_ex) : operation(&win_iocp_handle_read_op::do_complete), buffers_(buffers), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -57,6 +56,7 @@ public: asio::error_code ec(result_ec); // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_handle_read_op* o(static_cast<win_iocp_handle_read_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -64,7 +64,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) @@ -80,6 +80,8 @@ public: if (ec.value() == ERROR_HANDLE_EOF) ec = asio::error::eof; + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated diff --git a/3rdparty/asio/include/asio/detail/win_iocp_handle_service.hpp b/3rdparty/asio/include/asio/detail/win_iocp_handle_service.hpp index 99fc94f0bdf..9e2486b4b79 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_handle_service.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_handle_service.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_handle_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -110,6 +110,10 @@ public: ASIO_DECL asio::error_code close(implementation_type& impl, asio::error_code& ec); + // Release ownership of a handle. + ASIO_DECL native_handle_type release(implementation_type& impl, + asio::error_code& ec); + // Get the native handle representation. native_handle_type native_handle(const implementation_type& impl) const { @@ -148,7 +152,7 @@ public: const ConstBufferSequence& buffers, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -178,7 +182,7 @@ public: uint64_t offset, const ConstBufferSequence& buffers, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -229,7 +233,7 @@ public: const MutableBufferSequence& buffers, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -261,7 +265,7 @@ public: uint64_t offset, const MutableBufferSequence& buffers, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -339,6 +343,27 @@ private: // destroyed. ASIO_DECL void close_for_destruction(implementation_type& impl); + // The type of a NtSetInformationFile function pointer. + typedef LONG (NTAPI *nt_set_info_fn)(HANDLE, ULONG_PTR*, void*, ULONG, ULONG); + + // Helper function to get the NtSetInformationFile function pointer. If no + // NtSetInformationFile pointer has been obtained yet, one is obtained using + // GetProcAddress and the pointer is cached. Returns a null pointer if + // NtSetInformationFile is not available. + ASIO_DECL nt_set_info_fn get_nt_set_info(); + + // Helper function to emulate InterlockedCompareExchangePointer functionality + // for: + // - very old Platform SDKs; and + // - platform SDKs where MSVC's /Wp64 option causes spurious warnings. + ASIO_DECL void* interlocked_compare_exchange_pointer( + void** dest, void* exch, void* cmp); + + // Helper function to emulate InterlockedExchangePointer functionality for: + // - very old Platform SDKs; and + // - platform SDKs where MSVC's /Wp64 option causes spurious warnings. + ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val); + // Helper class used to implement per operation cancellation. class iocp_op_cancellation : public operation { @@ -382,6 +407,9 @@ private: // handlers. win_iocp_io_context& iocp_service_; + // Pointer to NtSetInformationFile implementation. + void* nt_set_info_; + // Mutex to protect access to the linked list of implementations. mutex mutex_; diff --git a/3rdparty/asio/include/asio/detail/win_iocp_handle_write_op.hpp b/3rdparty/asio/include/asio/detail/win_iocp_handle_write_op.hpp index a6862051d2d..6a5b7e78338 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_handle_write_op.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_handle_write_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_handle_write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -24,7 +24,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/operation.hpp" @@ -45,15 +44,18 @@ public: Handler& handler, const IoExecutor& io_ex) : operation(&win_iocp_handle_write_op::do_complete), buffers_(buffers), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } static void do_complete(void* owner, operation* base, - const asio::error_code& ec, std::size_t bytes_transferred) + const asio::error_code& result_ec, std::size_t bytes_transferred) { + asio::error_code ec(result_ec); + // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_handle_write_op* o(static_cast<win_iocp_handle_write_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -61,7 +63,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) @@ -73,6 +75,8 @@ public: } #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING) + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated diff --git a/3rdparty/asio/include/asio/detail/win_iocp_io_context.hpp b/3rdparty/asio/include/asio/detail/win_iocp_io_context.hpp index 1376d37fc45..1de94df7854 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_io_context.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_io_context.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_io_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -272,11 +272,13 @@ private: enum { +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) // Timeout to use with GetQueuedCompletionStatus on older versions of // Windows. Some versions of windows have a "bug" where a call to // GetQueuedCompletionStatus can appear stuck even though there are events // waiting on the queue. Using a timeout helps to work around the issue. default_gqcs_timeout = 500, +#endif // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) // Maximum waitable timer timeout, in milliseconds. max_timeout_msec = 5 * 60 * 1000, diff --git a/3rdparty/asio/include/asio/detail/win_iocp_null_buffers_op.hpp b/3rdparty/asio/include/asio/detail/win_iocp_null_buffers_op.hpp index 5aedd7aed97..07751b9234b 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_null_buffers_op.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_null_buffers_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_null_buffers_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,7 +22,6 @@ #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -46,7 +45,7 @@ public: &win_iocp_null_buffers_op::do_perform, &win_iocp_null_buffers_op::do_complete), cancel_token_(cancel_token), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -63,6 +62,7 @@ public: asio::error_code ec(result_ec); // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_null_buffers_op* o(static_cast<win_iocp_null_buffers_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -70,7 +70,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); // The reactor may have stored a result in the operation object. @@ -90,6 +90,8 @@ public: ec = asio::error::connection_refused; } + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated diff --git a/3rdparty/asio/include/asio/detail/win_iocp_operation.hpp b/3rdparty/asio/include/asio/detail/win_iocp_operation.hpp index 4e1cd6a98c7..a935f87b882 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_operation.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_operation.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_operation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/win_iocp_overlapped_op.hpp b/3rdparty/asio/include/asio/detail/win_iocp_overlapped_op.hpp index 247375ba2c7..dc65ad08311 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_overlapped_op.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_overlapped_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_overlapped_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,7 +22,6 @@ #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/operation.hpp" @@ -41,15 +40,18 @@ public: win_iocp_overlapped_op(Handler& handler, const IoExecutor& io_ex) : operation(&win_iocp_overlapped_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } static void do_complete(void* owner, operation* base, - const asio::error_code& ec, std::size_t bytes_transferred) + const asio::error_code& result_ec, std::size_t bytes_transferred) { + asio::error_code ec(result_ec); + // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_overlapped_op* o(static_cast<win_iocp_overlapped_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -57,9 +59,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated diff --git a/3rdparty/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp b/3rdparty/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp index 5249abb66dd..596705a38c6 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_overlapped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -47,11 +47,11 @@ public: // Construct an win_iocp_overlapped_ptr to contain the specified handler. template <typename Executor, typename Handler> explicit win_iocp_overlapped_ptr(const Executor& ex, - ASIO_MOVE_ARG(Handler) handler) + Handler&& handler) : ptr_(0), iocp_service_(0) { - this->reset(ex, ASIO_MOVE_CAST(Handler)(handler)); + this->reset(ex, static_cast<Handler&&>(handler)); } // Destructor automatically frees the OVERLAPPED object unless released. @@ -134,9 +134,9 @@ public: private: template <typename Executor> static win_iocp_io_context* get_iocp_service(const Executor& ex, - typename enable_if< + enable_if_t< can_query<const Executor&, execution::context_t>::value - >::type* = 0) + >* = 0) { return &use_service<win_iocp_io_context>( asio::query(ex, execution::context)); @@ -144,9 +144,9 @@ private: template <typename Executor> static win_iocp_io_context* get_iocp_service(const Executor& ex, - typename enable_if< + enable_if_t< !can_query<const Executor&, execution::context_t>::value - >::type* = 0) + >* = 0) { return &use_service<win_iocp_io_context>(ex.context()); } diff --git a/3rdparty/asio/include/asio/detail/win_iocp_serial_port_service.hpp b/3rdparty/asio/include/asio/detail/win_iocp_serial_port_service.hpp index d1d9d8281ce..e0e12e91d5f 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_serial_port_service.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_serial_port_service.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_serial_port_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -137,6 +137,7 @@ public: asio::error_code& ec) { ec = asio::error::operation_not_supported; + ASIO_ERROR_LOCATION(ec); return ec; } diff --git a/3rdparty/asio/include/asio/detail/win_iocp_socket_accept_op.hpp b/3rdparty/asio/include/asio/detail/win_iocp_socket_accept_op.hpp index c25cb172484..f4aa850be80 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_socket_accept_op.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_socket_accept_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_accept_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,7 +22,6 @@ #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/operation.hpp" @@ -55,7 +54,7 @@ public: enable_connection_aborted_(enable_connection_aborted), proxy_op_(0), cancel_requested_(0), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -88,6 +87,7 @@ public: asio::error_code ec(result_ec); // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_socket_accept_op* o(static_cast<win_iocp_socket_accept_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -137,9 +137,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -176,8 +178,6 @@ private: handler_work<Handler, IoExecutor> work_; }; -#if defined(ASIO_HAS_MOVE) - template <typename Protocol, typename PeerIoExecutor, typename Handler, typename IoExecutor> class win_iocp_socket_move_accept_op : public operation @@ -199,7 +199,7 @@ public: enable_connection_aborted_(enable_connection_aborted), cancel_requested_(0), proxy_op_(0), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -232,6 +232,7 @@ public: asio::error_code ec(result_ec); // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_socket_move_accept_op* o( static_cast<win_iocp_socket_move_accept_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -282,9 +283,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated @@ -293,8 +296,8 @@ public: // deallocated the memory here. detail::move_binder2<Handler, asio::error_code, peer_socket_type> - handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), ec, - ASIO_MOVE_CAST(peer_socket_type)(o->peer_)); + handler(0, static_cast<Handler&&>(o->handler_), ec, + static_cast<peer_socket_type&&>(o->peer_)); p.h = asio::detail::addressof(handler.handler_); p.reset(); @@ -326,8 +329,6 @@ private: handler_work<Handler, IoExecutor> work_; }; -#endif // defined(ASIO_HAS_MOVE) - } // namespace detail } // namespace asio diff --git a/3rdparty/asio/include/asio/detail/win_iocp_socket_connect_op.hpp b/3rdparty/asio/include/asio/detail/win_iocp_socket_connect_op.hpp index f7be04d5c56..104ee87bb24 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_socket_connect_op.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_socket_connect_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,7 +22,6 @@ #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -47,6 +46,7 @@ public: static status do_perform(reactor_op* base) { + ASIO_ASSUME(base != 0); win_iocp_socket_connect_op_base* o( static_cast<win_iocp_socket_connect_op_base*>(base)); @@ -68,7 +68,7 @@ public: Handler& handler, const IoExecutor& io_ex) : win_iocp_socket_connect_op_base(socket, &win_iocp_socket_connect_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -80,6 +80,7 @@ public: asio::error_code ec(result_ec); // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_socket_connect_op* o( static_cast<win_iocp_socket_connect_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -96,9 +97,11 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated diff --git a/3rdparty/asio/include/asio/detail/win_iocp_socket_recv_op.hpp b/3rdparty/asio/include/asio/detail/win_iocp_socket_recv_op.hpp index 0da29825dd2..874a12aa7d0 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_socket_recv_op.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_socket_recv_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,7 +23,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/operation.hpp" @@ -49,7 +48,7 @@ public: state_(state), cancel_token_(cancel_token), buffers_(buffers), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -61,6 +60,7 @@ public: asio::error_code ec(result_ec); // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_socket_recv_op* o(static_cast<win_iocp_socket_recv_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -68,7 +68,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) @@ -85,6 +85,8 @@ public: MutableBufferSequence>::all_empty(o->buffers_), ec, bytes_transferred); + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated diff --git a/3rdparty/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp b/3rdparty/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp index 40c91144c58..b4b98aa0148 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_recvfrom_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,7 +23,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/operation.hpp" @@ -51,7 +50,7 @@ public: endpoint_size_(static_cast<int>(endpoint.capacity())), cancel_token_(cancel_token), buffers_(buffers), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -68,6 +67,7 @@ public: asio::error_code ec(result_ec); // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_socket_recvfrom_op* o( static_cast<win_iocp_socket_recvfrom_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -76,7 +76,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) @@ -93,6 +93,8 @@ public: // Record the size of the endpoint returned by the operation. o->endpoint_.resize(o->endpoint_size_); + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated diff --git a/3rdparty/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp b/3rdparty/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp index a14a4b5cb1b..85e4b78dc20 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp @@ -1,8 +1,8 @@ // // detail/win_iocp_socket_recvmsg_op.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,7 +23,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/operation.hpp" @@ -51,7 +50,7 @@ public: cancel_token_(cancel_token), buffers_(buffers), out_flags_(out_flags), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -63,6 +62,7 @@ public: asio::error_code ec(result_ec); // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_socket_recvmsg_op* o( static_cast<win_iocp_socket_recvmsg_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -71,7 +71,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) @@ -86,6 +86,8 @@ public: socket_ops::complete_iocp_recvmsg(o->cancel_token_, ec); o->out_flags_ = 0; + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated diff --git a/3rdparty/asio/include/asio/detail/win_iocp_socket_send_op.hpp b/3rdparty/asio/include/asio/detail/win_iocp_socket_send_op.hpp index 3a40abefa06..c7043c4875e 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_socket_send_op.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_socket_send_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,7 +23,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/operation.hpp" @@ -47,7 +46,7 @@ public: : operation(&win_iocp_socket_send_op::do_complete), cancel_token_(cancel_token), buffers_(buffers), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -59,6 +58,7 @@ public: asio::error_code ec(result_ec); // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_socket_send_op* o(static_cast<win_iocp_socket_send_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -66,7 +66,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) @@ -80,6 +80,8 @@ public: socket_ops::complete_iocp_send(o->cancel_token_, ec); + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated diff --git a/3rdparty/asio/include/asio/detail/win_iocp_socket_service.hpp b/3rdparty/asio/include/asio/detail/win_iocp_socket_service.hpp index 6f7fa182c43..faeaffa4c36 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_socket_service.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_socket_service.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -27,7 +27,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/mutex.hpp" #include "asio/detail/operation.hpp" @@ -51,7 +50,7 @@ namespace detail { template <typename Protocol> class win_iocp_socket_service : - public execution_context_service_base<win_iocp_socket_service<Protocol> >, + public execution_context_service_base<win_iocp_socket_service<Protocol>>, public win_iocp_socket_service_base { public: @@ -131,7 +130,7 @@ public: // Constructor. win_iocp_socket_service(execution_context& context) : execution_context_service_base< - win_iocp_socket_service<Protocol> >(context), + win_iocp_socket_service<Protocol>>(context), win_iocp_socket_service_base(context) { } @@ -144,7 +143,7 @@ public: // Move-construct a new socket implementation. void move_construct(implementation_type& impl, - implementation_type& other_impl) ASIO_NOEXCEPT + implementation_type& other_impl) noexcept { this->base_move_construct(impl, other_impl); @@ -205,6 +204,8 @@ public: impl.have_remote_endpoint_ = false; impl.remote_endpoint_ = endpoint_type(); } + + ASIO_ERROR_LOCATION(ec); return ec; } @@ -219,6 +220,8 @@ public: impl.have_remote_endpoint_ = native_socket.have_remote_endpoint(); impl.remote_endpoint_ = native_socket.remote_endpoint(); } + + ASIO_ERROR_LOCATION(ec); return ec; } @@ -235,6 +238,8 @@ public: const endpoint_type& endpoint, asio::error_code& ec) { socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec); + + ASIO_ERROR_LOCATION(ec); return ec; } @@ -246,6 +251,8 @@ public: socket_ops::setsockopt(impl.socket_, impl.state_, option.level(impl.protocol_), option.name(impl.protocol_), option.data(impl.protocol_), option.size(impl.protocol_), ec); + + ASIO_ERROR_LOCATION(ec); return ec; } @@ -260,6 +267,8 @@ public: option.data(impl.protocol_), &size, ec); if (!ec) option.resize(impl.protocol_, size); + + ASIO_ERROR_LOCATION(ec); return ec; } @@ -270,7 +279,10 @@ public: endpoint_type endpoint; std::size_t addr_len = endpoint.capacity(); if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec)) + { + ASIO_ERROR_LOCATION(ec); return endpoint_type(); + } endpoint.resize(addr_len); return endpoint; } @@ -283,7 +295,10 @@ public: std::size_t addr_len = endpoint.capacity(); if (socket_ops::getpeername(impl.socket_, endpoint.data(), &addr_len, impl.have_remote_endpoint_, ec)) + { + ASIO_ERROR_LOCATION(ec); return endpoint_type(); + } endpoint.resize(addr_len); return endpoint; } @@ -306,9 +321,12 @@ public: buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs(buffers); - return socket_ops::sync_sendto(impl.socket_, impl.state_, - bufs.buffers(), bufs.count(), flags, + size_t n = socket_ops::sync_sendto(impl.socket_, + impl.state_, bufs.buffers(), bufs.count(), flags, destination.data(), destination.size(), ec); + + ASIO_ERROR_LOCATION(ec); + return n; } // Wait until data can be sent without blocking. @@ -318,7 +336,7 @@ public: { // Wait for socket to become ready. socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); - + ASIO_ERROR_LOCATION(ec); return 0; } @@ -330,7 +348,7 @@ public: socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -388,14 +406,15 @@ public: MutableBufferSequence> bufs(buffers); std::size_t addr_len = sender_endpoint.capacity(); - std::size_t bytes_recvd = socket_ops::sync_recvfrom( - impl.socket_, impl.state_, bufs.buffers(), bufs.count(), - flags, sender_endpoint.data(), &addr_len, ec); + std::size_t n = socket_ops::sync_recvfrom(impl.socket_, + impl.state_, bufs.buffers(), bufs.count(), flags, + sender_endpoint.data(), &addr_len, ec); if (!ec) sender_endpoint.resize(addr_len); - return bytes_recvd; + ASIO_ERROR_LOCATION(ec); + return n; } // Wait until data can be received without blocking. @@ -409,6 +428,7 @@ public: // Reset endpoint since it can be given no sensible value at this time. sender_endpoint = endpoint_type(); + ASIO_ERROR_LOCATION(ec); return 0; } @@ -422,7 +442,7 @@ public: socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -454,7 +474,7 @@ public: endpoint_type& sender_endpoint, socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -498,6 +518,7 @@ public: if (peer.is_open()) { ec = asio::error::already_open; + ASIO_ERROR_LOCATION(ec); return ec; } @@ -516,6 +537,7 @@ public: new_socket.release(); } + ASIO_ERROR_LOCATION(ec); return ec; } @@ -525,7 +547,7 @@ public: void async_accept(implementation_type& impl, Socket& peer, endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -557,7 +579,6 @@ public: p.v = p.p = 0; } -#if defined(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 PeerIoExecutor, typename Handler, typename IoExecutor> @@ -565,7 +586,7 @@ public: const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -597,7 +618,6 @@ public: p.p->address_length(), o); p.v = p.p = 0; } -#endif // defined(ASIO_HAS_MOVE) // Connect the socket to the specified endpoint. asio::error_code connect(implementation_type& impl, @@ -605,6 +625,7 @@ public: { socket_ops::sync_connect(impl.socket_, peer_endpoint.data(), peer_endpoint.size(), ec); + ASIO_ERROR_LOCATION(ec); return ec; } @@ -614,7 +635,7 @@ public: const endpoint_type& peer_endpoint, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. diff --git a/3rdparty/asio/include/asio/detail/win_iocp_socket_service_base.hpp b/3rdparty/asio/include/asio/detail/win_iocp_socket_service_base.hpp index 738c6f04191..a157143e35b 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_socket_service_base.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_socket_service_base.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_socket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -27,7 +27,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/mutex.hpp" #include "asio/detail/operation.hpp" @@ -96,7 +95,7 @@ public: // Move-construct a new socket implementation. ASIO_DECL void base_move_construct(base_implementation_type& impl, - base_implementation_type& other_impl) ASIO_NOEXCEPT; + base_implementation_type& other_impl) noexcept; // Move-assign from another socket implementation. ASIO_DECL void base_move_assign(base_implementation_type& impl, @@ -214,7 +213,7 @@ public: void async_wait(base_implementation_type& impl, socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); bool is_continuation = @@ -298,7 +297,7 @@ public: const ConstBufferSequence& buffers, socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -374,7 +373,7 @@ public: const MutableBufferSequence& buffers, socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -407,7 +406,7 @@ public: const null_buffers&, socket_base::message_flags flags, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -478,7 +477,7 @@ public: socket_base::message_flags& out_flags, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -510,7 +509,7 @@ public: socket_base::message_flags& out_flags, Handler& handler, const IoExecutor& io_ex) { - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Allocate and construct an operation to wrap the handler. @@ -569,9 +568,8 @@ protected: // Helper function to start an asynchronous send_to operation. ASIO_DECL void start_send_to_op(base_implementation_type& impl, - WSABUF* buffers, std::size_t buffer_count, - const socket_addr_type* addr, int addrlen, - socket_base::message_flags flags, operation* op); + WSABUF* buffers, std::size_t buffer_count, const void* addr, + int addrlen, socket_base::message_flags flags, operation* op); // Helper function to start an asynchronous receive operation. ASIO_DECL void start_receive_op(base_implementation_type& impl, @@ -585,7 +583,7 @@ protected: // Helper function to start an asynchronous receive_from operation. ASIO_DECL void start_receive_from_op(base_implementation_type& impl, - WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr, + WSABUF* buffers, std::size_t buffer_count, void* addr, socket_base::message_flags flags, int* addrlen, operation* op); // Helper function to start an asynchronous accept operation. @@ -599,9 +597,8 @@ protected: // Start the asynchronous connect operation using the reactor. ASIO_DECL int start_connect_op(base_implementation_type& impl, - int family, int type, const socket_addr_type* remote_addr, - std::size_t remote_addrlen, win_iocp_socket_connect_op_base* op, - operation* iocp_op); + int family, int type, const void* remote_addr, std::size_t remote_addrlen, + win_iocp_socket_connect_op_base* op, operation* iocp_op); // Helper function to close a socket when the associated object is being // destroyed. diff --git a/3rdparty/asio/include/asio/detail/win_iocp_thread_info.hpp b/3rdparty/asio/include/asio/detail/win_iocp_thread_info.hpp index 2b9b1bf5623..3f1e0126779 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_thread_info.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_thread_info.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_thread_info.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/win_iocp_wait_op.hpp b/3rdparty/asio/include/asio/detail/win_iocp_wait_op.hpp index b17fe404b89..882f16e73cf 100644 --- a/3rdparty/asio/include/asio/detail/win_iocp_wait_op.hpp +++ b/3rdparty/asio/include/asio/detail/win_iocp_wait_op.hpp @@ -2,7 +2,7 @@ // detail/win_iocp_wait_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,7 +23,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp" @@ -47,7 +46,7 @@ public: &win_iocp_wait_op::do_perform, &win_iocp_wait_op::do_complete), cancel_token_(cancel_token), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -64,6 +63,7 @@ public: asio::error_code ec(result_ec); // Take ownership of the operation object. + ASIO_ASSUME(base != 0); win_iocp_wait_op* o(static_cast<win_iocp_wait_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -71,7 +71,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); // The reactor may have stored a result in the operation object. @@ -91,6 +91,8 @@ public: ec = asio::error::connection_refused; } + ASIO_ERROR_LOCATION(ec); + // Make a copy of the handler so that the memory can be deallocated before // the upcall is made. Even if we're not about to make an upcall, a // sub-object of the handler may be the true owner of the memory associated diff --git a/3rdparty/asio/include/asio/detail/win_mutex.hpp b/3rdparty/asio/include/asio/detail/win_mutex.hpp index aed9ad91b92..77603ec9750 100644 --- a/3rdparty/asio/include/asio/detail/win_mutex.hpp +++ b/3rdparty/asio/include/asio/detail/win_mutex.hpp @@ -2,7 +2,7 @@ // detail/win_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/win_object_handle_service.hpp b/3rdparty/asio/include/asio/detail/win_object_handle_service.hpp index a80c27dfc0b..8e01b72f4f6 100644 --- a/3rdparty/asio/include/asio/detail/win_object_handle_service.hpp +++ b/3rdparty/asio/include/asio/detail/win_object_handle_service.hpp @@ -2,7 +2,7 @@ // detail/win_object_handle_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -20,7 +20,6 @@ #if defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE) -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/wait_handler.hpp" #include "asio/error.hpp" diff --git a/3rdparty/asio/include/asio/detail/win_static_mutex.hpp b/3rdparty/asio/include/asio/detail/win_static_mutex.hpp index 4538c3d168c..736ef0e3f2c 100644 --- a/3rdparty/asio/include/asio/detail/win_static_mutex.hpp +++ b/3rdparty/asio/include/asio/detail/win_static_mutex.hpp @@ -2,7 +2,7 @@ // detail/win_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/win_thread.hpp b/3rdparty/asio/include/asio/detail/win_thread.hpp index 0f6679d0190..c1e7b8e618a 100644 --- a/3rdparty/asio/include/asio/detail/win_thread.hpp +++ b/3rdparty/asio/include/asio/detail/win_thread.hpp @@ -2,7 +2,7 @@ // detail/win_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/win_tss_ptr.hpp b/3rdparty/asio/include/asio/detail/win_tss_ptr.hpp index fa137a8bce2..95a87717bad 100644 --- a/3rdparty/asio/include/asio/detail/win_tss_ptr.hpp +++ b/3rdparty/asio/include/asio/detail/win_tss_ptr.hpp @@ -2,7 +2,7 @@ // detail/win_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/winapp_thread.hpp b/3rdparty/asio/include/asio/detail/winapp_thread.hpp index 512aa231e26..efa662dfe6f 100644 --- a/3rdparty/asio/include/asio/detail/winapp_thread.hpp +++ b/3rdparty/asio/include/asio/detail/winapp_thread.hpp @@ -2,7 +2,7 @@ // detail/winapp_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/wince_thread.hpp b/3rdparty/asio/include/asio/detail/wince_thread.hpp index 63030f2545f..3c6b8543c21 100644 --- a/3rdparty/asio/include/asio/detail/wince_thread.hpp +++ b/3rdparty/asio/include/asio/detail/wince_thread.hpp @@ -2,7 +2,7 @@ // detail/wince_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/winrt_async_manager.hpp b/3rdparty/asio/include/asio/detail/winrt_async_manager.hpp index ee7d4f691a6..9d0f9023c8c 100644 --- a/3rdparty/asio/include/asio/detail/winrt_async_manager.hpp +++ b/3rdparty/asio/include/asio/detail/winrt_async_manager.hpp @@ -2,7 +2,7 @@ // detail/winrt_async_manager.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/winrt_async_op.hpp b/3rdparty/asio/include/asio/detail/winrt_async_op.hpp index 0751681fae7..a34989841bc 100644 --- a/3rdparty/asio/include/asio/detail/winrt_async_op.hpp +++ b/3rdparty/asio/include/asio/detail/winrt_async_op.hpp @@ -2,7 +2,7 @@ // detail/winrt_async_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/winrt_resolve_op.hpp b/3rdparty/asio/include/asio/detail/winrt_resolve_op.hpp index b7cfcb203ae..3cbd00e61f2 100644 --- a/3rdparty/asio/include/asio/detail/winrt_resolve_op.hpp +++ b/3rdparty/asio/include/asio/detail/winrt_resolve_op.hpp @@ -2,7 +2,7 @@ // detail/winrt_resolve_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,7 +22,6 @@ #include "asio/detail/bind_handler.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/winrt_async_op.hpp" @@ -54,7 +53,7 @@ public: Windows::Networking::EndpointPair^>^>( &winrt_resolve_op::do_complete), query_(query), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -63,6 +62,7 @@ public: const asio::error_code&, std::size_t) { // Take ownership of the operation object. + ASIO_ASSUME(base != 0); winrt_resolve_op* o(static_cast<winrt_resolve_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -70,7 +70,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); results_type results = results_type(); diff --git a/3rdparty/asio/include/asio/detail/winrt_resolver_service.hpp b/3rdparty/asio/include/asio/detail/winrt_resolver_service.hpp index 81ecb7400bf..02dddf08226 100644 --- a/3rdparty/asio/include/asio/detail/winrt_resolver_service.hpp +++ b/3rdparty/asio/include/asio/detail/winrt_resolver_service.hpp @@ -2,7 +2,7 @@ // detail/winrt_resolver_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -42,7 +42,7 @@ namespace detail { template <typename Protocol> class winrt_resolver_service : - public execution_context_service_base<winrt_resolver_service<Protocol> > + public execution_context_service_base<winrt_resolver_service<Protocol>> { public: // The implementation type of the resolver. A cancellation token is used to @@ -62,7 +62,7 @@ public: // Constructor. winrt_resolver_service(execution_context& context) : execution_context_service_base< - winrt_resolver_service<Protocol> >(context), + winrt_resolver_service<Protocol>>(context), scheduler_(use_service<scheduler_impl>(context)), async_manager_(use_service<winrt_async_manager>(context)) { diff --git a/3rdparty/asio/include/asio/detail/winrt_socket_connect_op.hpp b/3rdparty/asio/include/asio/detail/winrt_socket_connect_op.hpp index b0e0fbf2975..008062e1b6e 100644 --- a/3rdparty/asio/include/asio/detail/winrt_socket_connect_op.hpp +++ b/3rdparty/asio/include/asio/detail/winrt_socket_connect_op.hpp @@ -2,7 +2,7 @@ // detail/winrt_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,7 +23,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/winrt_async_op.hpp" @@ -43,7 +42,7 @@ public: winrt_socket_connect_op(Handler& handler, const IoExecutor& io_ex) : winrt_async_op<void>(&winrt_socket_connect_op::do_complete), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -52,6 +51,7 @@ public: const asio::error_code&, std::size_t) { // Take ownership of the operation object. + ASIO_ASSUME(base != 0); winrt_socket_connect_op* o(static_cast<winrt_socket_connect_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -59,7 +59,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); // Make a copy of the handler so that the memory can be deallocated before diff --git a/3rdparty/asio/include/asio/detail/winrt_socket_recv_op.hpp b/3rdparty/asio/include/asio/detail/winrt_socket_recv_op.hpp index 722578ee9f9..4b1d9f895f3 100644 --- a/3rdparty/asio/include/asio/detail/winrt_socket_recv_op.hpp +++ b/3rdparty/asio/include/asio/detail/winrt_socket_recv_op.hpp @@ -2,7 +2,7 @@ // detail/winrt_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,7 +23,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/winrt_async_op.hpp" @@ -46,7 +45,7 @@ public: : winrt_async_op<Windows::Storage::Streams::IBuffer^>( &winrt_socket_recv_op::do_complete), buffers_(buffers), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -55,6 +54,7 @@ public: const asio::error_code&, std::size_t) { // Take ownership of the operation object. + ASIO_ASSUME(base != 0); winrt_socket_recv_op* o(static_cast<winrt_socket_recv_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -62,7 +62,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) diff --git a/3rdparty/asio/include/asio/detail/winrt_socket_send_op.hpp b/3rdparty/asio/include/asio/detail/winrt_socket_send_op.hpp index 0f52d9718e7..eb21ef7e902 100644 --- a/3rdparty/asio/include/asio/detail/winrt_socket_send_op.hpp +++ b/3rdparty/asio/include/asio/detail/winrt_socket_send_op.hpp @@ -2,7 +2,7 @@ // detail/winrt_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,7 +23,6 @@ #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/winrt_async_op.hpp" @@ -45,7 +44,7 @@ public: Handler& handler, const IoExecutor& io_ex) : winrt_async_op<unsigned int>(&winrt_socket_send_op::do_complete), buffers_(buffers), - handler_(ASIO_MOVE_CAST(Handler)(handler)), + handler_(static_cast<Handler&&>(handler)), work_(handler_, io_ex) { } @@ -54,6 +53,7 @@ public: const asio::error_code&, std::size_t) { // Take ownership of the operation object. + ASIO_ASSUME(base != 0); winrt_socket_send_op* o(static_cast<winrt_socket_send_op*>(base)); ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -61,7 +61,7 @@ public: // Take ownership of the operation's outstanding work. handler_work<Handler, IoExecutor> w( - ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)( + static_cast<handler_work<Handler, IoExecutor>&&>( o->work_)); #if defined(ASIO_ENABLE_BUFFER_DEBUGGING) diff --git a/3rdparty/asio/include/asio/detail/winrt_ssocket_service.hpp b/3rdparty/asio/include/asio/detail/winrt_ssocket_service.hpp index b7727ff2d2f..6b45ed4fb0c 100644 --- a/3rdparty/asio/include/asio/detail/winrt_ssocket_service.hpp +++ b/3rdparty/asio/include/asio/detail/winrt_ssocket_service.hpp @@ -2,7 +2,7 @@ // detail/winrt_ssocket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -33,7 +33,7 @@ namespace detail { template <typename Protocol> class winrt_ssocket_service : - public execution_context_service_base<winrt_ssocket_service<Protocol> >, + public execution_context_service_base<winrt_ssocket_service<Protocol>>, public winrt_ssocket_service_base { public: @@ -62,7 +62,7 @@ public: // Constructor. winrt_ssocket_service(execution_context& context) - : execution_context_service_base<winrt_ssocket_service<Protocol> >(context), + : execution_context_service_base<winrt_ssocket_service<Protocol>>(context), winrt_ssocket_service_base(context) { } @@ -75,7 +75,7 @@ public: // Move-construct a new socket implementation. void move_construct(implementation_type& impl, - implementation_type& other_impl) ASIO_NOEXCEPT + implementation_type& other_impl) noexcept { this->base_move_construct(impl, other_impl); diff --git a/3rdparty/asio/include/asio/detail/winrt_ssocket_service_base.hpp b/3rdparty/asio/include/asio/detail/winrt_ssocket_service_base.hpp index 6668975e5a7..c752da80e2a 100644 --- a/3rdparty/asio/include/asio/detail/winrt_ssocket_service_base.hpp +++ b/3rdparty/asio/include/asio/detail/winrt_ssocket_service_base.hpp @@ -2,7 +2,7 @@ // detail/winrt_ssocket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -77,7 +77,7 @@ public: // Move-construct a new socket implementation. ASIO_DECL void base_move_construct(base_implementation_type& impl, - base_implementation_type& other_impl) ASIO_NOEXCEPT; + base_implementation_type& other_impl) noexcept; // Move-assign from another socket implementation. ASIO_DECL void base_move_assign(base_implementation_type& impl, diff --git a/3rdparty/asio/include/asio/detail/winrt_timer_scheduler.hpp b/3rdparty/asio/include/asio/detail/winrt_timer_scheduler.hpp index 8fd9636bf85..aadd581f75d 100644 --- a/3rdparty/asio/include/asio/detail/winrt_timer_scheduler.hpp +++ b/3rdparty/asio/include/asio/detail/winrt_timer_scheduler.hpp @@ -2,7 +2,7 @@ // detail/winrt_timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/winrt_utils.hpp b/3rdparty/asio/include/asio/detail/winrt_utils.hpp index d0e184098eb..f33786ccf8b 100644 --- a/3rdparty/asio/include/asio/detail/winrt_utils.hpp +++ b/3rdparty/asio/include/asio/detail/winrt_utils.hpp @@ -2,7 +2,7 @@ // detail/winrt_utils.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/detail/winsock_init.hpp b/3rdparty/asio/include/asio/detail/winsock_init.hpp index a9e361a1c94..7914560ab64 100644 --- a/3rdparty/asio/include/asio/detail/winsock_init.hpp +++ b/3rdparty/asio/include/asio/detail/winsock_init.hpp @@ -2,7 +2,7 @@ // detail/winsock_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -47,7 +47,7 @@ protected: ASIO_DECL static void throw_on_error(data& d); }; -template <int Major = 2, int Minor = 0> +template <int Major = 2, int Minor = 2> class winsock_init : private winsock_init_base { public: diff --git a/3rdparty/asio/include/asio/detail/work_dispatcher.hpp b/3rdparty/asio/include/asio/detail/work_dispatcher.hpp index 9ece5014d94..2a473e45af6 100644 --- a/3rdparty/asio/include/asio/detail/work_dispatcher.hpp +++ b/3rdparty/asio/include/asio/detail/work_dispatcher.hpp @@ -2,7 +2,7 @@ // detail/work_dispatcher.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -39,13 +39,13 @@ struct is_work_dispatcher_required : true_type template <typename Handler, typename Executor> struct is_work_dispatcher_required<Handler, Executor, - typename enable_if< + enable_if_t< is_same< typename associated_executor<Handler, Executor>::asio_associated_executor_is_unspecialised, void >::value - >::type> : false_type + >> : false_type { }; @@ -54,15 +54,14 @@ class work_dispatcher { public: template <typename CompletionHandler> - work_dispatcher(ASIO_MOVE_ARG(CompletionHandler) handler, + work_dispatcher(CompletionHandler&& handler, const Executor& handler_ex) - : handler_(ASIO_MOVE_CAST(CompletionHandler)(handler)), + : handler_(static_cast<CompletionHandler&&>(handler)), executor_(asio::prefer(handler_ex, execution::outstanding_work.tracked)) { } -#if defined(ASIO_HAS_MOVE) work_dispatcher(const work_dispatcher& other) : handler_(other.handler_), executor_(other.executor_) @@ -70,28 +69,25 @@ public: } work_dispatcher(work_dispatcher&& other) - : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)), - executor_(ASIO_MOVE_CAST(work_executor_type)(other.executor_)) + : handler_(static_cast<Handler&&>(other.handler_)), + executor_(static_cast<work_executor_type&&>(other.executor_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()() { - execution::execute( - asio::prefer(executor_, - execution::blocking.possibly, - execution::allocator((get_associated_allocator)(handler_))), + associated_allocator_t<Handler> alloc((get_associated_allocator)(handler_)); + asio::prefer(executor_, execution::allocator(alloc)).execute( asio::detail::bind_handler( - ASIO_MOVE_CAST(Handler)(handler_))); + static_cast<Handler&&>(handler_))); } private: - typedef typename decay< - typename prefer_result<const Executor&, + typedef decay_t< + prefer_result_t<const Executor&, execution::outstanding_work_t::tracked_t - >::type - >::type work_executor_type; + > + > work_executor_type; Handler handler_; work_executor_type executor_; @@ -101,18 +97,16 @@ private: template <typename Handler, typename Executor> class work_dispatcher<Handler, Executor, - typename enable_if<!execution::is_executor<Executor>::value>::type> + enable_if_t<!execution::is_executor<Executor>::value>> { public: template <typename CompletionHandler> - work_dispatcher(ASIO_MOVE_ARG(CompletionHandler) handler, - const Executor& handler_ex) + work_dispatcher(CompletionHandler&& handler, const Executor& handler_ex) : work_(handler_ex), - handler_(ASIO_MOVE_CAST(CompletionHandler)(handler)) + handler_(static_cast<CompletionHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) work_dispatcher(const work_dispatcher& other) : work_(other.work_), handler_(other.handler_) @@ -120,19 +114,17 @@ public: } work_dispatcher(work_dispatcher&& other) - : work_(ASIO_MOVE_CAST(executor_work_guard<Executor>)(other.work_)), - handler_(ASIO_MOVE_CAST(Handler)(other.handler_)) + : work_(static_cast<executor_work_guard<Executor>&&>(other.work_)), + handler_(static_cast<Handler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()() { - typename associated_allocator<Handler>::type alloc( - (get_associated_allocator)(handler_)); + associated_allocator_t<Handler> alloc((get_associated_allocator)(handler_)); work_.get_executor().dispatch( asio::detail::bind_handler( - ASIO_MOVE_CAST(Handler)(handler_)), alloc); + static_cast<Handler&&>(handler_)), alloc); work_.reset(); } diff --git a/3rdparty/asio/include/asio/detail/wrapped_handler.hpp b/3rdparty/asio/include/asio/detail/wrapped_handler.hpp index 18ca6d3b955..fce9abfab43 100644 --- a/3rdparty/asio/include/asio/detail/wrapped_handler.hpp +++ b/3rdparty/asio/include/asio/detail/wrapped_handler.hpp @@ -2,7 +2,7 @@ // detail/wrapped_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/bind_handler.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/push_options.hpp" @@ -52,11 +50,10 @@ public: wrapped_handler(Dispatcher dispatcher, Handler& handler) : dispatcher_(dispatcher), - handler_(ASIO_MOVE_CAST(Handler)(handler)) + handler_(static_cast<Handler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) wrapped_handler(const wrapped_handler& other) : dispatcher_(other.dispatcher_), handler_(other.handler_) @@ -65,14 +62,13 @@ public: wrapped_handler(wrapped_handler&& other) : dispatcher_(other.dispatcher_), - handler_(ASIO_MOVE_CAST(Handler)(other.handler_)) + handler_(static_cast<Handler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()() { - dispatcher_.dispatch(ASIO_MOVE_CAST(Handler)(handler_)); + dispatcher_.dispatch(static_cast<Handler&&>(handler_)); } void operator()() const @@ -161,7 +157,7 @@ class rewrapped_handler public: explicit rewrapped_handler(Handler& handler, const Context& context) : context_(context), - handler_(ASIO_MOVE_CAST(Handler)(handler)) + handler_(static_cast<Handler&&>(handler)) { } @@ -171,7 +167,6 @@ public: { } -#if defined(ASIO_HAS_MOVE) rewrapped_handler(const rewrapped_handler& other) : context_(other.context_), handler_(other.handler_) @@ -179,11 +174,10 @@ public: } rewrapped_handler(rewrapped_handler&& other) - : context_(ASIO_MOVE_CAST(Context)(other.context_)), - handler_(ASIO_MOVE_CAST(Handler)(other.handler_)) + : context_(static_cast<Context&&>(other.context_)), + handler_(static_cast<Handler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()() { @@ -201,92 +195,12 @@ public: }; template <typename Dispatcher, typename Handler, typename IsContinuation> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Dispatcher, typename Handler, typename IsContinuation> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Dispatcher, typename Handler, typename IsContinuation> inline bool asio_handler_is_continuation( wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler) { return IsContinuation()(this_handler->dispatcher_, this_handler->handler_); } -template <typename Function, typename Dispatcher, - typename Handler, typename IsContinuation> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler) -{ - this_handler->dispatcher_.dispatch( - rewrapped_handler<Function, Handler>( - function, this_handler->handler_)); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Dispatcher, - typename Handler, typename IsContinuation> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler) -{ - this_handler->dispatcher_.dispatch( - rewrapped_handler<Function, Handler>( - function, this_handler->handler_)); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Context> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - rewrapped_handler<Handler, Context>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler, typename Context> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - rewrapped_handler<Handler, Context>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->context_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - template <typename Dispatcher, typename Context> inline bool asio_handler_is_continuation( rewrapped_handler<Dispatcher, Context>* this_handler) @@ -295,30 +209,6 @@ inline bool asio_handler_is_continuation( this_handler->context_); } -template <typename Function, typename Handler, typename Context> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - rewrapped_handler<Handler, Context>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->context_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler, typename Context> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - rewrapped_handler<Handler, Context>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->context_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - } // namespace detail } // namespace asio diff --git a/3rdparty/asio/include/asio/dispatch.hpp b/3rdparty/asio/include/asio/dispatch.hpp index 64da41b7c25..9eb60a4103d 100644 --- a/3rdparty/asio/include/asio/dispatch.hpp +++ b/3rdparty/asio/include/asio/dispatch.hpp @@ -2,7 +2,7 @@ // dispatch.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,6 +17,7 @@ #include "asio/detail/config.hpp" #include "asio/async_result.hpp" +#include "asio/detail/initiate_dispatch.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution_context.hpp" #include "asio/execution/executor.hpp" @@ -32,27 +33,50 @@ namespace asio { * executor. The function object may be called from the current thread prior to * returning from <tt>dispatch()</tt>. Otherwise, it is queued for execution. * - * This function has the following effects: + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Constructs a function object handler of type @c Handler, initialized - * with <tt>handler(forward<CompletionToken>(token))</tt>. + * @returns This function returns <tt>async_initiate<NullaryToken, + * void()>(Init{}, token)</tt>, where @c Init is a function object type defined + * as: * - * @li Constructs an object @c result of type <tt>async_result<Handler></tt>, - * initializing the object as <tt>result(handler)</tt>. + * @code class Init + * { + * public: + * template <typename CompletionHandler> + * void operator()(CompletionHandler&& completion_handler) const; + * }; @endcode * - * @li Obtains the handler's associated executor object @c ex by performing - * <tt>get_associated_executor(handler)</tt>. + * The function call operator of @c Init: + * + * @li Obtains the handler's associated executor object @c ex of type @c Ex by + * performing @code auto ex = get_associated_executor(handler); @endcode * * @li Obtains the handler's associated allocator object @c alloc by performing - * <tt>get_associated_allocator(handler)</tt>. + * @code auto alloc = get_associated_allocator(handler); @endcode + * + * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs + * @code prefer(ex, execution::allocator(alloc)).execute( + * std::forward<CompletionHandler>(completion_handler)); @endcode * - * @li Performs <tt>ex.dispatch(std::move(handler), alloc)</tt>. + * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs + * @code ex.dispatch( + * std::forward<CompletionHandler>(completion_handler), + * alloc); @endcode * - * @li Returns <tt>result.get()</tt>. + * @par Completion Signature + * @code void() @endcode */ -template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( - ASIO_MOVE_ARG(CompletionToken) token); +template <ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken> +inline auto dispatch(NullaryToken&& token) + -> decltype( + async_initiate<NullaryToken, void()>( + declval<detail::initiate_dispatch>(), token)) +{ + return async_initiate<NullaryToken, void()>( + detail::initiate_dispatch(), token); +} /// Submits a completion token or function object for execution. /** @@ -60,62 +84,114 @@ ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( * The function object may be called from the current thread prior to returning * from <tt>dispatch()</tt>. Otherwise, it is queued for execution. * - * This function has the following effects: - * - * @li Constructs a function object handler of type @c Handler, initialized - * with <tt>handler(forward<CompletionToken>(token))</tt>. + * @param ex The target executor. * - * @li Constructs an object @c result of type <tt>async_result<Handler></tt>, - * initializing the object as <tt>result(handler)</tt>. + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Obtains the handler's associated executor object @c ex1 by performing - * <tt>get_associated_executor(handler)</tt>. + * @returns This function returns <tt>async_initiate<NullaryToken, + * void()>(Init{ex}, token)</tt>, where @c Init is a function object type + * defined as: * - * @li 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>. + * @code class Init + * { + * public: + * using executor_type = Executor; + * explicit Init(const Executor& ex) : ex_(ex) {} + * executor_type get_executor() const noexcept { return ex_; } + * template <typename CompletionHandler> + * void operator()(CompletionHandler&& completion_handler) const; + * private: + * Executor ex_; // exposition only + * }; @endcode * - * @li 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>. + * The function call operator of @c Init: * - * @li Performs <tt>Executor(ex).dispatch(std::move(f), alloc)</tt>. + * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by + * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode * - * @li Returns <tt>result.get()</tt>. + * @li Obtains the handler's associated allocator object @c alloc by performing + * @code auto alloc = get_associated_allocator(handler); @endcode + * + * @li If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a + * function object @c f with a member @c executor_ that is initialised with + * <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c + * handler_ that is a decay-copy of @c completion_handler, and a function call + * operator that performs: + * @code auto a = get_associated_allocator(handler_); + * prefer(executor_, execution::allocator(a)).execute(std::move(handler_)); + * @endcode + * + * @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a + * function object @c f with a member @c work_ that is initialised with + * <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of + * @c completion_handler, and a function call operator that performs: + * @code auto a = get_associated_allocator(handler_); + * work_.get_executor().dispatch(std::move(handler_), a); + * work_.reset(); @endcode + * + * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs + * @code prefer(ex, execution::allocator(alloc)).execute(std::move(f)); @endcode + * + * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs + * @code ex.dispatch(std::move(f), alloc); @endcode + * + * @par Completion Signature + * @code void() @endcode */ template <typename Executor, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( - const Executor& ex, - ASIO_MOVE_ARG(CompletionToken) token - ASIO_DEFAULT_COMPLETION_TOKEN(Executor), - typename constraint< + ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken + = default_completion_token_t<Executor>> +inline auto dispatch(const Executor& ex, + NullaryToken&& token = default_completion_token_t<Executor>(), + constraint_t< execution::is_executor<Executor>::value || is_executor<Executor>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<NullaryToken, void()>( + declval<detail::initiate_dispatch_with_executor<Executor>>(), token)) +{ + return async_initiate<NullaryToken, void()>( + detail::initiate_dispatch_with_executor<Executor>(ex), token); +} /// Submits a completion token or function object for execution. /** + * @param ctx An execution context, from which the target executor is obtained. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode + * * @returns <tt>dispatch(ctx.get_executor(), - * forward<CompletionToken>(token))</tt>. + * forward<NullaryToken>(token))</tt>. + * + * @par Completion Signature + * @code void() @endcode */ template <typename ExecutionContext, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename ExecutionContext::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( - ExecutionContext& ctx, - ASIO_MOVE_ARG(CompletionToken) token - ASIO_DEFAULT_COMPLETION_TOKEN( - typename ExecutionContext::executor_type), - typename constraint<is_convertible< - ExecutionContext&, execution_context&>::value>::type = 0); + ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken + = default_completion_token_t<typename ExecutionContext::executor_type>> +inline auto dispatch(ExecutionContext& ctx, + NullaryToken&& token = default_completion_token_t< + typename ExecutionContext::executor_type>(), + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) + -> decltype( + async_initiate<NullaryToken, void()>( + declval<detail::initiate_dispatch_with_executor< + typename ExecutionContext::executor_type>>(), token)) +{ + return async_initiate<NullaryToken, void()>( + detail::initiate_dispatch_with_executor< + typename ExecutionContext::executor_type>( + ctx.get_executor()), token); +} } // namespace asio #include "asio/detail/pop_options.hpp" -#include "asio/impl/dispatch.hpp" - #endif // ASIO_DISPATCH_HPP diff --git a/3rdparty/asio/include/asio/error.hpp b/3rdparty/asio/include/asio/error.hpp index 8b4decd52d2..d676ee8aa7d 100644 --- a/3rdparty/asio/include/asio/error.hpp +++ b/3rdparty/asio/include/asio/error.hpp @@ -2,7 +2,7 @@ // error.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -223,6 +223,41 @@ enum misc_errors fd_set_failure }; +// boostify: non-boost code starts here +#if !defined(ASIO_ERROR_LOCATION) +# define ASIO_ERROR_LOCATION(e) (void)0 +#endif // !defined(ASIO_ERROR_LOCATION) + +// boostify: non-boost code ends here +#if !defined(ASIO_ERROR_LOCATION) \ + && !defined(ASIO_DISABLE_ERROR_LOCATION) \ + && defined(ASIO_HAS_BOOST_CONFIG) \ + && (BOOST_VERSION >= 107900) + +# define ASIO_ERROR_LOCATION(e) \ + do { \ + BOOST_STATIC_CONSTEXPR boost::source_location loc \ + = BOOST_CURRENT_LOCATION; \ + (e).assign((e), &loc); \ + } while (false) + +#else // !defined(ASIO_ERROR_LOCATION) + // && !defined(ASIO_DISABLE_ERROR_LOCATION) + // && defined(ASIO_HAS_BOOST_CONFIG) + // && (BOOST_VERSION >= 107900) + +# define ASIO_ERROR_LOCATION(e) (void)0 + +#endif // !defined(ASIO_ERROR_LOCATION) + // && !defined(ASIO_DISABLE_ERROR_LOCATION) + // && defined(ASIO_HAS_BOOST_CONFIG) + // && (BOOST_VERSION >= 107900) + +inline void clear(asio::error_code& ec) +{ + ec.assign(0, ec.category()); +} + inline const asio::error_category& get_system_category() { return asio::system_category(); @@ -269,7 +304,6 @@ static const asio::error_category& } // namespace error } // namespace asio -#if defined(ASIO_HAS_STD_SYSTEM_ERROR) namespace std { template<> struct is_error_code_enum<asio::error::basic_errors> @@ -293,7 +327,6 @@ template<> struct is_error_code_enum<asio::error::misc_errors> }; } // namespace std -#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR) namespace asio { namespace error { diff --git a/3rdparty/asio/include/asio/error_code.hpp b/3rdparty/asio/include/asio/error_code.hpp index 4026b9ca58f..5cb07f48c42 100644 --- a/3rdparty/asio/include/asio/error_code.hpp +++ b/3rdparty/asio/include/asio/error_code.hpp @@ -2,7 +2,7 @@ // error_code.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,181 +16,18 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_STD_SYSTEM_ERROR) -# include <system_error> -#else // defined(ASIO_HAS_STD_SYSTEM_ERROR) -# include <string> -# include "asio/detail/noncopyable.hpp" -# if !defined(ASIO_NO_IOSTREAM) -# include <iosfwd> -# endif // !defined(ASIO_NO_IOSTREAM) -#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR) +#include <system_error> #include "asio/detail/push_options.hpp" namespace asio { -#if defined(ASIO_HAS_STD_SYSTEM_ERROR) - typedef std::error_category error_category; - -#else // defined(ASIO_HAS_STD_SYSTEM_ERROR) - -/// Base class for all error categories. -class error_category : private noncopyable -{ -public: - /// Destructor. - virtual ~error_category() - { - } - - /// Returns a string naming the error gategory. - virtual const char* name() const = 0; - - /// Returns a string describing the error denoted by @c value. - virtual std::string message(int value) const = 0; - - /// Equality operator to compare two error categories. - bool operator==(const error_category& rhs) const - { - return this == &rhs; - } - - /// Inequality operator to compare two error categories. - bool operator!=(const error_category& rhs) const - { - return !(*this == rhs); - } -}; - -#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR) +typedef std::error_code error_code; /// Returns the error category used for the system errors produced by asio. extern ASIO_DECL const error_category& system_category(); -#if defined(ASIO_HAS_STD_SYSTEM_ERROR) - -typedef std::error_code error_code; - -#else // defined(ASIO_HAS_STD_SYSTEM_ERROR) - -/// Class to represent an error code value. -class error_code -{ -public: - /// Default constructor. - error_code() - : value_(0), - category_(&system_category()) - { - } - - /// Construct with specific error code and category. - error_code(int v, const error_category& c) - : value_(v), - category_(&c) - { - } - - /// Construct from an error code enum. - template <typename ErrorEnum> - error_code(ErrorEnum e) - { - *this = make_error_code(e); - } - - /// Clear the error value to the default. - void clear() - { - value_ = 0; - category_ = &system_category(); - } - - /// Assign a new error value. - void assign(int v, const error_category& c) - { - value_ = v; - category_ = &c; - } - - /// Get the error value. - int value() const - { - return value_; - } - - /// Get the error category. - const error_category& category() const - { - return *category_; - } - - /// Get the message associated with the error. - std::string message() const - { - return category_->message(value_); - } - - struct unspecified_bool_type_t - { - }; - - typedef void (*unspecified_bool_type)(unspecified_bool_type_t); - - static void unspecified_bool_true(unspecified_bool_type_t) {} - - /// Operator returns non-null if there is a non-success error code. - operator unspecified_bool_type() const - { - if (value_ == 0) - return 0; - else - return &error_code::unspecified_bool_true; - } - - /// Operator to test if the error represents success. - bool operator!() const - { - return value_ == 0; - } - - /// Equality operator to compare two error objects. - friend bool operator==(const error_code& e1, const error_code& e2) - { - return e1.value_ == e2.value_ && e1.category_ == e2.category_; - } - - /// Inequality operator to compare two error objects. - friend bool operator!=(const error_code& e1, const error_code& e2) - { - return e1.value_ != e2.value_ || e1.category_ != e2.category_; - } - -private: - // The value associated with the error code. - int value_; - - // The category associated with the error code. - const error_category* category_; -}; - -# if !defined(ASIO_NO_IOSTREAM) - -/// Output an error code. -template <typename Elem, typename Traits> -std::basic_ostream<Elem, Traits>& operator<<( - std::basic_ostream<Elem, Traits>& os, const error_code& ec) -{ - os << ec.category().name() << ':' << ec.value(); - return os; -} - -# endif // !defined(ASIO_NO_IOSTREAM) - -#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/execution.hpp b/3rdparty/asio/include/asio/execution.hpp index 861b25bb4b4..fa773259fad 100644 --- a/3rdparty/asio/include/asio/execution.hpp +++ b/3rdparty/asio/include/asio/execution.hpp @@ -2,7 +2,7 @@ // execution.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,29 +20,14 @@ #include "asio/execution/bad_executor.hpp" #include "asio/execution/blocking.hpp" #include "asio/execution/blocking_adaptation.hpp" -#include "asio/execution/bulk_execute.hpp" -#include "asio/execution/bulk_guarantee.hpp" -#include "asio/execution/connect.hpp" #include "asio/execution/context.hpp" #include "asio/execution/context_as.hpp" -#include "asio/execution/execute.hpp" #include "asio/execution/executor.hpp" #include "asio/execution/invocable_archetype.hpp" #include "asio/execution/mapping.hpp" #include "asio/execution/occupancy.hpp" -#include "asio/execution/operation_state.hpp" #include "asio/execution/outstanding_work.hpp" #include "asio/execution/prefer_only.hpp" -#include "asio/execution/receiver.hpp" -#include "asio/execution/receiver_invocation_error.hpp" #include "asio/execution/relationship.hpp" -#include "asio/execution/schedule.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" -#include "asio/execution/set_done.hpp" -#include "asio/execution/set_error.hpp" -#include "asio/execution/set_value.hpp" -#include "asio/execution/start.hpp" -#include "asio/execution/submit.hpp" #endif // ASIO_EXECUTION_HPP diff --git a/3rdparty/asio/include/asio/execution/allocator.hpp b/3rdparty/asio/include/asio/execution/allocator.hpp index ea4d56c381a..cdb6a4a9203 100644 --- a/3rdparty/asio/include/asio/execution/allocator.hpp +++ b/3rdparty/asio/include/asio/execution/allocator.hpp @@ -2,7 +2,7 @@ // execution/allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,8 +18,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" #include "asio/is_applicable_property.hpp" #include "asio/traits/query_static_constexpr_member.hpp" #include "asio/traits/static_query.hpp" @@ -37,10 +35,9 @@ namespace execution { template <typename ProtoAllocator> struct allocator_t { - /// The allocator_t property applies to executors, senders, and schedulers. + /// The allocator_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The allocator_t property can be required. static constexpr bool is_requirable = true; @@ -79,23 +76,11 @@ struct allocator_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; template <typename T> struct static_proxy @@ -104,17 +89,17 @@ struct allocator_t struct type { template <typename P> - static constexpr auto query(ASIO_MOVE_ARG(P) p) + static constexpr auto query(P&& p) noexcept( noexcept( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) ) -> decltype( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) { - return T::query(ASIO_MOVE_CAST(P)(p)); + return T::query(static_cast<P&&>(p)); } }; #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) @@ -130,22 +115,19 @@ struct allocator_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(allocator_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = allocator_t::static_query<E>(); + static constexpr const T static_query_v = allocator_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - ASIO_CONSTEXPR ProtoAllocator value() const + constexpr ProtoAllocator value() const { return a_; } @@ -153,7 +135,7 @@ struct allocator_t private: friend struct allocator_t<void>; - explicit ASIO_CONSTEXPR allocator_t(const ProtoAllocator& a) + explicit constexpr allocator_t(const ProtoAllocator& a) : a_(a) { } @@ -173,25 +155,13 @@ struct allocator_t<void> { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; - ASIO_CONSTEXPR allocator_t() + constexpr allocator_t() { } @@ -202,17 +172,17 @@ struct allocator_t<void> struct type { template <typename P> - static constexpr auto query(ASIO_MOVE_ARG(P) p) + static constexpr auto query(P&& p) noexcept( noexcept( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) ) -> decltype( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) { - return T::query(ASIO_MOVE_CAST(P)(p)); + return T::query(static_cast<P&&>(p)); } }; #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) @@ -228,23 +198,20 @@ struct allocator_t<void> #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(allocator_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = allocator_t::static_query<E>(); + static constexpr const T static_query_v = allocator_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename OtherProtoAllocator> - ASIO_CONSTEXPR allocator_t<OtherProtoAllocator> operator()( + constexpr allocator_t<OtherProtoAllocator> operator()( const OtherProtoAllocator& a) const { return allocator_t<OtherProtoAllocator>(a); @@ -258,41 +225,15 @@ const T allocator_t<void>::static_query_v; #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr allocator_t<void> allocator; -#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -template <typename T> -struct allocator_instance -{ - static allocator_t<T> instance; -}; - -template <typename T> -allocator_t<T> allocator_instance<T>::instance; - -namespace { -static const allocator_t<void>& allocator = allocator_instance<void>::instance; -} // namespace -#endif } // namespace execution #if !defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T, typename ProtoAllocator> -struct is_applicable_property<T, execution::allocator_t<ProtoAllocator> > - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> +struct is_applicable_property<T, execution::allocator_t<ProtoAllocator>> + : integral_constant<bool, execution::is_executor<T>::value> { }; @@ -305,18 +246,18 @@ namespace traits { template <typename T, typename ProtoAllocator> struct static_query<T, execution::allocator_t<ProtoAllocator>, - typename enable_if< + enable_if_t< execution::allocator_t<ProtoAllocator>::template query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::allocator_t<ProtoAllocator>::template query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::allocator_t<ProtoAllocator>::template query_static_constexpr_member<T>::value(); diff --git a/3rdparty/asio/include/asio/execution/any_executor.hpp b/3rdparty/asio/include/asio/execution/any_executor.hpp index b5f5233fdfb..a057543b139 100644 --- a/3rdparty/asio/include/asio/execution/any_executor.hpp +++ b/3rdparty/asio/include/asio/execution/any_executor.hpp @@ -2,7 +2,7 @@ // execution/any_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,6 +19,7 @@ #include <new> #include <typeinfo> #include "asio/detail/assert.hpp" +#include "asio/detail/atomic_count.hpp" #include "asio/detail/cstddef.hpp" #include "asio/detail/executor_function.hpp" #include "asio/detail/memory.hpp" @@ -26,10 +27,8 @@ #include "asio/detail/scoped_ptr.hpp" #include "asio/detail/type_traits.hpp" #include "asio/detail/throw_exception.hpp" -#include "asio/detail/variadic_templates.hpp" #include "asio/execution/bad_executor.hpp" #include "asio/execution/blocking.hpp" -#include "asio/execution/execute.hpp" #include "asio/execution/executor.hpp" #include "asio/prefer.hpp" #include "asio/query.hpp" @@ -64,10 +63,25 @@ public: template <class... OtherSupportableProperties> any_executor(any_executor<OtherSupportableProperties...> e); + /// Construct to point to the same target as another any_executor. + template <class... OtherSupportableProperties> + any_executor(std::nothrow_t, + any_executor<OtherSupportableProperties...> e) noexcept; + + /// Construct to point to the same target as another any_executor. + any_executor(std::nothrow_t, const any_executor& e) noexcept; + + /// Construct to point to the same target as another any_executor. + any_executor(std::nothrow_t, any_executor&& e) noexcept; + /// Construct a polymorphic wrapper for the specified executor. template <typename Executor> any_executor(Executor e); + /// Construct a polymorphic wrapper for the specified executor. + template <typename Executor> + any_executor(std::nothrow_t, Executor e) noexcept; + /// Assignment operator. any_executor& operator=(const any_executor& e) noexcept; @@ -126,13 +140,6 @@ public: /// Execute the function on the target executor. /** - * Do not call this function directly. It is intended for use with the - * execution::execute customisation point. - * - * For example: - * @code execution::any_executor<> ex = ...; - * execution::execute(ex, my_function_object); @endcode - * * Throws asio::bad_executor if the polymorphic wrapper has no target. */ template <typename Function> @@ -220,20 +227,9 @@ namespace execution { #if !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL) #define ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename... SupportableProperties> class any_executor; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename = void, typename = void, typename = void, - typename = void, typename = void, typename = void, - typename = void, typename = void, typename = void> -class any_executor; - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - #endif // !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL) template <typename U> @@ -249,15 +245,13 @@ template <typename T, typename = void> struct is_requirable : false_type {}; template <typename T> -struct is_requirable<T, typename enable_if<T::is_requirable>::type> : - true_type {}; +struct is_requirable<T, enable_if_t<T::is_requirable>> : true_type {}; template <typename T, typename = void> struct is_preferable : false_type {}; template <typename T> -struct is_preferable<T, typename enable_if<T::is_preferable>::type> : - true_type {}; +struct is_preferable<T, enable_if_t<T::is_preferable>> : true_type {}; // Trait used to detect context_as property, for backward compatibility. @@ -265,7 +259,7 @@ template <typename T> struct is_context_as : false_type {}; template <typename U> -struct is_context_as<context_as_t<U> > : true_type {}; +struct is_context_as<context_as_t<U>> : true_type {}; // Helper template to: // - Check if a target can supply the supportable properties. @@ -302,53 +296,51 @@ struct supportable_properties<I, void(Prop)> struct found { - ASIO_STATIC_CONSTEXPR(bool, value = true); + static constexpr bool value = true; typedef Prop type; typedef typename Prop::polymorphic_query_result_type query_result_type; - ASIO_STATIC_CONSTEXPR(std::size_t, index = I); + static constexpr std::size_t index = I; }; struct not_found { - ASIO_STATIC_CONSTEXPR(bool, value = false); + static constexpr bool value = false; }; template <typename T> struct find_convertible_property : - conditional< + conditional_t< is_same<T, Prop>::value || is_convertible<T, Prop>::value, found, not_found - >::type {}; + > {}; template <typename T> struct find_convertible_requirable_property : - conditional< + conditional_t< is_requirable<Prop>::value && (is_same<T, Prop>::value || is_convertible<T, Prop>::value), found, not_found - >::type {}; + > {}; template <typename T> struct find_convertible_preferable_property : - conditional< + conditional_t< is_preferable<Prop>::value && (is_same<T, Prop>::value || is_convertible<T, Prop>::value), found, not_found - >::type {}; + > {}; struct find_context_as_property : - conditional< + conditional_t< is_context_as<Prop>::value, found, not_found - >::type {}; + > {}; }; -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <std::size_t I, typename Head, typename... Tail> struct supportable_properties<I, void(Head, Tail...)> { @@ -367,127 +359,136 @@ struct supportable_properties<I, void(Head, Tail...)> template <typename T> struct find_convertible_property : - conditional< + conditional_t< is_convertible<T, Head>::value, typename supportable_properties<I, void(Head)>::found, typename supportable_properties<I + 1, void(Tail...)>::template find_convertible_property<T> - >::type {}; + > {}; template <typename T> struct find_convertible_requirable_property : - conditional< + conditional_t< is_requirable<Head>::value && is_convertible<T, Head>::value, typename supportable_properties<I, void(Head)>::found, typename supportable_properties<I + 1, void(Tail...)>::template find_convertible_requirable_property<T> - >::type {}; + > {}; template <typename T> struct find_convertible_preferable_property : - conditional< + conditional_t< is_preferable<Head>::value && is_convertible<T, Head>::value, typename supportable_properties<I, void(Head)>::found, typename supportable_properties<I + 1, void(Tail...)>::template find_convertible_preferable_property<T> - >::type {}; + > {}; struct find_context_as_property : - conditional< + conditional_t< is_context_as<Head>::value, typename supportable_properties<I, void(Head)>::found, typename supportable_properties<I + 1, void(Tail...)>::find_context_as_property - >::type {}; + > {}; }; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#define ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF(n) \ - template <std::size_t I, \ - typename Head, ASIO_VARIADIC_TPARAMS(n)> \ - struct supportable_properties<I, \ - void(Head, ASIO_VARIADIC_TARGS(n))> \ - { \ - template <typename T> \ - struct is_valid_target : integral_constant<bool, \ - ( \ - supportable_properties<I, \ - void(Head)>::template is_valid_target<T>::value \ - && \ - supportable_properties<I + 1, \ - void(ASIO_VARIADIC_TARGS(n))>::template \ - is_valid_target<T>::value \ - ) \ - > \ - { \ - }; \ - \ - template <typename T> \ - struct find_convertible_property : \ - conditional< \ - is_convertible<T, Head>::value, \ - typename supportable_properties<I, void(Head)>::found, \ - typename supportable_properties<I + 1, \ - void(ASIO_VARIADIC_TARGS(n))>::template \ - find_convertible_property<T> \ - >::type {}; \ - \ - template <typename T> \ - struct find_convertible_requirable_property : \ - conditional< \ - is_requirable<Head>::value \ - && is_convertible<T, Head>::value, \ - typename supportable_properties<I, void(Head)>::found, \ - typename supportable_properties<I + 1, \ - void(ASIO_VARIADIC_TARGS(n))>::template \ - find_convertible_requirable_property<T> \ - >::type {}; \ - \ - template <typename T> \ - struct find_convertible_preferable_property : \ - conditional< \ - is_preferable<Head>::value \ - && is_convertible<T, Head>::value, \ - typename supportable_properties<I, void(Head)>::found, \ - typename supportable_properties<I + 1, \ - void(ASIO_VARIADIC_TARGS(n))>::template \ - find_convertible_preferable_property<T> \ - >::type {}; \ - \ - struct find_context_as_property : \ - conditional< \ - is_context_as<Head>::value, \ - typename supportable_properties<I, void(Head)>::found, \ - typename supportable_properties<I + 1, void( \ - ASIO_VARIADIC_TARGS(n))>::find_context_as_property \ - >::type {}; \ - }; \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF) -#undef ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename T, typename Props> struct is_valid_target_executor : - conditional< + conditional_t< is_executor<T>::value, typename supportable_properties<0, Props>::template is_valid_target<T>, false_type - >::type + > +{ +}; + +template <typename Props> +struct is_valid_target_executor<int, Props> : false_type +{ +}; + +class shared_target_executor { +public: + template <typename E> + shared_target_executor(E&& e, decay_t<E>*& target) + { + impl<decay_t<E>>* i = + new impl<decay_t<E>>(static_cast<E&&>(e)); + target = &i->ex_; + impl_ = i; + } + + template <typename E> + shared_target_executor(std::nothrow_t, E&& e, decay_t<E>*& target) noexcept + { + impl<decay_t<E>>* i = + new (std::nothrow) impl<decay_t<E>>(static_cast<E&&>(e)); + target = i ? &i->ex_ : 0; + impl_ = i; + } + + shared_target_executor(const shared_target_executor& other) noexcept + : impl_(other.impl_) + { + if (impl_) + asio::detail::ref_count_up(impl_->ref_count_); + } + + shared_target_executor(shared_target_executor&& other) noexcept + : impl_(other.impl_) + { + other.impl_ = 0; + } + + ~shared_target_executor() + { + if (impl_) + if (asio::detail::ref_count_down(impl_->ref_count_)) + delete impl_; + } + + void* get() const noexcept + { + return impl_ ? impl_->get() : 0; + } + +private: + shared_target_executor& operator=( + const shared_target_executor& other) = delete; + + shared_target_executor& operator=( + shared_target_executor&& other) = delete; + + struct impl_base + { + impl_base() : ref_count_(1) {} + virtual ~impl_base() {} + virtual void* get() = 0; + asio::detail::atomic_count ref_count_; + }; + + template <typename Executor> + struct impl : impl_base + { + impl(Executor ex) : ex_(static_cast<Executor&&>(ex)) {} + virtual void* get() { return &ex_; } + Executor ex_; + }; + + impl_base* impl_; }; class any_executor_base { public: - any_executor_base() ASIO_NOEXCEPT - : object_fns_(object_fns_table<void>()), + any_executor_base() noexcept + : object_fns_(0), target_(0), - target_fns_(target_fns_table<void>()) + target_fns_(0) { } @@ -506,144 +507,231 @@ public: } template <ASIO_EXECUTION_EXECUTOR Executor> + any_executor_base(std::nothrow_t, Executor ex, false_type) noexcept + : target_fns_(target_fns_table<Executor>( + any_executor_base::query_blocking(ex, + can_query<const Executor&, const execution::blocking_t&>()) + == execution::blocking.always)) + { + any_executor_base::construct_object(std::nothrow, ex, + integral_constant<bool, + sizeof(Executor) <= sizeof(object_type) + && alignment_of<Executor>::value <= alignment_of<object_type>::value + >()); + if (target_ == 0) + { + object_fns_ = 0; + target_fns_ = 0; + } + } + + template <ASIO_EXECUTION_EXECUTOR Executor> any_executor_base(Executor other, true_type) - : object_fns_(object_fns_table<asio::detail::shared_ptr<void> >()), + : object_fns_(object_fns_table<shared_target_executor>()), target_fns_(other.target_fns_) { - asio::detail::shared_ptr<Executor> p = - asio::detail::make_shared<Executor>( - ASIO_MOVE_CAST(Executor)(other)); + Executor* p = 0; + new (&object_) shared_target_executor( + static_cast<Executor&&>(other), p); target_ = p->template target<void>(); - new (&object_) asio::detail::shared_ptr<void>( - ASIO_MOVE_CAST(asio::detail::shared_ptr<Executor>)(p)); } - any_executor_base(const any_executor_base& other) ASIO_NOEXCEPT - : object_fns_(other.object_fns_), + template <ASIO_EXECUTION_EXECUTOR Executor> + any_executor_base(std::nothrow_t, + Executor other, true_type) noexcept + : object_fns_(object_fns_table<shared_target_executor>()), target_fns_(other.target_fns_) { - object_fns_->copy(*this, other); + Executor* p = 0; + new (&object_) shared_target_executor( + std::nothrow, static_cast<Executor&&>(other), p); + if (p) + target_ = p->template target<void>(); + else + { + target_ = 0; + object_fns_ = 0; + target_fns_ = 0; + } } - ~any_executor_base() ASIO_NOEXCEPT + any_executor_base(const any_executor_base& other) noexcept { - object_fns_->destroy(*this); + if (!!other) + { + object_fns_ = other.object_fns_; + target_fns_ = other.target_fns_; + object_fns_->copy(*this, other); + } + else + { + object_fns_ = 0; + target_ = 0; + target_fns_ = 0; + } + } + + ~any_executor_base() noexcept + { + if (!!*this) + object_fns_->destroy(*this); } any_executor_base& operator=( - const any_executor_base& other) ASIO_NOEXCEPT + const any_executor_base& other) noexcept { if (this != &other) { - object_fns_->destroy(*this); - object_fns_ = other.object_fns_; - target_fns_ = other.target_fns_; - object_fns_->copy(*this, other); + if (!!*this) + object_fns_->destroy(*this); + if (!!other) + { + object_fns_ = other.object_fns_; + target_fns_ = other.target_fns_; + object_fns_->copy(*this, other); + } + else + { + object_fns_ = 0; + target_ = 0; + target_fns_ = 0; + } } return *this; } - any_executor_base& operator=(nullptr_t) ASIO_NOEXCEPT + any_executor_base& operator=(nullptr_t) noexcept { - object_fns_->destroy(*this); + if (target_) + object_fns_->destroy(*this); target_ = 0; - object_fns_ = object_fns_table<void>(); - target_fns_ = target_fns_table<void>(); + object_fns_ = 0; + target_fns_ = 0; return *this; } -#if defined(ASIO_HAS_MOVE) - - any_executor_base(any_executor_base&& other) ASIO_NOEXCEPT - : object_fns_(other.object_fns_), - target_fns_(other.target_fns_) + any_executor_base(any_executor_base&& other) noexcept { - other.object_fns_ = object_fns_table<void>(); - other.target_fns_ = target_fns_table<void>(); - object_fns_->move(*this, other); - other.target_ = 0; + if (other.target_) + { + object_fns_ = other.object_fns_; + target_fns_ = other.target_fns_; + other.object_fns_ = 0; + other.target_fns_ = 0; + object_fns_->move(*this, other); + other.target_ = 0; + } + else + { + object_fns_ = 0; + target_ = 0; + target_fns_ = 0; + } } any_executor_base& operator=( - any_executor_base&& other) ASIO_NOEXCEPT + any_executor_base&& other) noexcept { if (this != &other) { - object_fns_->destroy(*this); - object_fns_ = other.object_fns_; - other.object_fns_ = object_fns_table<void>(); - target_fns_ = other.target_fns_; - other.target_fns_ = target_fns_table<void>(); - object_fns_->move(*this, other); - other.target_ = 0; + if (!!*this) + object_fns_->destroy(*this); + if (!!other) + { + object_fns_ = other.object_fns_; + target_fns_ = other.target_fns_; + other.object_fns_ = 0; + other.target_fns_ = 0; + object_fns_->move(*this, other); + other.target_ = 0; + } + else + { + object_fns_ = 0; + target_ = 0; + target_fns_ = 0; + } } return *this; } -#endif // defined(ASIO_HAS_MOVE) - - void swap(any_executor_base& other) ASIO_NOEXCEPT + void swap(any_executor_base& other) noexcept { if (this != &other) { - any_executor_base tmp(ASIO_MOVE_CAST(any_executor_base)(other)); - other = ASIO_MOVE_CAST(any_executor_base)(*this); - *this = ASIO_MOVE_CAST(any_executor_base)(tmp); + any_executor_base tmp(static_cast<any_executor_base&&>(other)); + other = static_cast<any_executor_base&&>(*this); + *this = static_cast<any_executor_base&&>(tmp); } } template <typename F> - void execute(ASIO_MOVE_ARG(F) f) const + void execute(F&& f) const { - if (target_fns_->blocking_execute != 0) + if (target_) { - asio::detail::non_const_lvalue<F> f2(f); - target_fns_->blocking_execute(*this, function_view(f2.value)); + if (target_fns_->blocking_execute != 0) + { + asio::detail::non_const_lvalue<F> f2(f); + target_fns_->blocking_execute(*this, function_view(f2.value)); + } + else + { + target_fns_->execute(*this, + function(static_cast<F&&>(f), std::allocator<void>())); + } } else { - target_fns_->execute(*this, - function(ASIO_MOVE_CAST(F)(f), std::allocator<void>())); + bad_executor ex; + asio::detail::throw_exception(ex); } } template <typename Executor> Executor* target() { - return static_cast<Executor*>(target_); + return target_ && (is_same<Executor, void>::value + || target_fns_->target_type() == target_type_ex<Executor>()) + ? static_cast<Executor*>(target_) : 0; } template <typename Executor> const Executor* target() const { - return static_cast<Executor*>(target_); + return target_ && (is_same<Executor, void>::value + || target_fns_->target_type() == target_type_ex<Executor>()) + ? static_cast<const Executor*>(target_) : 0; } #if !defined(ASIO_NO_TYPEID) const std::type_info& target_type() const + { + return target_ ? target_fns_->target_type() : typeid(void); + } #else // !defined(ASIO_NO_TYPEID) const void* target_type() const -#endif // !defined(ASIO_NO_TYPEID) { - return target_fns_->target_type(); + return target_ ? target_fns_->target_type() : 0; } +#endif // !defined(ASIO_NO_TYPEID) struct unspecified_bool_type_t {}; typedef void (*unspecified_bool_type)(unspecified_bool_type_t); static void unspecified_bool_true(unspecified_bool_type_t) {} - operator unspecified_bool_type() const ASIO_NOEXCEPT + operator unspecified_bool_type() const noexcept { return target_ ? &any_executor_base::unspecified_bool_true : 0; } - bool operator!() const ASIO_NOEXCEPT + bool operator!() const noexcept { return target_ == 0; } protected: - bool equality_helper(const any_executor_base& other) const ASIO_NOEXCEPT + bool equality_helper(const any_executor_base& other) const noexcept { if (target_ == other.target_) return true; @@ -676,73 +764,38 @@ protected: const void* (*target)(const any_executor_base&); }; - static void destroy_void(any_executor_base&) - { - } - - static void copy_void(any_executor_base& ex1, const any_executor_base&) - { - ex1.target_ = 0; - } - - static void move_void(any_executor_base& ex1, any_executor_base&) - { - ex1.target_ = 0; - } - - static const void* target_void(const any_executor_base&) - { - return 0; - } - - template <typename Obj> - static const object_fns* object_fns_table( - typename enable_if< - is_same<Obj, void>::value - >::type* = 0) - { - static const object_fns fns = - { - &any_executor_base::destroy_void, - &any_executor_base::copy_void, - &any_executor_base::move_void, - &any_executor_base::target_void - }; - return &fns; - } - static void destroy_shared(any_executor_base& ex) { - typedef asio::detail::shared_ptr<void> type; + typedef shared_target_executor type; ex.object<type>().~type(); } static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2) { - typedef asio::detail::shared_ptr<void> type; + typedef shared_target_executor type; new (&ex1.object_) type(ex2.object<type>()); ex1.target_ = ex2.target_; } static void move_shared(any_executor_base& ex1, any_executor_base& ex2) { - typedef asio::detail::shared_ptr<void> type; - new (&ex1.object_) type(ASIO_MOVE_CAST(type)(ex2.object<type>())); + typedef shared_target_executor type; + new (&ex1.object_) type(static_cast<type&&>(ex2.object<type>())); ex1.target_ = ex2.target_; ex2.object<type>().~type(); } static const void* target_shared(const any_executor_base& ex) { - typedef asio::detail::shared_ptr<void> type; + typedef shared_target_executor type; return ex.object<type>().get(); } template <typename Obj> static const object_fns* object_fns_table( - typename enable_if< - is_same<Obj, asio::detail::shared_ptr<void> >::value - >::type* = 0) + enable_if_t< + is_same<Obj, shared_target_executor>::value + >* = 0) { static const object_fns fns = { @@ -770,7 +823,7 @@ protected: template <typename Obj> static void move_object(any_executor_base& ex1, any_executor_base& ex2) { - new (&ex1.object_) Obj(ASIO_MOVE_CAST(Obj)(ex2.object<Obj>())); + new (&ex1.object_) Obj(static_cast<Obj&&>(ex2.object<Obj>())); ex1.target_ = &ex1.object<Obj>(); ex2.object<Obj>().~Obj(); } @@ -783,10 +836,10 @@ protected: template <typename Obj> static const object_fns* object_fns_table( - typename enable_if< + enable_if_t< !is_same<Obj, void>::value - && !is_same<Obj, asio::detail::shared_ptr<void> >::value - >::type* = 0) + && !is_same<Obj, shared_target_executor>::value + >* = 0) { static const object_fns fns = { @@ -809,57 +862,11 @@ protected: const void* (*target_type)(); #endif // !defined(ASIO_NO_TYPEID) bool (*equal)(const any_executor_base&, const any_executor_base&); - void (*execute)(const any_executor_base&, ASIO_MOVE_ARG(function)); + void (*execute)(const any_executor_base&, function&&); void (*blocking_execute)(const any_executor_base&, function_view); }; #if !defined(ASIO_NO_TYPEID) - static const std::type_info& target_type_void() - { - return typeid(void); - } -#else // !defined(ASIO_NO_TYPEID) - static const void* target_type_void() - { - return 0; - } -#endif // !defined(ASIO_NO_TYPEID) - - static bool equal_void(const any_executor_base&, const any_executor_base&) - { - return true; - } - - static void execute_void(const any_executor_base&, - ASIO_MOVE_ARG(function)) - { - bad_executor ex; - asio::detail::throw_exception(ex); - } - - static void blocking_execute_void(const any_executor_base&, function_view) - { - bad_executor ex; - asio::detail::throw_exception(ex); - } - - template <typename Ex> - static const target_fns* target_fns_table( - typename enable_if< - is_same<Ex, void>::value - >::type* = 0) - { - static const target_fns fns = - { - &any_executor_base::target_type_void, - &any_executor_base::equal_void, - &any_executor_base::execute_void, - &any_executor_base::blocking_execute_void - }; - return &fns; - } - -#if !defined(ASIO_NO_TYPEID) template <typename Ex> static const std::type_info& target_type_ex() { @@ -878,27 +885,33 @@ protected: static bool equal_ex(const any_executor_base& ex1, const any_executor_base& ex2) { - return *ex1.target<Ex>() == *ex2.target<Ex>(); + const Ex* p1 = ex1.target<Ex>(); + const Ex* p2 = ex2.target<Ex>(); + ASIO_ASSUME(p1 != 0 && p2 != 0); + return *p1 == *p2; } template <typename Ex> - static void execute_ex(const any_executor_base& ex, - ASIO_MOVE_ARG(function) f) + static void execute_ex(const any_executor_base& ex, function&& f) { - execution::execute(*ex.target<Ex>(), ASIO_MOVE_CAST(function)(f)); + const Ex* p = ex.target<Ex>(); + ASIO_ASSUME(p != 0); + p->execute(static_cast<function&&>(f)); } template <typename Ex> static void blocking_execute_ex(const any_executor_base& ex, function_view f) { - execution::execute(*ex.target<Ex>(), f); + const Ex* p = ex.target<Ex>(); + ASIO_ASSUME(p != 0); + p->execute(f); } template <typename Ex> static const target_fns* target_fns_table(bool is_always_blocking, - typename enable_if< + enable_if_t< !is_same<Ex, void>::value - >::type* = 0) + >* = 0) { static const target_fns fns_with_execute = { @@ -932,10 +945,10 @@ protected: template <typename Ex, class Prop> static void query_fn_non_void(void*, const void* ex, const void* prop, - typename enable_if< + enable_if_t< asio::can_query<const Ex&, const Prop&>::value && is_same<typename Prop::polymorphic_query_result_type, void>::value - >::type*) + >*) { asio::query(*static_cast<const Ex*>(ex), *static_cast<const Prop*>(prop)); @@ -943,23 +956,23 @@ protected: template <typename Ex, class Prop> static void query_fn_non_void(void*, const void*, const void*, - typename enable_if< + enable_if_t< !asio::can_query<const Ex&, const Prop&>::value && is_same<typename Prop::polymorphic_query_result_type, void>::value - >::type*) + >*) { } template <typename Ex, class Prop> static void query_fn_non_void(void* result, const void* ex, const void* prop, - typename enable_if< + enable_if_t< asio::can_query<const Ex&, const Prop&>::value && !is_same<typename Prop::polymorphic_query_result_type, void>::value && is_reference<typename Prop::polymorphic_query_result_type>::value - >::type*) + >*) { - *static_cast<typename remove_reference< - typename Prop::polymorphic_query_result_type>::type**>(result) + *static_cast<remove_reference_t< + typename Prop::polymorphic_query_result_type>**>(result) = &static_cast<typename Prop::polymorphic_query_result_type>( asio::query(*static_cast<const Ex*>(ex), *static_cast<const Prop*>(prop))); @@ -967,22 +980,22 @@ protected: template <typename Ex, class Prop> static void query_fn_non_void(void*, const void*, const void*, - typename enable_if< + enable_if_t< !asio::can_query<const Ex&, const Prop&>::value && !is_same<typename Prop::polymorphic_query_result_type, void>::value && is_reference<typename Prop::polymorphic_query_result_type>::value - >::type*) + >*) { std::terminate(); // Combination should not be possible. } template <typename Ex, class Prop> static void query_fn_non_void(void* result, const void* ex, const void* prop, - typename enable_if< + enable_if_t< asio::can_query<const Ex&, const Prop&>::value && !is_same<typename Prop::polymorphic_query_result_type, void>::value && is_scalar<typename Prop::polymorphic_query_result_type>::value - >::type*) + >*) { *static_cast<typename Prop::polymorphic_query_result_type*>(result) = static_cast<typename Prop::polymorphic_query_result_type>( @@ -992,11 +1005,11 @@ protected: template <typename Ex, class Prop> static void query_fn_non_void(void* result, const void*, const void*, - typename enable_if< + enable_if_t< !asio::can_query<const Ex&, const Prop&>::value && !is_same<typename Prop::polymorphic_query_result_type, void>::value && is_scalar<typename Prop::polymorphic_query_result_type>::value - >::type*) + >*) { *static_cast<typename Prop::polymorphic_query_result_type*>(result) = typename Prop::polymorphic_query_result_type(); @@ -1004,12 +1017,12 @@ protected: template <typename Ex, class Prop> static void query_fn_non_void(void* result, const void* ex, const void* prop, - typename enable_if< + enable_if_t< asio::can_query<const Ex&, const Prop&>::value && !is_same<typename Prop::polymorphic_query_result_type, void>::value && !is_reference<typename Prop::polymorphic_query_result_type>::value && !is_scalar<typename Prop::polymorphic_query_result_type>::value - >::type*) + >*) { *static_cast<typename Prop::polymorphic_query_result_type**>(result) = new typename Prop::polymorphic_query_result_type( @@ -1026,18 +1039,18 @@ protected: template <typename Ex, class Prop> static void query_fn_impl(void* result, const void* ex, const void* prop, - typename enable_if< + enable_if_t< is_same<Ex, void>::value - >::type*) + >*) { query_fn_void(result, ex, prop); } template <typename Ex, class Prop> static void query_fn_impl(void* result, const void* ex, const void* prop, - typename enable_if< + enable_if_t< !is_same<Ex, void>::value - >::type*) + >*) { query_fn_non_void<Ex, Prop>(result, ex, prop, 0); } @@ -1050,9 +1063,9 @@ protected: template <typename Poly, typename Ex, class Prop> static Poly require_fn_impl(const void*, const void*, - typename enable_if< + enable_if_t< is_same<Ex, void>::value - >::type*) + >*) { bad_executor ex; asio::detail::throw_exception(ex); @@ -1061,9 +1074,9 @@ protected: template <typename Poly, typename Ex, class Prop> static Poly require_fn_impl(const void* ex, const void* prop, - typename enable_if< + enable_if_t< !is_same<Ex, void>::value && Prop::is_requirable - >::type*) + >*) { return asio::require(*static_cast<const Ex*>(ex), *static_cast<const Prop*>(prop)); @@ -1083,9 +1096,9 @@ protected: template <typename Poly, typename Ex, class Prop> static Poly prefer_fn_impl(const void*, const void*, - typename enable_if< + enable_if_t< is_same<Ex, void>::value - >::type*) + >*) { bad_executor ex; asio::detail::throw_exception(ex); @@ -1094,9 +1107,9 @@ protected: template <typename Poly, typename Ex, class Prop> static Poly prefer_fn_impl(const void* ex, const void* prop, - typename enable_if< + enable_if_t< !is_same<Ex, void>::value && Prop::is_preferable - >::type*) + >*) { return asio::prefer(*static_cast<const Ex*>(ex), *static_cast<const Prop*>(prop)); @@ -1143,27 +1156,44 @@ private: void construct_object(Executor& ex, true_type) { object_fns_ = object_fns_table<Executor>(); - target_ = new (&object_) Executor(ASIO_MOVE_CAST(Executor)(ex)); + target_ = new (&object_) Executor(static_cast<Executor&&>(ex)); } template <typename Executor> void construct_object(Executor& ex, false_type) { - object_fns_ = object_fns_table<asio::detail::shared_ptr<void> >(); - asio::detail::shared_ptr<Executor> p = - asio::detail::make_shared<Executor>( - ASIO_MOVE_CAST(Executor)(ex)); - target_ = p.get(); - new (&object_) asio::detail::shared_ptr<void>( - ASIO_MOVE_CAST(asio::detail::shared_ptr<Executor>)(p)); + object_fns_ = object_fns_table<shared_target_executor>(); + Executor* p = 0; + new (&object_) shared_target_executor( + static_cast<Executor&&>(ex), p); + target_ = p; + } + + template <typename Executor> + void construct_object(std::nothrow_t, + Executor& ex, true_type) noexcept + { + object_fns_ = object_fns_table<Executor>(); + target_ = new (&object_) Executor(static_cast<Executor&&>(ex)); + } + + template <typename Executor> + void construct_object(std::nothrow_t, + Executor& ex, false_type) noexcept + { + object_fns_ = object_fns_table<shared_target_executor>(); + Executor* p = 0; + new (&object_) shared_target_executor( + std::nothrow, static_cast<Executor&&>(ex), p); + target_ = p; } /*private:*/public: // template <typename...> friend class any_executor; typedef aligned_storage< - sizeof(asio::detail::shared_ptr<void>), - alignment_of<asio::detail::shared_ptr<void> >::value + sizeof(asio::detail::shared_ptr<void>) + sizeof(void*), + alignment_of<asio::detail::shared_ptr<void>>::value >::type object_type; object_type object_; @@ -1180,8 +1210,7 @@ struct any_executor_context #if !defined(ASIO_NO_TS_EXECUTORS) template <typename Derived, typename Property> -struct any_executor_context<Derived, Property, - typename enable_if<Property::value>::type> +struct any_executor_context<Derived, Property, enable_if_t<Property::value>> { typename Property::query_result_type context() const { @@ -1197,32 +1226,45 @@ template <> class any_executor<> : public detail::any_executor_base { public: - any_executor() ASIO_NOEXCEPT + any_executor() noexcept : detail::any_executor_base() { } - any_executor(nullptr_t) ASIO_NOEXCEPT + any_executor(nullptr_t) noexcept : detail::any_executor_base() { } template <typename Executor> any_executor(Executor ex, - typename enable_if< - conditional< + enable_if_t< + conditional_t< !is_same<Executor, any_executor>::value && !is_base_of<detail::any_executor_base, Executor>::value, is_executor<Executor>, false_type - >::type::value - >::type* = 0) + >::value + >* = 0) : detail::any_executor_base( - ASIO_MOVE_CAST(Executor)(ex), false_type()) + static_cast<Executor&&>(ex), false_type()) { } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) + template <typename Executor> + any_executor(std::nothrow_t, Executor ex, + enable_if_t< + conditional_t< + !is_same<Executor, any_executor>::value + && !is_base_of<detail::any_executor_base, Executor>::value, + is_executor<Executor>, + false_type + >::value + >* = 0) noexcept + : detail::any_executor_base(std::nothrow, + static_cast<Executor&&>(ex), false_type()) + { + } template <typename... OtherSupportableProperties> any_executor(any_executor<OtherSupportableProperties...> other) @@ -1231,25 +1273,27 @@ public: { } -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename U0, typename U1, typename U2, typename U3, - typename U4, typename U5, typename U6, typename U7> - any_executor(any_executor<U0, U1, U2, U3, U4, U5, U6, U7> other) + template <typename... OtherSupportableProperties> + any_executor(std::nothrow_t, + any_executor<OtherSupportableProperties...> other) noexcept : detail::any_executor_base( static_cast<const detail::any_executor_base&>(other)) { } -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) + any_executor(const any_executor& other) noexcept + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)) + { + } - any_executor(const any_executor& other) ASIO_NOEXCEPT + any_executor(std::nothrow_t, const any_executor& other) noexcept : detail::any_executor_base( static_cast<const detail::any_executor_base&>(other)) { } - any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT + any_executor& operator=(const any_executor& other) noexcept { if (this != &other) { @@ -1259,22 +1303,27 @@ public: return *this; } - any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT + any_executor& operator=(nullptr_t p) noexcept { detail::any_executor_base::operator=(p); return *this; } -#if defined(ASIO_HAS_MOVE) + any_executor(any_executor&& other) noexcept + : detail::any_executor_base( + static_cast<any_executor_base&&>( + static_cast<any_executor_base&>(other))) + { + } - any_executor(any_executor&& other) ASIO_NOEXCEPT + any_executor(std::nothrow_t, any_executor&& other) noexcept : detail::any_executor_base( static_cast<any_executor_base&&>( static_cast<any_executor_base&>(other))) { } - any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT + any_executor& operator=(any_executor&& other) noexcept { if (this != &other) { @@ -1285,9 +1334,7 @@ public: return *this; } -#endif // defined(ASIO_HAS_MOVE) - - void swap(any_executor& other) ASIO_NOEXCEPT + void swap(any_executor& other) noexcept { detail::any_executor_base::swap( static_cast<detail::any_executor_base&>(other)); @@ -1299,77 +1346,75 @@ public: using detail::any_executor_base::operator unspecified_bool_type; using detail::any_executor_base::operator!; - bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT + bool equality_helper(const any_executor& other) const noexcept { return any_executor_base::equality_helper(other); } template <typename AnyExecutor1, typename AnyExecutor2> - friend typename enable_if< + friend enable_if_t< is_base_of<any_executor, AnyExecutor1>::value || is_base_of<any_executor, AnyExecutor2>::value, bool - >::type operator==(const AnyExecutor1& a, - const AnyExecutor2& b) ASIO_NOEXCEPT + > operator==(const AnyExecutor1& a, + const AnyExecutor2& b) noexcept { return static_cast<const any_executor&>(a).equality_helper(b); } template <typename AnyExecutor> - friend typename enable_if< + friend enable_if_t< is_same<AnyExecutor, any_executor>::value, bool - >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT + > operator==(const AnyExecutor& a, nullptr_t) noexcept { return !a; } template <typename AnyExecutor> - friend typename enable_if< + friend enable_if_t< is_same<AnyExecutor, any_executor>::value, bool - >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT + > operator==(nullptr_t, const AnyExecutor& b) noexcept { return !b; } template <typename AnyExecutor1, typename AnyExecutor2> - friend typename enable_if< + friend enable_if_t< is_base_of<any_executor, AnyExecutor1>::value || is_base_of<any_executor, AnyExecutor2>::value, bool - >::type operator!=(const AnyExecutor1& a, - const AnyExecutor2& b) ASIO_NOEXCEPT + > operator!=(const AnyExecutor1& a, + const AnyExecutor2& b) noexcept { return !static_cast<const any_executor&>(a).equality_helper(b); } template <typename AnyExecutor> - friend typename enable_if< + friend enable_if_t< is_same<AnyExecutor, any_executor>::value, bool - >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT + > operator!=(const AnyExecutor& a, nullptr_t) noexcept { return !!a; } template <typename AnyExecutor> - friend typename enable_if< + friend enable_if_t< is_same<AnyExecutor, any_executor>::value, bool - >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT + > operator!=(nullptr_t, const AnyExecutor& b) noexcept { return !!b; } }; -inline void swap(any_executor<>& a, any_executor<>& b) ASIO_NOEXCEPT +inline void swap(any_executor<>& a, any_executor<>& b) noexcept { return a.swap(b); } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename... SupportableProperties> class any_executor : public detail::any_executor_base, @@ -1379,13 +1424,13 @@ class any_executor : 0, void(SupportableProperties...)>::find_context_as_property> { public: - any_executor() ASIO_NOEXCEPT + any_executor() noexcept : detail::any_executor_base(), prop_fns_(prop_fns_table<void>()) { } - any_executor(nullptr_t) ASIO_NOEXCEPT + any_executor(nullptr_t) noexcept : detail::any_executor_base(), prop_fns_(prop_fns_table<void>()) { @@ -1393,49 +1438,100 @@ public: template <typename Executor> any_executor(Executor ex, - typename enable_if< - conditional< + enable_if_t< + conditional_t< !is_same<Executor, any_executor>::value && !is_base_of<detail::any_executor_base, Executor>::value, detail::is_valid_target_executor< Executor, void(SupportableProperties...)>, false_type - >::type::value - >::type* = 0) + >::value + >* = 0) : detail::any_executor_base( - ASIO_MOVE_CAST(Executor)(ex), false_type()), + static_cast<Executor&&>(ex), false_type()), prop_fns_(prop_fns_table<Executor>()) { } + template <typename Executor> + any_executor(std::nothrow_t, Executor ex, + enable_if_t< + conditional_t< + !is_same<Executor, any_executor>::value + && !is_base_of<detail::any_executor_base, Executor>::value, + detail::is_valid_target_executor< + Executor, void(SupportableProperties...)>, + false_type + >::value + >* = 0) noexcept + : detail::any_executor_base(std::nothrow, + static_cast<Executor&&>(ex), false_type()), + prop_fns_(prop_fns_table<Executor>()) + { + if (this->template target<void>() == 0) + prop_fns_ = prop_fns_table<void>(); + } + template <typename... OtherSupportableProperties> any_executor(any_executor<OtherSupportableProperties...> other, - typename enable_if< - conditional< + enable_if_t< + conditional_t< !is_same< any_executor<OtherSupportableProperties...>, any_executor >::value, typename detail::supportable_properties< 0, void(SupportableProperties...)>::template is_valid_target< - any_executor<OtherSupportableProperties...> >, + any_executor<OtherSupportableProperties...>>, false_type - >::type::value - >::type* = 0) - : detail::any_executor_base(ASIO_MOVE_CAST( - any_executor<OtherSupportableProperties...>)(other), true_type()), - prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...> >()) + >::value + >* = 0) + : detail::any_executor_base( + static_cast<any_executor<OtherSupportableProperties...>&&>(other), + true_type()), + prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...>>()) { } - any_executor(const any_executor& other) ASIO_NOEXCEPT + template <typename... OtherSupportableProperties> + any_executor(std::nothrow_t, + any_executor<OtherSupportableProperties...> other, + enable_if_t< + conditional_t< + !is_same< + any_executor<OtherSupportableProperties...>, + any_executor + >::value, + typename detail::supportable_properties< + 0, void(SupportableProperties...)>::template is_valid_target< + any_executor<OtherSupportableProperties...>>, + false_type + >::value + >* = 0) noexcept + : detail::any_executor_base(std::nothrow, + static_cast<any_executor<OtherSupportableProperties...>&&>(other), + true_type()), + prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...>>()) + { + if (this->template target<void>() == 0) + prop_fns_ = prop_fns_table<void>(); + } + + any_executor(const any_executor& other) noexcept : detail::any_executor_base( static_cast<const detail::any_executor_base&>(other)), prop_fns_(other.prop_fns_) { } - any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT + any_executor(std::nothrow_t, const any_executor& other) noexcept + : detail::any_executor_base( + static_cast<const detail::any_executor_base&>(other)), + prop_fns_(other.prop_fns_) + { + } + + any_executor& operator=(const any_executor& other) noexcept { if (this != &other) { @@ -1446,16 +1542,23 @@ public: return *this; } - any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT + any_executor& operator=(nullptr_t p) noexcept { prop_fns_ = prop_fns_table<void>(); detail::any_executor_base::operator=(p); return *this; } -#if defined(ASIO_HAS_MOVE) + any_executor(any_executor&& other) noexcept + : detail::any_executor_base( + static_cast<any_executor_base&&>( + static_cast<any_executor_base&>(other))), + prop_fns_(other.prop_fns_) + { + other.prop_fns_ = prop_fns_table<void>(); + } - any_executor(any_executor&& other) ASIO_NOEXCEPT + any_executor(std::nothrow_t, any_executor&& other) noexcept : detail::any_executor_base( static_cast<any_executor_base&&>( static_cast<any_executor_base&>(other))), @@ -1464,7 +1567,7 @@ public: other.prop_fns_ = prop_fns_table<void>(); } - any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT + any_executor& operator=(any_executor&& other) noexcept { if (this != &other) { @@ -1476,9 +1579,7 @@ public: return *this; } -#endif // defined(ASIO_HAS_MOVE) - - void swap(any_executor& other) ASIO_NOEXCEPT + void swap(any_executor& other) noexcept { if (this != &other) { @@ -1496,65 +1597,65 @@ public: using detail::any_executor_base::operator unspecified_bool_type; using detail::any_executor_base::operator!; - bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT + bool equality_helper(const any_executor& other) const noexcept { return any_executor_base::equality_helper(other); } template <typename AnyExecutor1, typename AnyExecutor2> - friend typename enable_if< + friend enable_if_t< is_base_of<any_executor, AnyExecutor1>::value || is_base_of<any_executor, AnyExecutor2>::value, bool - >::type operator==(const AnyExecutor1& a, - const AnyExecutor2& b) ASIO_NOEXCEPT + > operator==(const AnyExecutor1& a, + const AnyExecutor2& b) noexcept { return static_cast<const any_executor&>(a).equality_helper(b); } template <typename AnyExecutor> - friend typename enable_if< + friend enable_if_t< is_same<AnyExecutor, any_executor>::value, bool - >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT + > operator==(const AnyExecutor& a, nullptr_t) noexcept { return !a; } template <typename AnyExecutor> - friend typename enable_if< + friend enable_if_t< is_same<AnyExecutor, any_executor>::value, bool - >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT + > operator==(nullptr_t, const AnyExecutor& b) noexcept { return !b; } template <typename AnyExecutor1, typename AnyExecutor2> - friend typename enable_if< + friend enable_if_t< is_base_of<any_executor, AnyExecutor1>::value || is_base_of<any_executor, AnyExecutor2>::value, bool - >::type operator!=(const AnyExecutor1& a, - const AnyExecutor2& b) ASIO_NOEXCEPT + > operator!=(const AnyExecutor1& a, + const AnyExecutor2& b) noexcept { return !static_cast<const any_executor&>(a).equality_helper(b); } template <typename AnyExecutor> - friend typename enable_if< + friend enable_if_t< is_same<AnyExecutor, any_executor>::value, bool - >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT + > operator!=(const AnyExecutor& a, nullptr_t) noexcept { return !!a; } template <typename AnyExecutor> - friend typename enable_if< + friend enable_if_t< is_same<AnyExecutor, any_executor>::value, bool - >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT + > operator!=(nullptr_t, const AnyExecutor& b) noexcept { return !!b; } @@ -1567,13 +1668,18 @@ public: template <typename Property> void query(const Property& p, - typename enable_if< + enable_if_t< is_same< typename find_convertible_property<Property>::query_result_type, void >::value - >::type* = 0) const + >* = 0) const { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } typedef find_convertible_property<Property> found; prop_fns_[found::index].query(0, object_fns_->target(*this), &static_cast<const typename found::type&>(p)); @@ -1582,7 +1688,7 @@ public: template <typename Property> typename find_convertible_property<Property>::query_result_type query(const Property& p, - typename enable_if< + enable_if_t< !is_same< typename find_convertible_property<Property>::query_result_type, void @@ -1591,11 +1697,15 @@ public: is_reference< typename find_convertible_property<Property>::query_result_type >::value - >::type* = 0) const + >* = 0) const { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } typedef find_convertible_property<Property> found; - typename remove_reference< - typename found::query_result_type>::type* result = 0; + remove_reference_t<typename found::query_result_type>* result = 0; prop_fns_[found::index].query(&result, object_fns_->target(*this), &static_cast<const typename found::type&>(p)); return *result; @@ -1604,7 +1714,7 @@ public: template <typename Property> typename find_convertible_property<Property>::query_result_type query(const Property& p, - typename enable_if< + enable_if_t< !is_same< typename find_convertible_property<Property>::query_result_type, void @@ -1613,8 +1723,13 @@ public: is_scalar< typename find_convertible_property<Property>::query_result_type >::value - >::type* = 0) const + >* = 0) const { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } typedef find_convertible_property<Property> found; typename found::query_result_type result; prop_fns_[found::index].query(&result, object_fns_->target(*this), @@ -1625,7 +1740,7 @@ public: template <typename Property> typename find_convertible_property<Property>::query_result_type query(const Property& p, - typename enable_if< + enable_if_t< !is_same< typename find_convertible_property<Property>::query_result_type, void @@ -1638,8 +1753,13 @@ public: !is_scalar< typename find_convertible_property<Property>::query_result_type >::value - >::type* = 0) const + >* = 0) const { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } typedef find_convertible_property<Property> found; typename found::query_result_type* result; prop_fns_[found::index].query(&result, object_fns_->target(*this), @@ -1656,10 +1776,15 @@ public: template <typename Property> any_executor require(const Property& p, - typename enable_if< + enable_if_t< find_convertible_requirable_property<Property>::value - >::type* = 0) const + >* = 0) const { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } typedef find_convertible_requirable_property<Property> found; return prop_fns_[found::index].require(object_fns_->target(*this), &static_cast<const typename found::type&>(p)); @@ -1673,10 +1798,15 @@ public: template <typename Property> any_executor prefer(const Property& p, - typename enable_if< + enable_if_t< find_convertible_preferable_property<Property>::value - >::type* = 0) const + >* = 0) const { + if (!target_) + { + bad_executor ex; + asio::detail::throw_exception(ex); + } typedef find_convertible_preferable_property<Property> found; return prop_fns_[found::index].prefer(object_fns_->target(*this), &static_cast<const typename found::type&>(p)); @@ -1705,634 +1835,91 @@ public: template <typename... SupportableProperties> inline void swap(any_executor<SupportableProperties...>& a, - any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT + any_executor<SupportableProperties...>& b) noexcept { return a.swap(b); } -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \ - ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_##n - -#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 \ - { \ - &detail::any_executor_base::query_fn<Ex, T1>, \ - &detail::any_executor_base::require_fn<any_executor, Ex, T1>, \ - &detail::any_executor_base::prefer_fn<any_executor, Ex, T1> \ - } -#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 \ - ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1, \ - { \ - &detail::any_executor_base::query_fn<Ex, T2>, \ - &detail::any_executor_base::require_fn<any_executor, Ex, T2>, \ - &detail::any_executor_base::prefer_fn<any_executor, Ex, T2> \ - } -#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 \ - ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2, \ - { \ - &detail::any_executor_base::query_fn<Ex, T3>, \ - &detail::any_executor_base::require_fn<any_executor, Ex, T3>, \ - &detail::any_executor_base::prefer_fn<any_executor, Ex, T3> \ - } -#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 \ - ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3, \ - { \ - &detail::any_executor_base::query_fn<Ex, T4>, \ - &detail::any_executor_base::require_fn<any_executor, Ex, T4>, \ - &detail::any_executor_base::prefer_fn<any_executor, Ex, T4> \ - } -#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 \ - ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4, \ - { \ - &detail::any_executor_base::query_fn<Ex, T5>, \ - &detail::any_executor_base::require_fn<any_executor, Ex, T5>, \ - &detail::any_executor_base::prefer_fn<any_executor, Ex, T5> \ - } -#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 \ - ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5, \ - { \ - &detail::any_executor_base::query_fn<Ex, T6>, \ - &detail::any_executor_base::require_fn<any_executor, Ex, T6>, \ - &detail::any_executor_base::prefer_fn<any_executor, Ex, T6> \ - } -#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 \ - ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6, \ - { \ - &detail::any_executor_base::query_fn<Ex, T7>, \ - &detail::any_executor_base::require_fn<any_executor, Ex, T7>, \ - &detail::any_executor_base::prefer_fn<any_executor, Ex, T7> \ - } -#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 \ - ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7, \ - { \ - &detail::any_executor_base::query_fn<Ex, T8>, \ - &detail::any_executor_base::require_fn<any_executor, Ex, T8>, \ - &detail::any_executor_base::prefer_fn<any_executor, Ex, T8> \ - } - -#if defined(ASIO_HAS_MOVE) - -# define ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \ - any_executor(any_executor&& other) ASIO_NOEXCEPT \ - : detail::any_executor_base( \ - static_cast<any_executor_base&&>( \ - static_cast<any_executor_base&>(other))), \ - prop_fns_(other.prop_fns_) \ - { \ - other.prop_fns_ = prop_fns_table<void>(); \ - } \ - \ - any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT \ - { \ - if (this != &other) \ - { \ - prop_fns_ = other.prop_fns_; \ - detail::any_executor_base::operator=( \ - static_cast<detail::any_executor_base&&>( \ - static_cast<detail::any_executor_base&>(other))); \ - } \ - return *this; \ - } \ - /**/ -#else // defined(ASIO_HAS_MOVE) - -# define ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS - -#endif // defined(ASIO_HAS_MOVE) - -#define ASIO_PRIVATE_ANY_EXECUTOR_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - class any_executor<ASIO_VARIADIC_TARGS(n)> : \ - public detail::any_executor_base, \ - public detail::any_executor_context< \ - any_executor<ASIO_VARIADIC_TARGS(n)>, \ - typename detail::supportable_properties< \ - 0, void(ASIO_VARIADIC_TARGS(n))>::find_context_as_property> \ - { \ - public: \ - any_executor() ASIO_NOEXCEPT \ - : detail::any_executor_base(), \ - prop_fns_(prop_fns_table<void>()) \ - { \ - } \ - \ - any_executor(nullptr_t) ASIO_NOEXCEPT \ - : detail::any_executor_base(), \ - prop_fns_(prop_fns_table<void>()) \ - { \ - } \ - \ - template <ASIO_EXECUTION_EXECUTOR Executor> \ - any_executor(Executor ex, \ - typename enable_if< \ - conditional< \ - !is_same<Executor, any_executor>::value \ - && !is_base_of<detail::any_executor_base, Executor>::value, \ - detail::is_valid_target_executor< \ - Executor, void(ASIO_VARIADIC_TARGS(n))>, \ - false_type \ - >::type::value \ - >::type* = 0) \ - : detail::any_executor_base(ASIO_MOVE_CAST( \ - Executor)(ex), false_type()), \ - prop_fns_(prop_fns_table<Executor>()) \ - { \ - } \ - \ - any_executor(const any_executor& other) ASIO_NOEXCEPT \ - : detail::any_executor_base( \ - static_cast<const detail::any_executor_base&>(other)), \ - prop_fns_(other.prop_fns_) \ - { \ - } \ - \ - any_executor(any_executor<> other) \ - : detail::any_executor_base(ASIO_MOVE_CAST( \ - any_executor<>)(other), true_type()), \ - prop_fns_(prop_fns_table<any_executor<> >()) \ - { \ - } \ - \ - template <typename OtherAnyExecutor> \ - any_executor(OtherAnyExecutor other, \ - typename enable_if< \ - conditional< \ - !is_same<OtherAnyExecutor, any_executor>::value \ - && is_base_of<detail::any_executor_base, \ - OtherAnyExecutor>::value, \ - typename detail::supportable_properties< \ - 0, void(ASIO_VARIADIC_TARGS(n))>::template \ - is_valid_target<OtherAnyExecutor>, \ - false_type \ - >::type::value \ - >::type* = 0) \ - : detail::any_executor_base(ASIO_MOVE_CAST( \ - OtherAnyExecutor)(other), true_type()), \ - prop_fns_(prop_fns_table<OtherAnyExecutor>()) \ - { \ - } \ - \ - any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT \ - { \ - if (this != &other) \ - { \ - prop_fns_ = other.prop_fns_; \ - detail::any_executor_base::operator=( \ - static_cast<const detail::any_executor_base&>(other)); \ - } \ - return *this; \ - } \ - \ - any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT \ - { \ - prop_fns_ = prop_fns_table<void>(); \ - detail::any_executor_base::operator=(p); \ - return *this; \ - } \ - \ - ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \ - \ - void swap(any_executor& other) ASIO_NOEXCEPT \ - { \ - if (this != &other) \ - { \ - detail::any_executor_base::swap( \ - static_cast<detail::any_executor_base&>(other)); \ - const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_; \ - other.prop_fns_ = prop_fns_; \ - prop_fns_ = tmp_prop_fns; \ - } \ - } \ - \ - using detail::any_executor_base::execute; \ - using detail::any_executor_base::target; \ - using detail::any_executor_base::target_type; \ - using detail::any_executor_base::operator unspecified_bool_type; \ - using detail::any_executor_base::operator!; \ - \ - bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT \ - { \ - return any_executor_base::equality_helper(other); \ - } \ - \ - template <typename AnyExecutor1, typename AnyExecutor2> \ - friend typename enable_if< \ - is_base_of<any_executor, AnyExecutor1>::value \ - || is_base_of<any_executor, AnyExecutor2>::value, \ - bool \ - >::type operator==(const AnyExecutor1& a, \ - const AnyExecutor2& b) ASIO_NOEXCEPT \ - { \ - return static_cast<const any_executor&>(a).equality_helper(b); \ - } \ - \ - template <typename AnyExecutor> \ - friend typename enable_if< \ - is_same<AnyExecutor, any_executor>::value, \ - bool \ - >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT \ - { \ - return !a; \ - } \ - \ - template <typename AnyExecutor> \ - friend typename enable_if< \ - is_same<AnyExecutor, any_executor>::value, \ - bool \ - >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT \ - { \ - return !b; \ - } \ - \ - template <typename AnyExecutor1, typename AnyExecutor2> \ - friend typename enable_if< \ - is_base_of<any_executor, AnyExecutor1>::value \ - || is_base_of<any_executor, AnyExecutor2>::value, \ - bool \ - >::type operator!=(const AnyExecutor1& a, \ - const AnyExecutor2& b) ASIO_NOEXCEPT \ - { \ - return !static_cast<const any_executor&>(a).equality_helper(b); \ - } \ - \ - template <typename AnyExecutor> \ - friend typename enable_if< \ - is_same<AnyExecutor, any_executor>::value, \ - bool \ - >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT \ - { \ - return !!a; \ - } \ - \ - template <typename AnyExecutor> \ - friend typename enable_if< \ - is_same<AnyExecutor, any_executor>::value, \ - bool \ - >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT \ - { \ - return !!b; \ - } \ - \ - template <typename T> \ - struct find_convertible_property : \ - detail::supportable_properties< \ - 0, void(ASIO_VARIADIC_TARGS(n))>::template \ - find_convertible_property<T> {}; \ - \ - template <typename Property> \ - void query(const Property& p, \ - typename enable_if< \ - is_same< \ - typename find_convertible_property<Property>::query_result_type, \ - void \ - >::value \ - >::type* = 0) const \ - { \ - typedef find_convertible_property<Property> found; \ - prop_fns_[found::index].query(0, object_fns_->target(*this), \ - &static_cast<const typename found::type&>(p)); \ - } \ - \ - template <typename Property> \ - typename find_convertible_property<Property>::query_result_type \ - query(const Property& p, \ - typename enable_if< \ - !is_same< \ - typename find_convertible_property<Property>::query_result_type, \ - void \ - >::value \ - && \ - is_reference< \ - typename find_convertible_property<Property>::query_result_type \ - >::value \ - >::type* = 0) const \ - { \ - typedef find_convertible_property<Property> found; \ - typename remove_reference< \ - typename found::query_result_type>::type* result; \ - prop_fns_[found::index].query(&result, object_fns_->target(*this), \ - &static_cast<const typename found::type&>(p)); \ - return *result; \ - } \ - \ - template <typename Property> \ - typename find_convertible_property<Property>::query_result_type \ - query(const Property& p, \ - typename enable_if< \ - !is_same< \ - typename find_convertible_property<Property>::query_result_type, \ - void \ - >::value \ - && \ - is_scalar< \ - typename find_convertible_property<Property>::query_result_type \ - >::value \ - >::type* = 0) const \ - { \ - typedef find_convertible_property<Property> found; \ - typename found::query_result_type result; \ - prop_fns_[found::index].query(&result, object_fns_->target(*this), \ - &static_cast<const typename found::type&>(p)); \ - return result; \ - } \ - \ - template <typename Property> \ - typename find_convertible_property<Property>::query_result_type \ - query(const Property& p, \ - typename enable_if< \ - !is_same< \ - typename find_convertible_property<Property>::query_result_type, \ - void \ - >::value \ - && \ - !is_reference< \ - typename find_convertible_property<Property>::query_result_type \ - >::value \ - && \ - !is_scalar< \ - typename find_convertible_property<Property>::query_result_type \ - >::value \ - >::type* = 0) const \ - { \ - typedef find_convertible_property<Property> found; \ - typename found::query_result_type* result; \ - prop_fns_[found::index].query(&result, object_fns_->target(*this), \ - &static_cast<const typename found::type&>(p)); \ - return *asio::detail::scoped_ptr< \ - typename found::query_result_type>(result); \ - } \ - \ - template <typename T> \ - struct find_convertible_requirable_property : \ - detail::supportable_properties< \ - 0, void(ASIO_VARIADIC_TARGS(n))>::template \ - find_convertible_requirable_property<T> {}; \ - \ - template <typename Property> \ - any_executor require(const Property& p, \ - typename enable_if< \ - find_convertible_requirable_property<Property>::value \ - >::type* = 0) const \ - { \ - typedef find_convertible_requirable_property<Property> found; \ - return prop_fns_[found::index].require(object_fns_->target(*this), \ - &static_cast<const typename found::type&>(p)); \ - } \ - \ - template <typename T> \ - struct find_convertible_preferable_property : \ - detail::supportable_properties< \ - 0, void(ASIO_VARIADIC_TARGS(n))>::template \ - find_convertible_preferable_property<T> {}; \ - \ - template <typename Property> \ - any_executor prefer(const Property& p, \ - typename enable_if< \ - find_convertible_preferable_property<Property>::value \ - >::type* = 0) const \ - { \ - typedef find_convertible_preferable_property<Property> found; \ - return prop_fns_[found::index].prefer(object_fns_->target(*this), \ - &static_cast<const typename found::type&>(p)); \ - } \ - \ - template <typename Ex> \ - static const prop_fns<any_executor>* prop_fns_table() \ - { \ - static const prop_fns<any_executor> fns[] = \ - { \ - ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \ - }; \ - return fns; \ - } \ - \ - const prop_fns<any_executor>* prop_fns_; \ - typedef detail::supportable_properties<0, \ - void(ASIO_VARIADIC_TARGS(n))> supportable_properties_type; \ - }; \ - \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - inline void swap(any_executor<ASIO_VARIADIC_TARGS(n)>& a, \ - any_executor<ASIO_VARIADIC_TARGS(n)>& b) ASIO_NOEXCEPT \ - { \ - return a.swap(b); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_DEF) -#undef ASIO_PRIVATE_ANY_EXECUTOR_DEF -#undef ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS -#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS -#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 -#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 -#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 -#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 -#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 -#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 -#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 -#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 - -#endif // if defined(ASIO_HAS_VARIADIC_TEMPLATES) - } // namespace execution namespace traits { #if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename... SupportableProperties> -struct equality_comparable<execution::any_executor<SupportableProperties...> > -{ - static const bool is_valid = true; - static const bool is_noexcept = true; -}; - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <> -struct equality_comparable<execution::any_executor<> > +struct equality_comparable<execution::any_executor<SupportableProperties...>> { - static const bool is_valid = true; - static const bool is_noexcept = true; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; }; -#define ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - struct equality_comparable< \ - execution::any_executor<ASIO_VARIADIC_TARGS(n)> > \ - { \ - static const bool is_valid = true; \ - static const bool is_noexcept = true; \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE( - ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF) -#undef ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) #if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename F, typename... SupportableProperties> struct execute_member<execution::any_executor<SupportableProperties...>, F> { - static const bool is_valid = true; - static const bool is_noexcept = false; - typedef void result_type; -}; - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename F> -struct execute_member<execution::any_executor<>, F> -{ - static const bool is_valid = true; - static const bool is_noexcept = false; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef void result_type; }; -#define ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF(n) \ - template <typename F, ASIO_VARIADIC_TPARAMS(n)> \ - struct execute_member< \ - execution::any_executor<ASIO_VARIADIC_TARGS(n)>, F> \ - { \ - static const bool is_valid = true; \ - static const bool is_noexcept = false; \ - typedef void result_type; \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE( - ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF) -#undef ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) #if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename Prop, typename... SupportableProperties> struct query_member< execution::any_executor<SupportableProperties...>, Prop, - typename enable_if< + enable_if_t< execution::detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_property<Prop>::value - >::type> + >> { - static const bool is_valid = true; - static const bool is_noexcept = false; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef typename execution::detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_property<Prop>::query_result_type result_type; }; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#define ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF(n) \ - template <typename Prop, ASIO_VARIADIC_TPARAMS(n)> \ - struct query_member< \ - execution::any_executor<ASIO_VARIADIC_TARGS(n)>, Prop, \ - typename enable_if< \ - execution::detail::supportable_properties< \ - 0, void(ASIO_VARIADIC_TARGS(n))>::template \ - find_convertible_property<Prop>::value \ - >::type> \ - { \ - static const bool is_valid = true; \ - static const bool is_noexcept = false; \ - typedef typename execution::detail::supportable_properties< \ - 0, void(ASIO_VARIADIC_TARGS(n))>::template \ - find_convertible_property<Prop>::query_result_type result_type; \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF) -#undef ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename Prop, typename... SupportableProperties> struct require_member< execution::any_executor<SupportableProperties...>, Prop, - typename enable_if< + enable_if_t< execution::detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_requirable_property<Prop>::value - >::type> + >> { - static const bool is_valid = true; - static const bool is_noexcept = false; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef execution::any_executor<SupportableProperties...> result_type; }; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#define ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF(n) \ - template <typename Prop, ASIO_VARIADIC_TPARAMS(n)> \ - struct require_member< \ - execution::any_executor<ASIO_VARIADIC_TARGS(n)>, Prop, \ - typename enable_if< \ - execution::detail::supportable_properties< \ - 0, void(ASIO_VARIADIC_TARGS(n))>::template \ - find_convertible_requirable_property<Prop>::value \ - >::type> \ - { \ - static const bool is_valid = true; \ - static const bool is_noexcept = false; \ - typedef execution::any_executor<ASIO_VARIADIC_TARGS(n)> result_type; \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE( - ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF) -#undef ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) #if !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) template <typename Prop, typename... SupportableProperties> struct prefer_member< execution::any_executor<SupportableProperties...>, Prop, - typename enable_if< + enable_if_t< execution::detail::supportable_properties< 0, void(SupportableProperties...)>::template find_convertible_preferable_property<Prop>::value - >::type> + >> { - static const bool is_valid = true; - static const bool is_noexcept = false; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef execution::any_executor<SupportableProperties...> result_type; }; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#define ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF(n) \ - template <typename Prop, ASIO_VARIADIC_TPARAMS(n)> \ - struct prefer_member< \ - execution::any_executor<ASIO_VARIADIC_TARGS(n)>, Prop, \ - typename enable_if< \ - execution::detail::supportable_properties< \ - 0, void(ASIO_VARIADIC_TARGS(n))>::template \ - find_convertible_preferable_property<Prop>::value \ - >::type> \ - { \ - static const bool is_valid = true; \ - static const bool is_noexcept = false; \ - typedef execution::any_executor<ASIO_VARIADIC_TARGS(n)> result_type; \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF) -#undef ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) #endif // !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) } // namespace traits diff --git a/3rdparty/asio/include/asio/execution/bad_executor.hpp b/3rdparty/asio/include/asio/execution/bad_executor.hpp index 0532ceff17a..791951684fe 100644 --- a/3rdparty/asio/include/asio/execution/bad_executor.hpp +++ b/3rdparty/asio/include/asio/execution/bad_executor.hpp @@ -2,7 +2,7 @@ // execution/bad_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -28,11 +28,10 @@ class bad_executor { public: /// Constructor. - ASIO_DECL bad_executor() ASIO_NOEXCEPT; + ASIO_DECL bad_executor() noexcept; /// Obtain message associated with exception. - ASIO_DECL virtual const char* what() const - ASIO_NOEXCEPT_OR_NOTHROW; + ASIO_DECL virtual const char* what() const noexcept; }; } // namespace execution diff --git a/3rdparty/asio/include/asio/execution/blocking.hpp b/3rdparty/asio/include/asio/execution/blocking.hpp index 76a2eb523dc..e120299bded 100644 --- a/3rdparty/asio/include/asio/execution/blocking.hpp +++ b/3rdparty/asio/include/asio/execution/blocking.hpp @@ -2,7 +2,7 @@ // execution/blocking.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,14 +17,12 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/execution/execute.hpp" #include "asio/execution/executor.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" #include "asio/is_applicable_property.hpp" #include "asio/prefer.hpp" #include "asio/query.hpp" #include "asio/require.hpp" +#include "asio/traits/execute_member.hpp" #include "asio/traits/query_free.hpp" #include "asio/traits/query_member.hpp" #include "asio/traits/query_static_constexpr_member.hpp" @@ -43,10 +41,9 @@ namespace execution { /// behaviour of their execution functions. struct blocking_t { - /// The blocking_t property applies to executors, senders, and schedulers. + /// The blocking_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The top-level blocking_t property cannot be required. static constexpr bool is_requirable = false; @@ -62,11 +59,9 @@ struct blocking_t /// submitted function object. struct possibly_t { - /// The blocking_t::possibly_t property applies to executors, senders, and - /// schedulers. + /// The blocking_t::possibly_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The blocking_t::possibly_t property can be required. static constexpr bool is_requirable = true; @@ -92,11 +87,9 @@ struct blocking_t /// function object. struct always_t { - /// The blocking_t::always_t property applies to executors, senders, and - /// schedulers. + /// The blocking_t::always_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The blocking_t::always_t property can be required. static constexpr bool is_requirable = true; @@ -122,11 +115,9 @@ struct blocking_t /// submitted function object. struct never_t { - /// The blocking_t::never_t property applies to executors, senders, and - /// schedulers. + /// The blocking_t::never_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The blocking_t::never_t property can be required. static constexpr bool is_requirable = true; @@ -199,8 +190,8 @@ template <int I> struct allowed_t; template <typename Executor, typename Function> void blocking_execute( - ASIO_MOVE_ARG(Executor) ex, - ASIO_MOVE_ARG(Function) func); + Executor&& ex, + Function&& func); } // namespace blocking_adaptation @@ -209,45 +200,33 @@ struct blocking_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); + static constexpr bool is_requirable = false; + static constexpr bool is_preferable = false; typedef blocking_t polymorphic_query_result_type; typedef detail::blocking::possibly_t<I> possibly_t; typedef detail::blocking::always_t<I> always_t; typedef detail::blocking::never_t<I> never_t; - ASIO_CONSTEXPR blocking_t() + constexpr blocking_t() : value_(-1) { } - ASIO_CONSTEXPR blocking_t(possibly_t) + constexpr blocking_t(possibly_t) : value_(0) { } - ASIO_CONSTEXPR blocking_t(always_t) + constexpr blocking_t(always_t) : value_(1) { } - ASIO_CONSTEXPR blocking_t(never_t) + constexpr blocking_t(never_t) : value_(2) { } @@ -259,16 +238,14 @@ struct blocking_t struct type { template <typename P> - auto query(ASIO_MOVE_ARG(P) p) const + auto query(P&& p) const noexcept( noexcept( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ) ) -> decltype( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ); }; #else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) @@ -283,17 +260,17 @@ struct blocking_t struct type { template <typename P> - static constexpr auto query(ASIO_MOVE_ARG(P) p) + static constexpr auto query(P&& p) noexcept( noexcept( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) ) -> decltype( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) { - return T::query(ASIO_MOVE_CAST(P)(p)); + return T::query(static_cast<P&&>(p)); } }; #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) @@ -313,88 +290,87 @@ struct blocking_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, possibly_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, possibly_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, possibly_t>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, always_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::static_query<T, possibly_t>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, always_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, always_t>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, never_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::static_query<T, possibly_t>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::static_query<T, always_t>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, never_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, never_t>::value(); } template <typename E, typename T = decltype(blocking_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = blocking_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - friend ASIO_CONSTEXPR bool operator==( + friend constexpr bool operator==( const blocking_t& a, const blocking_t& b) { return a.value_ == b.value_; } - friend ASIO_CONSTEXPR bool operator!=( + friend constexpr bool operator!=( const blocking_t& a, const blocking_t& b) { return a.value_ != b.value_; @@ -402,22 +378,20 @@ struct blocking_t struct convertible_from_blocking_t { - ASIO_CONSTEXPR convertible_from_blocking_t(blocking_t) {} + constexpr convertible_from_blocking_t(blocking_t) {} }; template <typename Executor> - friend ASIO_CONSTEXPR blocking_t query( + friend constexpr blocking_t query( const Executor& ex, convertible_from_blocking_t, - typename enable_if< + enable_if_t< can_query<const Executor&, possibly_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, blocking_t<>::possibly_t>::value)) + noexcept(is_nothrow_query<const Executor&, blocking_t<>::possibly_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, possibly_t>::value)) + noexcept(is_nothrow_query<const Executor&, possibly_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -425,21 +399,19 @@ struct blocking_t } template <typename Executor> - friend ASIO_CONSTEXPR blocking_t query( + friend constexpr blocking_t query( const Executor& ex, convertible_from_blocking_t, - typename enable_if< + enable_if_t< !can_query<const Executor&, possibly_t>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< can_query<const Executor&, always_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, blocking_t<>::always_t>::value)) + noexcept(is_nothrow_query<const Executor&, blocking_t<>::always_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, always_t>::value)) + noexcept(is_nothrow_query<const Executor&, always_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -447,24 +419,22 @@ struct blocking_t } template <typename Executor> - friend ASIO_CONSTEXPR blocking_t query( + friend constexpr blocking_t query( const Executor& ex, convertible_from_blocking_t, - typename enable_if< + enable_if_t< !can_query<const Executor&, possibly_t>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !can_query<const Executor&, always_t>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< can_query<const Executor&, never_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, blocking_t<>::never_t>::value)) + noexcept(is_nothrow_query<const Executor&, blocking_t<>::never_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, never_t>::value)) + noexcept(is_nothrow_query<const Executor&, never_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -475,10 +445,6 @@ struct blocking_t ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(always_t, always); ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(never_t, never); -#if !defined(ASIO_HAS_CONSTEXPR) - static const blocking_t instance; -#endif // !defined(ASIO_HAS_CONSTEXPR) - private: int value_; }; @@ -490,11 +456,6 @@ const T blocking_t<I>::static_query_v; #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_CONSTEXPR) -template <int I> -const blocking_t<I> blocking_t<I>::instance; -#endif - template <int I> const typename blocking_t<I>::possibly_t blocking_t<I>::possibly; @@ -511,26 +472,14 @@ struct possibly_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; typedef blocking_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR possibly_t() + constexpr possibly_t() { } @@ -547,78 +496,77 @@ struct possibly_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename T> - static ASIO_CONSTEXPR possibly_t static_query( - typename enable_if< + static constexpr possibly_t static_query( + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::query_free<T, possibly_t>::is_valid - >::type* = 0, - typename enable_if< - !can_query<T, always_t<I> >::value - >::type* = 0, - typename enable_if< - !can_query<T, never_t<I> >::value - >::type* = 0) ASIO_NOEXCEPT + >* = 0, + enable_if_t< + !can_query<T, always_t<I>>::value + >* = 0, + enable_if_t< + !can_query<T, never_t<I>>::value + >* = 0) noexcept { return possibly_t(); } template <typename E, typename T = decltype(possibly_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = possibly_t::static_query<E>(); #endif // defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR blocking_t<I> value() + static constexpr blocking_t<I> value() { return possibly_t(); } - friend ASIO_CONSTEXPR bool operator==( + friend constexpr bool operator==( const possibly_t&, const possibly_t&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( + friend constexpr bool operator!=( const possibly_t&, const possibly_t&) { return false; } - friend ASIO_CONSTEXPR bool operator==( + friend constexpr bool operator==( const possibly_t&, const always_t<I>&) { return false; } - friend ASIO_CONSTEXPR bool operator!=( + friend constexpr bool operator!=( const possibly_t&, const always_t<I>&) { return true; } - friend ASIO_CONSTEXPR bool operator==( + friend constexpr bool operator==( const possibly_t&, const never_t<I>&) { return false; } - friend ASIO_CONSTEXPR bool operator!=( + friend constexpr bool operator!=( const possibly_t&, const never_t<I>&) { return true; @@ -636,125 +584,110 @@ template <typename Executor> class adapter { public: - adapter(int, const Executor& e) ASIO_NOEXCEPT + adapter(int, const Executor& e) noexcept : executor_(e) { } - adapter(const adapter& other) ASIO_NOEXCEPT + adapter(const adapter& other) noexcept : executor_(other.executor_) { } -#if defined(ASIO_HAS_MOVE) - adapter(adapter&& other) ASIO_NOEXCEPT - : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)) + adapter(adapter&& other) noexcept + : executor_(static_cast<Executor&&>(other.executor_)) { } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) template <int I> - static ASIO_CONSTEXPR always_t<I> query( - blocking_t<I>) ASIO_NOEXCEPT + static constexpr always_t<I> query(blocking_t<I>) noexcept { return always_t<I>(); } template <int I> - static ASIO_CONSTEXPR always_t<I> query( - possibly_t<I>) ASIO_NOEXCEPT + static constexpr always_t<I> query(possibly_t<I>) noexcept { return always_t<I>(); } template <int I> - static ASIO_CONSTEXPR always_t<I> query( - always_t<I>) ASIO_NOEXCEPT + static constexpr always_t<I> query(always_t<I>) noexcept { return always_t<I>(); } template <int I> - static ASIO_CONSTEXPR always_t<I> query( - never_t<I>) ASIO_NOEXCEPT + static constexpr always_t<I> query(never_t<I>) noexcept { return always_t<I>(); } template <typename Property> - typename enable_if< + enable_if_t< can_query<const Executor&, Property>::value, - typename query_result<const Executor&, Property>::type - >::type query(const Property& p) const - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, Property>::value)) + query_result_t<const Executor&, Property> + > query(const Property& p) const + noexcept(is_nothrow_query<const Executor&, Property>::value) { return asio::query(executor_, p); } template <int I> - typename enable_if< - can_require<const Executor&, possibly_t<I> >::value, - typename require_result<const Executor&, possibly_t<I> >::type - >::type require(possibly_t<I>) const ASIO_NOEXCEPT + enable_if_t< + can_require<const Executor&, possibly_t<I>>::value, + require_result_t<const Executor&, possibly_t<I>> + > require(possibly_t<I>) const noexcept { return asio::require(executor_, possibly_t<I>()); } template <int I> - typename enable_if< - can_require<const Executor&, never_t<I> >::value, - typename require_result<const Executor&, never_t<I> >::type - >::type require(never_t<I>) const ASIO_NOEXCEPT + enable_if_t< + can_require<const Executor&, never_t<I>>::value, + require_result_t<const Executor&, never_t<I>> + > require(never_t<I>) const noexcept { return asio::require(executor_, never_t<I>()); } template <typename Property> - typename enable_if< + enable_if_t< can_require<const Executor&, Property>::value, - adapter<typename decay< - typename require_result<const Executor&, Property>::type - >::type> - >::type require(const Property& p) const - ASIO_NOEXCEPT_IF(( - is_nothrow_require<const Executor&, Property>::value)) + adapter<decay_t<require_result_t<const Executor&, Property>>> + > require(const Property& p) const + noexcept(is_nothrow_require<const Executor&, Property>::value) { - return adapter<typename decay< - typename require_result<const Executor&, Property>::type - >::type>(0, asio::require(executor_, p)); + return adapter<decay_t<require_result_t<const Executor&, Property>>>( + 0, asio::require(executor_, p)); } template <typename Property> - typename enable_if< + enable_if_t< can_prefer<const Executor&, Property>::value, - adapter<typename decay< - typename prefer_result<const Executor&, Property>::type - >::type> - >::type prefer(const Property& p) const - ASIO_NOEXCEPT_IF(( - is_nothrow_prefer<const Executor&, Property>::value)) + adapter<decay_t<prefer_result_t<const Executor&, Property>>> + > prefer(const Property& p) const + noexcept(is_nothrow_prefer<const Executor&, Property>::value) { - return adapter<typename decay< - typename prefer_result<const Executor&, Property>::type - >::type>(0, asio::prefer(executor_, p)); + return adapter<decay_t<prefer_result_t<const Executor&, Property>>>( + 0, asio::prefer(executor_, p)); } template <typename Function> - typename enable_if< - execution::can_execute<const Executor&, Function>::value - >::type execute(ASIO_MOVE_ARG(Function) f) const + enable_if_t< + traits::execute_member<const Executor&, Function>::is_valid + > execute(Function&& f) const { blocking_adaptation::blocking_execute( - executor_, ASIO_MOVE_CAST(Function)(f)); + executor_, static_cast<Function&&>(f)); } - friend bool operator==(const adapter& a, const adapter& b) ASIO_NOEXCEPT + friend bool operator==(const adapter& a, const adapter& b) noexcept { return a.executor_ == b.executor_; } - friend bool operator!=(const adapter& a, const adapter& b) ASIO_NOEXCEPT + friend bool operator!=(const adapter& a, const adapter& b) noexcept { return a.executor_ != b.executor_; } @@ -768,26 +701,14 @@ struct always_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = false; typedef blocking_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR always_t() + constexpr always_t() { } @@ -804,57 +725,54 @@ struct always_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(always_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = always_t::static_query<E>(); + static constexpr const T static_query_v = always_t::static_query<E>(); #endif // defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR blocking_t<I> value() + static constexpr blocking_t<I> value() { return always_t(); } - friend ASIO_CONSTEXPR bool operator==( + friend constexpr bool operator==( const always_t&, const always_t&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( + friend constexpr bool operator!=( const always_t&, const always_t&) { return false; } - friend ASIO_CONSTEXPR bool operator==( + friend constexpr bool operator==( const always_t&, const possibly_t<I>&) { return false; } - friend ASIO_CONSTEXPR bool operator!=( + friend constexpr bool operator!=( const always_t&, const possibly_t<I>&) { return true; } - friend ASIO_CONSTEXPR bool operator==( + friend constexpr bool operator==( const always_t&, const never_t<I>&) { return false; } - friend ASIO_CONSTEXPR bool operator!=( + friend constexpr bool operator!=( const always_t&, const never_t<I>&) { return true; @@ -863,15 +781,15 @@ struct always_t template <typename Executor> friend adapter<Executor> require( const Executor& e, const always_t&, - typename enable_if< + enable_if_t< is_executor<Executor>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_require< const Executor&, blocking_adaptation::allowed_t<0> >::is_valid - >::type* = 0) + >* = 0) { return adapter<Executor>(0, e); } @@ -889,26 +807,14 @@ struct never_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; typedef blocking_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR never_t() + constexpr never_t() { } @@ -925,58 +831,51 @@ struct never_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(never_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = never_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR blocking_t<I> value() + static constexpr blocking_t<I> value() { return never_t(); } - friend ASIO_CONSTEXPR bool operator==( - const never_t&, const never_t&) + friend constexpr bool operator==(const never_t&, const never_t&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( - const never_t&, const never_t&) + friend constexpr bool operator!=(const never_t&, const never_t&) { return false; } - friend ASIO_CONSTEXPR bool operator==( - const never_t&, const possibly_t<I>&) + friend constexpr bool operator==(const never_t&, const possibly_t<I>&) { return false; } - friend ASIO_CONSTEXPR bool operator!=( - const never_t&, const possibly_t<I>&) + friend constexpr bool operator!=(const never_t&, const possibly_t<I>&) { return true; } - friend ASIO_CONSTEXPR bool operator==( - const never_t&, const always_t<I>&) + friend constexpr bool operator==(const never_t&, const always_t<I>&) { return false; } - friend ASIO_CONSTEXPR bool operator!=( - const never_t&, const always_t<I>&) + friend constexpr bool operator!=(const never_t&, const always_t<I>&) { return true; } @@ -993,11 +892,7 @@ const T never_t<I>::static_query_v; typedef detail::blocking_t<> blocking_t; -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr blocking_t blocking; -#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -namespace { static const blocking_t& blocking = blocking_t::instance; } -#endif } // namespace execution @@ -1005,69 +900,25 @@ namespace { static const blocking_t& blocking = blocking_t::instance; } template <typename T> struct is_applicable_property<T, execution::blocking_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::blocking_t::possibly_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::blocking_t::always_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::blocking_t::never_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; @@ -1079,42 +930,42 @@ namespace traits { template <typename T> struct query_free_default<T, execution::blocking_t, - typename enable_if< + enable_if_t< can_query<T, execution::blocking_t::possibly_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::blocking_t::possibly_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::blocking_t::possibly_t>::value; typedef execution::blocking_t result_type; }; template <typename T> struct query_free_default<T, execution::blocking_t, - typename enable_if< + enable_if_t< !can_query<T, execution::blocking_t::possibly_t>::value && can_query<T, execution::blocking_t::always_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::blocking_t::always_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::blocking_t::always_t>::value; typedef execution::blocking_t result_type; }; template <typename T> struct query_free_default<T, execution::blocking_t, - typename enable_if< + enable_if_t< !can_query<T, execution::blocking_t::possibly_t>::value && !can_query<T, execution::blocking_t::always_t>::value && can_query<T, execution::blocking_t::never_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::blocking_t::never_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::blocking_t::never_t>::value; typedef execution::blocking_t result_type; }; @@ -1126,18 +977,18 @@ struct query_free_default<T, execution::blocking_t, template <typename T> struct static_query<T, execution::blocking_t, - typename enable_if< + enable_if_t< execution::detail::blocking_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::blocking_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::blocking_t::query_static_constexpr_member<T>::value(); } @@ -1145,21 +996,21 @@ struct static_query<T, execution::blocking_t, template <typename T> struct static_query<T, execution::blocking_t, - typename enable_if< + enable_if_t< !execution::detail::blocking_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::blocking_t<0>:: query_member<T>::is_valid && traits::static_query<T, execution::blocking_t::possibly_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::blocking_t::possibly_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::blocking_t::possibly_t>::value(); } @@ -1167,22 +1018,22 @@ struct static_query<T, execution::blocking_t, template <typename T> struct static_query<T, execution::blocking_t, - typename enable_if< + enable_if_t< !execution::detail::blocking_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::blocking_t<0>:: query_member<T>::is_valid && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid && traits::static_query<T, execution::blocking_t::always_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::blocking_t::always_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::blocking_t::always_t>::value(); } @@ -1190,7 +1041,7 @@ struct static_query<T, execution::blocking_t, template <typename T> struct static_query<T, execution::blocking_t, - typename enable_if< + enable_if_t< !execution::detail::blocking_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::blocking_t<0>:: @@ -1198,15 +1049,15 @@ struct static_query<T, execution::blocking_t, && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid && !traits::static_query<T, execution::blocking_t::always_t>::is_valid && traits::static_query<T, execution::blocking_t::never_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::blocking_t::never_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::blocking_t::never_t>::value(); } @@ -1214,18 +1065,18 @@ struct static_query<T, execution::blocking_t, template <typename T> struct static_query<T, execution::blocking_t::possibly_t, - typename enable_if< + enable_if_t< execution::detail::blocking::possibly_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::blocking::possibly_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::blocking::possibly_t<0>:: query_static_constexpr_member<T>::value(); @@ -1234,7 +1085,7 @@ struct static_query<T, execution::blocking_t::possibly_t, template <typename T> struct static_query<T, execution::blocking_t::possibly_t, - typename enable_if< + enable_if_t< !execution::detail::blocking::possibly_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::blocking::possibly_t<0>:: @@ -1242,14 +1093,14 @@ struct static_query<T, execution::blocking_t::possibly_t, && !traits::query_free<T, execution::blocking_t::possibly_t>::is_valid && !can_query<T, execution::blocking_t::always_t>::value && !can_query<T, execution::blocking_t::never_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::blocking_t::possibly_t result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return result_type(); } @@ -1257,18 +1108,18 @@ struct static_query<T, execution::blocking_t::possibly_t, template <typename T> struct static_query<T, execution::blocking_t::always_t, - typename enable_if< + enable_if_t< execution::detail::blocking::always_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::blocking::always_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::blocking::always_t<0>:: query_static_constexpr_member<T>::value(); @@ -1277,18 +1128,18 @@ struct static_query<T, execution::blocking_t::always_t, template <typename T> struct static_query<T, execution::blocking_t::never_t, - typename enable_if< + enable_if_t< execution::detail::blocking::never_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::blocking::never_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::blocking::never_t<0>:: query_static_constexpr_member<T>::value(); @@ -1298,61 +1149,21 @@ struct static_query<T, execution::blocking_t::never_t, #endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - -template <typename T> -struct static_require<T, execution::blocking_t::possibly_t, - typename enable_if< - static_query<T, execution::blocking_t::possibly_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::blocking_t::possibly_t>::result_type, - execution::blocking_t::possibly_t>::value)); -}; - -template <typename T> -struct static_require<T, execution::blocking_t::always_t, - typename enable_if< - static_query<T, execution::blocking_t::always_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::blocking_t::always_t>::result_type, - execution::blocking_t::always_t>::value)); -}; - -template <typename T> -struct static_require<T, execution::blocking_t::never_t, - typename enable_if< - static_query<T, execution::blocking_t::never_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::blocking_t::never_t>::result_type, - execution::blocking_t::never_t>::value)); -}; - -#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - #if !defined(ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT) template <typename T> struct require_free_default<T, execution::blocking_t::always_t, - typename enable_if< - is_same<T, typename decay<T>::type>::value + enable_if_t< + is_same<T, decay_t<T>>::value && execution::is_executor<T>::value && traits::static_require< const T&, execution::detail::blocking_adaptation::allowed_t<0> >::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef execution::detail::blocking::adapter<T> result_type; }; @@ -1362,10 +1173,10 @@ struct require_free_default<T, execution::blocking_t::always_t, template <typename Executor> struct equality_comparable< - execution::detail::blocking::adapter<Executor> > + execution::detail::blocking::adapter<Executor>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; }; #endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) @@ -1376,8 +1187,8 @@ template <typename Executor, typename Function> struct execute_member< execution::detail::blocking::adapter<Executor>, Function> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef void result_type; }; @@ -1388,13 +1199,13 @@ struct execute_member< template <typename Executor, int I> struct query_static_constexpr_member< execution::detail::blocking::adapter<Executor>, - execution::detail::blocking_t<I> > + execution::detail::blocking_t<I>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::blocking_t::always_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return result_type(); } @@ -1403,13 +1214,13 @@ struct query_static_constexpr_member< template <typename Executor, int I> struct query_static_constexpr_member< execution::detail::blocking::adapter<Executor>, - execution::detail::blocking::always_t<I> > + execution::detail::blocking::always_t<I>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::blocking_t::always_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return result_type(); } @@ -1418,13 +1229,13 @@ struct query_static_constexpr_member< template <typename Executor, int I> struct query_static_constexpr_member< execution::detail::blocking::adapter<Executor>, - execution::detail::blocking::possibly_t<I> > + execution::detail::blocking::possibly_t<I>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::blocking_t::always_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return result_type(); } @@ -1433,13 +1244,13 @@ struct query_static_constexpr_member< template <typename Executor, int I> struct query_static_constexpr_member< execution::detail::blocking::adapter<Executor>, - execution::detail::blocking::never_t<I> > + execution::detail::blocking::never_t<I>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::blocking_t::always_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return result_type(); } @@ -1452,14 +1263,14 @@ struct query_static_constexpr_member< template <typename Executor, typename Property> struct query_member< execution::detail::blocking::adapter<Executor>, Property, - typename enable_if< + enable_if_t< can_query<const Executor&, Property>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<Executor, Property>::value)); - typedef typename query_result<Executor, Property>::type result_type; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<Executor, Property>::value; + typedef query_result_t<Executor, Property> result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) @@ -1470,53 +1281,52 @@ template <typename Executor, int I> struct require_member< execution::detail::blocking::adapter<Executor>, execution::detail::blocking::possibly_t<I>, - typename enable_if< + enable_if_t< can_require< const Executor&, execution::detail::blocking::possibly_t<I> >::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_require<const Executor&, - execution::detail::blocking::possibly_t<I> >::value)); - typedef typename require_result<const Executor&, - execution::detail::blocking::possibly_t<I> >::type result_type; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_require<const Executor&, + execution::detail::blocking::possibly_t<I>>::value; + typedef require_result_t<const Executor&, + execution::detail::blocking::possibly_t<I>> result_type; }; template <typename Executor, int I> struct require_member< execution::detail::blocking::adapter<Executor>, execution::detail::blocking::never_t<I>, - typename enable_if< + enable_if_t< can_require< const Executor&, execution::detail::blocking::never_t<I> >::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_require<const Executor&, - execution::detail::blocking::never_t<I> >::value)); - typedef typename require_result<const Executor&, - execution::detail::blocking::never_t<I> >::type result_type; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_require<const Executor&, + execution::detail::blocking::never_t<I>>::value; + typedef require_result_t<const Executor&, + execution::detail::blocking::never_t<I>> result_type; }; template <typename Executor, typename Property> struct require_member< execution::detail::blocking::adapter<Executor>, Property, - typename enable_if< + enable_if_t< can_require<const Executor&, Property>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_require<Executor, Property>::value)); - typedef execution::detail::blocking::adapter<typename decay< - typename require_result<Executor, Property>::type - >::type> result_type; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_require<Executor, Property>::value; + typedef execution::detail::blocking::adapter< + decay_t<require_result_t<Executor, Property>>> result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) @@ -1526,16 +1336,15 @@ struct require_member< template <typename Executor, typename Property> struct prefer_member< execution::detail::blocking::adapter<Executor>, Property, - typename enable_if< + enable_if_t< can_prefer<const Executor&, Property>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_prefer<Executor, Property>::value)); - typedef execution::detail::blocking::adapter<typename decay< - typename prefer_result<Executor, Property>::type - >::type> result_type; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_prefer<Executor, Property>::value; + typedef execution::detail::blocking::adapter< + decay_t<prefer_result_t<Executor, Property>>> result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) diff --git a/3rdparty/asio/include/asio/execution/blocking_adaptation.hpp b/3rdparty/asio/include/asio/execution/blocking_adaptation.hpp index 2a3fe908df9..a2769b254a5 100644 --- a/3rdparty/asio/include/asio/execution/blocking_adaptation.hpp +++ b/3rdparty/asio/include/asio/execution/blocking_adaptation.hpp @@ -2,7 +2,7 @@ // execution/blocking_adaptation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,10 +19,7 @@ #include "asio/detail/event.hpp" #include "asio/detail/mutex.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/execution/execute.hpp" #include "asio/execution/executor.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" #include "asio/is_applicable_property.hpp" #include "asio/prefer.hpp" #include "asio/query.hpp" @@ -47,11 +44,9 @@ namespace execution { /// allowed in order to apply the blocking_adaptation_t::allowed_t property. struct blocking_adaptation_t { - /// The blocking_adaptation_t property applies to executors, senders, and - /// schedulers. + /// The blocking_adaptation_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The top-level blocking_adaptation_t property cannot be required. static constexpr bool is_requirable = false; @@ -65,11 +60,9 @@ struct blocking_adaptation_t /// A sub-property that indicates that automatic adaptation is not allowed. struct disallowed_t { - /// The blocking_adaptation_t::disallowed_t property applies to executors, - /// senders, and schedulers. + /// The blocking_adaptation_t::disallowed_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The blocking_adaptation_t::disallowed_t property can be required. static constexpr bool is_requirable = true; @@ -93,11 +86,9 @@ struct blocking_adaptation_t /// A sub-property that indicates that automatic adaptation is allowed. struct allowed_t { - /// The blocking_adaptation_t::allowed_t property applies to executors, - /// senders, and schedulers. + /// The blocking_adaptation_t::allowed_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The blocking_adaptation_t::allowed_t property can be required. static constexpr bool is_requirable = true; @@ -165,39 +156,27 @@ struct blocking_adaptation_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); + static constexpr bool is_requirable = false; + static constexpr bool is_preferable = false; typedef blocking_adaptation_t polymorphic_query_result_type; typedef detail::blocking_adaptation::disallowed_t<I> disallowed_t; typedef detail::blocking_adaptation::allowed_t<I> allowed_t; - ASIO_CONSTEXPR blocking_adaptation_t() + constexpr blocking_adaptation_t() : value_(-1) { } - ASIO_CONSTEXPR blocking_adaptation_t(disallowed_t) + constexpr blocking_adaptation_t(disallowed_t) : value_(0) { } - ASIO_CONSTEXPR blocking_adaptation_t(allowed_t) + constexpr blocking_adaptation_t(allowed_t) : value_(1) { } @@ -209,16 +188,14 @@ struct blocking_adaptation_t struct type { template <typename P> - auto query(ASIO_MOVE_ARG(P) p) const + auto query(P&& p) const noexcept( noexcept( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ) ) -> decltype( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ); }; #else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) @@ -233,17 +210,17 @@ struct blocking_adaptation_t struct type { template <typename P> - static constexpr auto query(ASIO_MOVE_ARG(P) p) + static constexpr auto query(P&& p) noexcept( noexcept( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) ) -> decltype( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) { - return T::query(ASIO_MOVE_CAST(P)(p)); + return T::query(static_cast<P&&>(p)); } }; #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) @@ -263,66 +240,64 @@ struct blocking_adaptation_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, disallowed_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, disallowed_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, disallowed_t>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, allowed_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::static_query<T, disallowed_t>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, allowed_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, allowed_t>::value(); } template <typename E, typename T = decltype(blocking_adaptation_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = blocking_adaptation_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - friend ASIO_CONSTEXPR bool operator==( + friend constexpr bool operator==( const blocking_adaptation_t& a, const blocking_adaptation_t& b) { return a.value_ == b.value_; } - friend ASIO_CONSTEXPR bool operator!=( + friend constexpr bool operator!=( const blocking_adaptation_t& a, const blocking_adaptation_t& b) { return a.value_ != b.value_; @@ -330,26 +305,24 @@ struct blocking_adaptation_t struct convertible_from_blocking_adaptation_t { - ASIO_CONSTEXPR convertible_from_blocking_adaptation_t( + constexpr convertible_from_blocking_adaptation_t( blocking_adaptation_t) { } }; template <typename Executor> - friend ASIO_CONSTEXPR blocking_adaptation_t query( + friend constexpr blocking_adaptation_t query( const Executor& ex, convertible_from_blocking_adaptation_t, - typename enable_if< + enable_if_t< can_query<const Executor&, disallowed_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, - blocking_adaptation_t<>::disallowed_t>::value)) + noexcept(is_nothrow_query<const Executor&, + blocking_adaptation_t<>::disallowed_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, disallowed_t>::value)) + noexcept(is_nothrow_query<const Executor&, disallowed_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -357,22 +330,20 @@ struct blocking_adaptation_t } template <typename Executor> - friend ASIO_CONSTEXPR blocking_adaptation_t query( + friend constexpr blocking_adaptation_t query( const Executor& ex, convertible_from_blocking_adaptation_t, - typename enable_if< + enable_if_t< !can_query<const Executor&, disallowed_t>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< can_query<const Executor&, allowed_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, - blocking_adaptation_t<>::allowed_t>::value)) + noexcept(is_nothrow_query<const Executor&, + blocking_adaptation_t<>::allowed_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, allowed_t>::value)) + noexcept(is_nothrow_query<const Executor&, allowed_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -382,10 +353,6 @@ struct blocking_adaptation_t ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(disallowed_t, disallowed); ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(allowed_t, allowed); -#if !defined(ASIO_HAS_CONSTEXPR) - static const blocking_adaptation_t instance; -#endif // !defined(ASIO_HAS_CONSTEXPR) - private: int value_; }; @@ -397,11 +364,6 @@ const T blocking_adaptation_t<I>::static_query_v; #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_CONSTEXPR) -template <int I> -const blocking_adaptation_t<I> blocking_adaptation_t<I>::instance; -#endif - template <int I> const typename blocking_adaptation_t<I>::disallowed_t blocking_adaptation_t<I>::disallowed; @@ -417,26 +379,14 @@ struct disallowed_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; typedef blocking_adaptation_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR disallowed_t() + constexpr disallowed_t() { } @@ -455,55 +405,62 @@ struct disallowed_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename T> - static ASIO_CONSTEXPR disallowed_t static_query( - typename enable_if< + static constexpr disallowed_t static_query( + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::query_free<T, disallowed_t>::is_valid - >::type* = 0, - typename enable_if< - !can_query<T, allowed_t<I> >::value - >::type* = 0) ASIO_NOEXCEPT + >* = 0, + enable_if_t< + !can_query<T, allowed_t<I>>::value + >* = 0) noexcept { return disallowed_t(); } template <typename E, typename T = decltype(disallowed_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = disallowed_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR blocking_adaptation_t<I> value() + static constexpr blocking_adaptation_t<I> value() { return disallowed_t(); } - friend ASIO_CONSTEXPR bool operator==( - const disallowed_t&, const disallowed_t&) + friend constexpr bool operator==(const disallowed_t&, const disallowed_t&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( - const disallowed_t&, const disallowed_t&) + friend constexpr bool operator!=(const disallowed_t&, const disallowed_t&) + { + return false; + } + + friend constexpr bool operator==(const disallowed_t&, const allowed_t<I>&) { return false; } + + friend constexpr bool operator!=(const disallowed_t&, const allowed_t<I>&) + { + return true; + } }; #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ @@ -517,105 +474,91 @@ template <typename Executor> class adapter { public: - adapter(int, const Executor& e) ASIO_NOEXCEPT + adapter(int, const Executor& e) noexcept : executor_(e) { } - adapter(const adapter& other) ASIO_NOEXCEPT + adapter(const adapter& other) noexcept : executor_(other.executor_) { } -#if defined(ASIO_HAS_MOVE) - adapter(adapter&& other) ASIO_NOEXCEPT - : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)) + adapter(adapter&& other) noexcept + : executor_(static_cast<Executor&&>(other.executor_)) { } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) template <int I> - static ASIO_CONSTEXPR allowed_t<I> query( - blocking_adaptation_t<I>) ASIO_NOEXCEPT + static constexpr allowed_t<I> query(blocking_adaptation_t<I>) noexcept { return allowed_t<I>(); } template <int I> - static ASIO_CONSTEXPR allowed_t<I> query( - allowed_t<I>) ASIO_NOEXCEPT + static constexpr allowed_t<I> query(allowed_t<I>) noexcept { return allowed_t<I>(); } template <int I> - static ASIO_CONSTEXPR allowed_t<I> query( - disallowed_t<I>) ASIO_NOEXCEPT + static constexpr allowed_t<I> query(disallowed_t<I>) noexcept { return allowed_t<I>(); } template <typename Property> - typename enable_if< + enable_if_t< can_query<const Executor&, Property>::value, - typename query_result<const Executor&, Property>::type - >::type query(const Property& p) const - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, Property>::value)) + query_result_t<const Executor&, Property> + > query(const Property& p) const + noexcept(is_nothrow_query<const Executor&, Property>::value) { return asio::query(executor_, p); } template <int I> - Executor require(disallowed_t<I>) const ASIO_NOEXCEPT + Executor require(disallowed_t<I>) const noexcept { return executor_; } template <typename Property> - typename enable_if< + enable_if_t< can_require<const Executor&, Property>::value, - adapter<typename decay< - typename require_result<const Executor&, Property>::type - >::type> - >::type require(const Property& p) const - ASIO_NOEXCEPT_IF(( - is_nothrow_require<const Executor&, Property>::value)) + adapter<decay_t<require_result_t<const Executor&, Property>>> + > require(const Property& p) const + noexcept(is_nothrow_require<const Executor&, Property>::value) { - return adapter<typename decay< - typename require_result<const Executor&, Property>::type - >::type>(0, asio::require(executor_, p)); + return adapter<decay_t<require_result_t<const Executor&, Property>>>( + 0, asio::require(executor_, p)); } template <typename Property> - typename enable_if< + enable_if_t< can_prefer<const Executor&, Property>::value, - adapter<typename decay< - typename prefer_result<const Executor&, Property>::type - >::type> - >::type prefer(const Property& p) const - ASIO_NOEXCEPT_IF(( - is_nothrow_prefer<const Executor&, Property>::value)) + adapter<decay_t<prefer_result_t<const Executor&, Property>>> + > prefer(const Property& p) const + noexcept(is_nothrow_prefer<const Executor&, Property>::value) { - return adapter<typename decay< - typename prefer_result<const Executor&, Property>::type - >::type>(0, asio::prefer(executor_, p)); + return adapter<decay_t<prefer_result_t<const Executor&, Property>>>( + 0, asio::prefer(executor_, p)); } template <typename Function> - typename enable_if< - execution::can_execute<const Executor&, Function>::value - >::type execute(ASIO_MOVE_ARG(Function) f) const + enable_if_t< + traits::execute_member<const Executor&, Function>::is_valid + > execute(Function&& f) const { - execution::execute(executor_, ASIO_MOVE_CAST(Function)(f)); + executor_.execute(static_cast<Function&&>(f)); } - friend bool operator==(const adapter& a, const adapter& b) ASIO_NOEXCEPT + friend bool operator==(const adapter& a, const adapter& b) noexcept { return a.executor_ == b.executor_; } - friend bool operator!=(const adapter& a, const adapter& b) ASIO_NOEXCEPT + friend bool operator!=(const adapter& a, const adapter& b) noexcept { return a.executor_ != b.executor_; } @@ -629,26 +572,14 @@ struct allowed_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = false; typedef blocking_adaptation_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR allowed_t() + constexpr allowed_t() { } @@ -667,44 +598,49 @@ struct allowed_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(allowed_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = allowed_t::static_query<E>(); + static constexpr const T static_query_v = allowed_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR blocking_adaptation_t<I> value() + static constexpr blocking_adaptation_t<I> value() { return allowed_t(); } - friend ASIO_CONSTEXPR bool operator==( - const allowed_t&, const allowed_t&) + friend constexpr bool operator==(const allowed_t&, const allowed_t&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( - const allowed_t&, const allowed_t&) + friend constexpr bool operator!=(const allowed_t&, const allowed_t&) { return false; } + friend constexpr bool operator==(const allowed_t&, const disallowed_t<I>&) + { + return false; + } + + friend constexpr bool operator!=(const allowed_t&, const disallowed_t<I>&) + { + return true; + } + template <typename Executor> friend adapter<Executor> require( const Executor& e, const allowed_t&, - typename enable_if< + enable_if_t< is_executor<Executor>::value - >::type* = 0) + >* = 0) { return adapter<Executor>(0, e); } @@ -722,17 +658,17 @@ class blocking_execute_state { public: template <typename F> - blocking_execute_state(ASIO_MOVE_ARG(F) f) - : func_(ASIO_MOVE_CAST(F)(f)), + blocking_execute_state(F&& f) + : func_(static_cast<F&&>(f)), is_complete_(false) { } template <typename Executor> - void execute_and_wait(ASIO_MOVE_ARG(Executor) ex) + void execute_and_wait(Executor&& ex) { handler h = { this }; - execution::execute(ASIO_MOVE_CAST(Executor)(ex), h); + ex.execute(h); asio::detail::mutex::scoped_lock lock(mutex_); while (!is_complete_) event_.wait(lock); @@ -769,11 +705,11 @@ public: template <typename Executor, typename Function> void blocking_execute( - ASIO_MOVE_ARG(Executor) ex, - ASIO_MOVE_ARG(Function) func) + Executor&& ex, + Function&& func) { - typedef typename decay<Function>::type func_t; - blocking_execute_state<func_t> state(ASIO_MOVE_CAST(Function)(func)); + typedef decay_t<Function> func_t; + blocking_execute_state<func_t> state(static_cast<Function&&>(func)); state.execute_and_wait(ex); } @@ -782,12 +718,7 @@ void blocking_execute( typedef detail::blocking_adaptation_t<> blocking_adaptation_t; -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr blocking_adaptation_t blocking_adaptation; -#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -namespace { static const blocking_adaptation_t& - blocking_adaptation = blocking_adaptation_t::instance; } -#endif } // namespace execution @@ -795,52 +726,19 @@ namespace { static const blocking_adaptation_t& template <typename T> struct is_applicable_property<T, execution::blocking_adaptation_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::blocking_adaptation_t::disallowed_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::blocking_adaptation_t::allowed_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; @@ -852,27 +750,27 @@ namespace traits { template <typename T> struct query_free_default<T, execution::blocking_adaptation_t, - typename enable_if< + enable_if_t< can_query<T, execution::blocking_adaptation_t::disallowed_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = (is_nothrow_query<T, - execution::blocking_adaptation_t::disallowed_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::blocking_adaptation_t::disallowed_t>::value; typedef execution::blocking_adaptation_t result_type; }; template <typename T> struct query_free_default<T, execution::blocking_adaptation_t, - typename enable_if< + enable_if_t< !can_query<T, execution::blocking_adaptation_t::disallowed_t>::value && can_query<T, execution::blocking_adaptation_t::allowed_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::blocking_adaptation_t::allowed_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::blocking_adaptation_t::allowed_t>::value; typedef execution::blocking_adaptation_t result_type; }; @@ -884,18 +782,18 @@ struct query_free_default<T, execution::blocking_adaptation_t, template <typename T> struct static_query<T, execution::blocking_adaptation_t, - typename enable_if< + enable_if_t< execution::detail::blocking_adaptation_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::blocking_adaptation_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::blocking_adaptation_t<0>:: query_static_constexpr_member<T>::value(); @@ -904,22 +802,22 @@ struct static_query<T, execution::blocking_adaptation_t, template <typename T> struct static_query<T, execution::blocking_adaptation_t, - typename enable_if< + enable_if_t< !execution::detail::blocking_adaptation_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::blocking_adaptation_t<0>:: query_member<T>::is_valid && traits::static_query<T, execution::blocking_adaptation_t::disallowed_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::blocking_adaptation_t::disallowed_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::blocking_adaptation_t::disallowed_t>::value(); @@ -928,7 +826,7 @@ struct static_query<T, execution::blocking_adaptation_t, template <typename T> struct static_query<T, execution::blocking_adaptation_t, - typename enable_if< + enable_if_t< !execution::detail::blocking_adaptation_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::blocking_adaptation_t<0>:: @@ -937,15 +835,15 @@ struct static_query<T, execution::blocking_adaptation_t, execution::blocking_adaptation_t::disallowed_t>::is_valid && traits::static_query<T, execution::blocking_adaptation_t::allowed_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::blocking_adaptation_t::allowed_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::blocking_adaptation_t::allowed_t>::value(); @@ -954,18 +852,18 @@ struct static_query<T, execution::blocking_adaptation_t, template <typename T> struct static_query<T, execution::blocking_adaptation_t::disallowed_t, - typename enable_if< + enable_if_t< execution::detail::blocking_adaptation::disallowed_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::blocking_adaptation::disallowed_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::blocking_adaptation::disallowed_t<0>:: query_static_constexpr_member<T>::value(); @@ -974,7 +872,7 @@ struct static_query<T, execution::blocking_adaptation_t::disallowed_t, template <typename T> struct static_query<T, execution::blocking_adaptation_t::disallowed_t, - typename enable_if< + enable_if_t< !execution::detail::blocking_adaptation::disallowed_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::blocking_adaptation::disallowed_t<0>:: @@ -982,14 +880,14 @@ struct static_query<T, execution::blocking_adaptation_t::disallowed_t, && !traits::query_free<T, execution::blocking_adaptation_t::disallowed_t>::is_valid && !can_query<T, execution::blocking_adaptation_t::allowed_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::blocking_adaptation_t::disallowed_t result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return result_type(); } @@ -997,18 +895,18 @@ struct static_query<T, execution::blocking_adaptation_t::disallowed_t, template <typename T> struct static_query<T, execution::blocking_adaptation_t::allowed_t, - typename enable_if< + enable_if_t< execution::detail::blocking_adaptation::allowed_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::blocking_adaptation::allowed_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::blocking_adaptation::allowed_t<0>:: query_static_constexpr_member<T>::value(); @@ -1018,45 +916,17 @@ struct static_query<T, execution::blocking_adaptation_t::allowed_t, #endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - -template <typename T> -struct static_require<T, execution::blocking_adaptation_t::disallowed_t, - typename enable_if< - static_query<T, execution::blocking_adaptation_t::disallowed_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::blocking_adaptation_t::disallowed_t>::result_type, - execution::blocking_adaptation_t::disallowed_t>::value)); -}; - -template <typename T> -struct static_require<T, execution::blocking_adaptation_t::allowed_t, - typename enable_if< - static_query<T, execution::blocking_adaptation_t::allowed_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::blocking_adaptation_t::allowed_t>::result_type, - execution::blocking_adaptation_t::allowed_t>::value)); -}; - -#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - #if !defined(ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT) template <typename T> struct require_free_default<T, execution::blocking_adaptation_t::allowed_t, - typename enable_if< - is_same<T, typename decay<T>::type>::value + enable_if_t< + is_same<T, decay_t<T>>::value && execution::is_executor<T>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef execution::detail::blocking_adaptation::adapter<T> result_type; }; @@ -1066,10 +936,10 @@ struct require_free_default<T, execution::blocking_adaptation_t::allowed_t, template <typename Executor> struct equality_comparable< - execution::detail::blocking_adaptation::adapter<Executor> > + execution::detail::blocking_adaptation::adapter<Executor>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; }; #endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) @@ -1080,8 +950,8 @@ template <typename Executor, typename Function> struct execute_member< execution::detail::blocking_adaptation::adapter<Executor>, Function> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef void result_type; }; @@ -1092,13 +962,13 @@ struct execute_member< template <typename Executor, int I> struct query_static_constexpr_member< execution::detail::blocking_adaptation::adapter<Executor>, - execution::detail::blocking_adaptation_t<I> > + execution::detail::blocking_adaptation_t<I>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::blocking_adaptation_t::allowed_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return result_type(); } @@ -1107,13 +977,13 @@ struct query_static_constexpr_member< template <typename Executor, int I> struct query_static_constexpr_member< execution::detail::blocking_adaptation::adapter<Executor>, - execution::detail::blocking_adaptation::allowed_t<I> > + execution::detail::blocking_adaptation::allowed_t<I>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::blocking_adaptation_t::allowed_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return result_type(); } @@ -1122,13 +992,13 @@ struct query_static_constexpr_member< template <typename Executor, int I> struct query_static_constexpr_member< execution::detail::blocking_adaptation::adapter<Executor>, - execution::detail::blocking_adaptation::disallowed_t<I> > + execution::detail::blocking_adaptation::disallowed_t<I>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::blocking_adaptation_t::allowed_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return result_type(); } @@ -1141,14 +1011,14 @@ struct query_static_constexpr_member< template <typename Executor, typename Property> struct query_member< execution::detail::blocking_adaptation::adapter<Executor>, Property, - typename enable_if< + enable_if_t< can_query<const Executor&, Property>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<Executor, Property>::value)); - typedef typename query_result<Executor, Property>::type result_type; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<Executor, Property>::value; + typedef query_result_t<Executor, Property> result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) @@ -1158,26 +1028,25 @@ struct query_member< template <typename Executor, int I> struct require_member< execution::detail::blocking_adaptation::adapter<Executor>, - execution::detail::blocking_adaptation::disallowed_t<I> > + execution::detail::blocking_adaptation::disallowed_t<I>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef Executor result_type; }; template <typename Executor, typename Property> struct require_member< execution::detail::blocking_adaptation::adapter<Executor>, Property, - typename enable_if< + enable_if_t< can_require<const Executor&, Property>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_require<Executor, Property>::value)); - typedef execution::detail::blocking_adaptation::adapter<typename decay< - typename require_result<Executor, Property>::type - >::type> result_type; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_require<Executor, Property>::value; + typedef execution::detail::blocking_adaptation::adapter< + decay_t<require_result_t<Executor, Property>>> result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) @@ -1187,16 +1056,15 @@ struct require_member< template <typename Executor, typename Property> struct prefer_member< execution::detail::blocking_adaptation::adapter<Executor>, Property, - typename enable_if< + enable_if_t< can_prefer<const Executor&, Property>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_prefer<Executor, Property>::value)); - typedef execution::detail::blocking_adaptation::adapter<typename decay< - typename prefer_result<Executor, Property>::type - >::type> result_type; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_prefer<Executor, Property>::value; + typedef execution::detail::blocking_adaptation::adapter< + decay_t<prefer_result_t<Executor, Property>>> result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) diff --git a/3rdparty/asio/include/asio/execution/bulk_execute.hpp b/3rdparty/asio/include/asio/execution/bulk_execute.hpp deleted file mode 100644 index 2bc13c954c0..00000000000 --- a/3rdparty/asio/include/asio/execution/bulk_execute.hpp +++ /dev/null @@ -1,397 +0,0 @@ -// -// execution/bulk_execute.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_BULK_EXECUTE_HPP -#define ASIO_EXECUTION_BULK_EXECUTE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/bulk_guarantee.hpp" -#include "asio/execution/detail/bulk_sender.hpp" -#include "asio/execution/executor.hpp" -#include "asio/execution/sender.hpp" -#include "asio/traits/bulk_execute_member.hpp" -#include "asio/traits/bulk_execute_free.hpp" - -#include "asio/detail/push_options.hpp" - -#if defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace execution { - -/// A customisation point that creates a bulk sender. -/** - * The name <tt>execution::bulk_execute</tt> denotes a customisation point - * object. If <tt>is_convertible_v<N, size_t></tt> is true, then the expression - * <tt>execution::bulk_execute(S, F, N)</tt> for some subexpressions - * <tt>S</tt>, <tt>F</tt>, and <tt>N</tt> is expression-equivalent to: - * - * @li <tt>S.bulk_execute(F, N)</tt>, if that expression is valid. If the - * function selected does not execute <tt>N</tt> invocations of the function - * object <tt>F</tt> on the executor <tt>S</tt> in bulk with forward progress - * guarantee <tt>asio::query(S, execution::bulk_guarantee)</tt>, and - * the result of that function does not model <tt>sender<void></tt>, the - * program is ill-formed with no diagnostic required. - * - * @li Otherwise, <tt>bulk_execute(S, F, N)</tt>, if that expression is valid, - * with overload resolution performed in a context that includes the - * declaration <tt>void bulk_execute();</tt> and that does not include a - * declaration of <tt>execution::bulk_execute</tt>. If the function selected - * by overload resolution does not execute <tt>N</tt> invocations of the - * function object <tt>F</tt> on the executor <tt>S</tt> in bulk with forward - * progress guarantee <tt>asio::query(E, - * execution::bulk_guarantee)</tt>, and the result of that function does not - * model <tt>sender<void></tt>, the program is ill-formed with no diagnostic - * required. - * - * @li Otherwise, if the types <tt>F</tt> and - * <tt>executor_index_t<remove_cvref_t<S>></tt> model <tt>invocable</tt> and - * if <tt>asio::query(S, execution::bulk_guarantee)</tt> equals - * <tt>execution::bulk_guarantee.unsequenced</tt>, then - * - * - Evaluates <tt>DECAY_COPY(std::forward<decltype(F)>(F))</tt> on the - * calling thread to create a function object <tt>cf</tt>. [Note: - * Additional copies of <tt>cf</tt> may subsequently be created. --end - * note.] - * - * - For each value of <tt>i</tt> in <tt>N</tt>, <tt>cf(i)</tt> (or copy of - * <tt>cf</tt>)) will be invoked at most once by an execution agent that is - * unique for each value of <tt>i</tt>. - * - * - May block pending completion of one or more invocations of <tt>cf</tt>. - * - * - Synchronizes with (C++Std [intro.multithread]) the invocations of - * <tt>cf</tt>. - * - * @li Otherwise, <tt>execution::bulk_execute(S, F, N)</tt> is ill-formed. - */ -inline constexpr unspecified bulk_execute = unspecified; - -/// A type trait that determines whether a @c bulk_execute expression is -/// well-formed. -/** - * Class template @c can_bulk_execute is a trait that is derived from @c - * true_type if the expression <tt>execution::bulk_execute(std::declval<S>(), - * std::declval<F>(), std::declval<N>)</tt> is well formed; otherwise @c - * false_type. - */ -template <typename S, typename F, typename N> -struct can_bulk_execute : - integral_constant<bool, automatically_determined> -{ -}; - -} // namespace execution -} // namespace asio - -#else // defined(GENERATING_DOCUMENTATION) - -namespace asio_execution_bulk_execute_fn { - -using asio::declval; -using asio::enable_if; -using asio::execution::bulk_guarantee_t; -using asio::execution::detail::bulk_sender; -using asio::execution::executor_index; -using asio::execution::is_sender; -using asio::is_convertible; -using asio::is_same; -using asio::remove_cvref; -using asio::result_of; -using asio::traits::bulk_execute_free; -using asio::traits::bulk_execute_member; -using asio::traits::static_require; - -void bulk_execute(); - -enum overload_type -{ - call_member, - call_free, - adapter, - ill_formed -}; - -template <typename S, typename Args, typename = void, typename = void, - typename = void, typename = void, typename = void, typename = void> -struct call_traits -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef void result_type; -}; - -template <typename S, typename F, typename N> -struct call_traits<S, void(F, N), - typename enable_if< - is_convertible<N, std::size_t>::value - >::type, - typename enable_if< - bulk_execute_member<S, F, N>::is_valid - >::type, - typename enable_if< - is_sender< - typename bulk_execute_member<S, F, N>::result_type - >::value - >::type> : - bulk_execute_member<S, F, N> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); -}; - -template <typename S, typename F, typename N> -struct call_traits<S, void(F, N), - typename enable_if< - is_convertible<N, std::size_t>::value - >::type, - typename enable_if< - !bulk_execute_member<S, F, N>::is_valid - >::type, - typename enable_if< - bulk_execute_free<S, F, N>::is_valid - >::type, - typename enable_if< - is_sender< - typename bulk_execute_free<S, F, N>::result_type - >::value - >::type> : - bulk_execute_free<S, F, N> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); -}; - -template <typename S, typename F, typename N> -struct call_traits<S, void(F, N), - typename enable_if< - is_convertible<N, std::size_t>::value - >::type, - typename enable_if< - !bulk_execute_member<S, F, N>::is_valid - >::type, - typename enable_if< - !bulk_execute_free<S, F, N>::is_valid - >::type, - typename enable_if< - is_sender<S>::value - >::type, - typename enable_if< - is_same< - typename result_of< - F(typename executor_index<typename remove_cvref<S>::type>::type) - >::type, - typename result_of< - F(typename executor_index<typename remove_cvref<S>::type>::type) - >::type - >::value - >::type, - typename enable_if< - static_require<S, bulk_guarantee_t::unsequenced_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef bulk_sender<S, F, N> result_type; -}; - -struct impl -{ -#if defined(ASIO_HAS_MOVE) - template <typename S, typename F, typename N> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(F, N)>::overload == call_member, - typename call_traits<S, void(F, N)>::result_type - >::type - operator()(S&& s, F&& f, N&& n) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(F, N)>::is_noexcept)) - { - return ASIO_MOVE_CAST(S)(s).bulk_execute( - ASIO_MOVE_CAST(F)(f), ASIO_MOVE_CAST(N)(n)); - } - - template <typename S, typename F, typename N> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(F, N)>::overload == call_free, - typename call_traits<S, void(F, N)>::result_type - >::type - operator()(S&& s, F&& f, N&& n) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(F, N)>::is_noexcept)) - { - return bulk_execute(ASIO_MOVE_CAST(S)(s), - ASIO_MOVE_CAST(F)(f), ASIO_MOVE_CAST(N)(n)); - } - - template <typename S, typename F, typename N> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(F, N)>::overload == adapter, - typename call_traits<S, void(F, N)>::result_type - >::type - operator()(S&& s, F&& f, N&& n) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(F, N)>::is_noexcept)) - { - return typename call_traits<S, void(F, N)>::result_type( - ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(F)(f), - ASIO_MOVE_CAST(N)(n)); - } -#else // defined(ASIO_HAS_MOVE) - template <typename S, typename F, typename N> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(const F&, const N&)>::overload == call_member, - typename call_traits<S, void(const F&, const N&)>::result_type - >::type - operator()(S& s, const F& f, const N& n) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(const F&, const N&)>::is_noexcept)) - { - return s.bulk_execute(ASIO_MOVE_CAST(F)(f), - ASIO_MOVE_CAST(N)(n)); - } - - template <typename S, typename F, typename N> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(const F&, const N&)>::overload == call_member, - typename call_traits<S, void(const F&, const N&)>::result_type - >::type - operator()(const S& s, const F& f, const N& n) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(const F&, const N&)>::is_noexcept)) - { - return s.bulk_execute(ASIO_MOVE_CAST(F)(f), - ASIO_MOVE_CAST(N)(n)); - } - - template <typename S, typename F, typename N> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(const F&, const N&)>::overload == call_free, - typename call_traits<S, void(const F&, const N&)>::result_type - >::type - operator()(S& s, const F& f, const N& n) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(const F&, const N&)>::is_noexcept)) - { - return bulk_execute(s, ASIO_MOVE_CAST(F)(f), - ASIO_MOVE_CAST(N)(n)); - } - - template <typename S, typename F, typename N> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(const F&, const N&)>::overload == call_free, - typename call_traits<S, void(const F&, const N&)>::result_type - >::type - operator()(const S& s, const F& f, const N& n) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(const F&, const N&)>::is_noexcept)) - { - return bulk_execute(s, ASIO_MOVE_CAST(F)(f), - ASIO_MOVE_CAST(N)(n)); - } - - template <typename S, typename F, typename N> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(const F&, const N&)>::overload == adapter, - typename call_traits<S, void(const F&, const N&)>::result_type - >::type - operator()(S& s, const F& f, const N& n) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(const F&, const N&)>::is_noexcept)) - { - return typename call_traits<S, void(const F&, const N&)>::result_type( - s, ASIO_MOVE_CAST(F)(f), ASIO_MOVE_CAST(N)(n)); - } - - template <typename S, typename F, typename N> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(const F&, const N&)>::overload == adapter, - typename call_traits<S, void(const F&, const N&)>::result_type - >::type - operator()(const S& s, const F& f, const N& n) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(const F&, const N&)>::is_noexcept)) - { - return typename call_traits<S, void(const F&, const N&)>::result_type( - s, ASIO_MOVE_CAST(F)(f), ASIO_MOVE_CAST(N)(n)); - } -#endif // defined(ASIO_HAS_MOVE) -}; - -template <typename T = impl> -struct static_instance -{ - static const T instance; -}; - -template <typename T> -const T static_instance<T>::instance = {}; - -} // namespace asio_execution_bulk_execute_fn -namespace asio { -namespace execution { -namespace { - -static ASIO_CONSTEXPR - const asio_execution_bulk_execute_fn::impl& bulk_execute = - asio_execution_bulk_execute_fn::static_instance<>::instance; - -} // namespace - -template <typename S, typename F, typename N> -struct can_bulk_execute : - integral_constant<bool, - asio_execution_bulk_execute_fn::call_traits< - S, void(F, N)>::overload != - asio_execution_bulk_execute_fn::ill_formed> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename F, typename N> -constexpr bool can_bulk_execute_v = can_bulk_execute<S, F, N>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename F, typename N> -struct is_nothrow_bulk_execute : - integral_constant<bool, - asio_execution_bulk_execute_fn::call_traits< - S, void(F, N)>::is_noexcept> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename F, typename N> -constexpr bool is_nothrow_bulk_execute_v - = is_nothrow_bulk_execute<S, F, N>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename F, typename N> -struct bulk_execute_result -{ - typedef typename asio_execution_bulk_execute_fn::call_traits< - S, void(F, N)>::result_type type; -}; - -} // namespace execution -} // namespace asio - -#endif // defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_BULK_EXECUTE_HPP diff --git a/3rdparty/asio/include/asio/execution/bulk_guarantee.hpp b/3rdparty/asio/include/asio/execution/bulk_guarantee.hpp deleted file mode 100644 index 6482218357d..00000000000 --- a/3rdparty/asio/include/asio/execution/bulk_guarantee.hpp +++ /dev/null @@ -1,1215 +0,0 @@ -// -// execution/bulk_guarantee.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_BULK_GUARANTEE_HPP -#define ASIO_EXECUTION_BULK_GUARANTEE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/executor.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" -#include "asio/is_applicable_property.hpp" -#include "asio/query.hpp" -#include "asio/traits/query_free.hpp" -#include "asio/traits/query_member.hpp" -#include "asio/traits/query_static_constexpr_member.hpp" -#include "asio/traits/static_query.hpp" -#include "asio/traits/static_require.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { - -#if defined(GENERATING_DOCUMENTATION) - -namespace execution { - -/// A property to communicate the forward progress and ordering guarantees of -/// execution agents associated with the bulk execution. -struct bulk_guarantee_t -{ - /// The bulk_guarantee_t property applies to executors, senders, and - /// schedulers. - template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; - - /// The top-level bulk_guarantee_t property cannot be required. - static constexpr bool is_requirable = false; - - /// The top-level bulk_guarantee_t property cannot be preferred. - static constexpr bool is_preferable = false; - - /// The type returned by queries against an @c any_executor. - typedef bulk_guarantee_t polymorphic_query_result_type; - - /// A sub-property that indicates that execution agents within the same bulk - /// execution may be parallelised and vectorised. - struct unsequenced_t - { - /// The bulk_guarantee_t::unsequenced_t property applies to executors, - /// senders, and schedulers. - template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; - - /// The bulk_guarantee_t::unsequenced_t property can be required. - static constexpr bool is_requirable = true; - - /// The bulk_guarantee_t::unsequenced_t property can be preferred. - static constexpr bool is_preferable = true; - - /// The type returned by queries against an @c any_executor. - typedef bulk_guarantee_t polymorphic_query_result_type; - - /// Default constructor. - constexpr unsequenced_t(); - - /// Get the value associated with a property object. - /** - * @returns unsequenced_t(); - */ - static constexpr bulk_guarantee_t value(); - }; - - /// A sub-property that indicates that execution agents within the same bulk - /// execution may not be parallelised and vectorised. - struct sequenced_t - { - /// The bulk_guarantee_t::sequenced_t property applies to executors, - /// senders, and schedulers. - template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; - - /// The bulk_guarantee_t::sequenced_t property can be required. - static constexpr bool is_requirable = true; - - /// The bulk_guarantee_t::sequenced_t property can be preferred. - static constexpr bool is_preferable = true; - - /// The type returned by queries against an @c any_executor. - typedef bulk_guarantee_t polymorphic_query_result_type; - - /// Default constructor. - constexpr sequenced_t(); - - /// Get the value associated with a property object. - /** - * @returns sequenced_t(); - */ - static constexpr bulk_guarantee_t value(); - }; - - /// A sub-property that indicates that execution agents within the same bulk - /// execution may be parallelised. - struct parallel_t - { - /// The bulk_guarantee_t::parallel_t property applies to executors, - /// senders, and schedulers. - template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; - - /// The bulk_guarantee_t::parallel_t property can be required. - static constexpr bool is_requirable = true; - - /// The bulk_guarantee_t::parallel_t property can be preferred. - static constexpr bool is_preferable = true; - - /// The type returned by queries against an @c any_executor. - typedef bulk_guarantee_t polymorphic_query_result_type; - - /// Default constructor. - constexpr parallel_t(); - - /// Get the value associated with a property object. - /** - * @returns parallel_t(); - */ - static constexpr bulk_guarantee_t value(); - }; - - /// A special value used for accessing the bulk_guarantee_t::unsequenced_t - /// property. - static constexpr unsequenced_t unsequenced; - - /// A special value used for accessing the bulk_guarantee_t::sequenced_t - /// property. - static constexpr sequenced_t sequenced; - - /// A special value used for accessing the bulk_guarantee_t::parallel_t - /// property. - static constexpr parallel_t parallel; - - /// Default constructor. - constexpr bulk_guarantee_t(); - - /// Construct from a sub-property value. - constexpr bulk_guarantee_t(unsequenced_t); - - /// Construct from a sub-property value. - constexpr bulk_guarantee_t(sequenced_t); - - /// Construct from a sub-property value. - constexpr bulk_guarantee_t(parallel_t); - - /// Compare property values for equality. - friend constexpr bool operator==( - const bulk_guarantee_t& a, const bulk_guarantee_t& b) noexcept; - - /// Compare property values for inequality. - friend constexpr bool operator!=( - const bulk_guarantee_t& a, const bulk_guarantee_t& b) noexcept; -}; - -/// A special value used for accessing the bulk_guarantee_t property. -constexpr bulk_guarantee_t bulk_guarantee; - -} // namespace execution - -#else // defined(GENERATING_DOCUMENTATION) - -namespace execution { -namespace detail { -namespace bulk_guarantee { - -template <int I> struct unsequenced_t; -template <int I> struct sequenced_t; -template <int I> struct parallel_t; - -} // namespace bulk_guarantee - -template <int I = 0> -struct bulk_guarantee_t -{ -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - - ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); - typedef bulk_guarantee_t polymorphic_query_result_type; - - typedef detail::bulk_guarantee::unsequenced_t<I> unsequenced_t; - typedef detail::bulk_guarantee::sequenced_t<I> sequenced_t; - typedef detail::bulk_guarantee::parallel_t<I> parallel_t; - - ASIO_CONSTEXPR bulk_guarantee_t() - : value_(-1) - { - } - - ASIO_CONSTEXPR bulk_guarantee_t(unsequenced_t) - : value_(0) - { - } - - ASIO_CONSTEXPR bulk_guarantee_t(sequenced_t) - : value_(1) - { - } - - ASIO_CONSTEXPR bulk_guarantee_t(parallel_t) - : value_(2) - { - } - - template <typename T> - struct proxy - { -#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) - struct type - { - template <typename P> - auto query(ASIO_MOVE_ARG(P) p) const - noexcept( - noexcept( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) - ) - ) - -> decltype( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) - ); - }; -#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) - typedef T type; -#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) - }; - - template <typename T> - struct static_proxy - { -#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) - struct type - { - template <typename P> - static constexpr auto query(ASIO_MOVE_ARG(P) p) - noexcept( - noexcept( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) - ) - ) - -> decltype( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) - ) - { - return T::query(ASIO_MOVE_CAST(P)(p)); - } - }; -#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) - typedef T type; -#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) - }; - - template <typename T> - struct query_member : - traits::query_member<typename proxy<T>::type, bulk_guarantee_t> {}; - - template <typename T> - struct query_static_constexpr_member : - traits::query_static_constexpr_member< - typename static_proxy<T>::type, bulk_guarantee_t> {}; - -#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ - && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type - static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) - { - return query_static_constexpr_member<T>::value(); - } - - template <typename T> - static ASIO_CONSTEXPR - typename traits::static_query<T, unsequenced_t>::result_type - static_query( - typename enable_if< - !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< - !query_member<T>::is_valid - >::type* = 0, - typename enable_if< - traits::static_query<T, unsequenced_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT - { - return traits::static_query<T, unsequenced_t>::value(); - } - - template <typename T> - static ASIO_CONSTEXPR - typename traits::static_query<T, sequenced_t>::result_type - static_query( - typename enable_if< - !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< - !query_member<T>::is_valid - >::type* = 0, - typename enable_if< - !traits::static_query<T, unsequenced_t>::is_valid - >::type* = 0, - typename enable_if< - traits::static_query<T, sequenced_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT - { - return traits::static_query<T, sequenced_t>::value(); - } - - template <typename T> - static ASIO_CONSTEXPR - typename traits::static_query<T, parallel_t>::result_type - static_query( - typename enable_if< - !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< - !query_member<T>::is_valid - >::type* = 0, - typename enable_if< - !traits::static_query<T, unsequenced_t>::is_valid - >::type* = 0, - typename enable_if< - !traits::static_query<T, sequenced_t>::is_valid - >::type* = 0, - typename enable_if< - traits::static_query<T, parallel_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT - { - return traits::static_query<T, parallel_t>::value(); - } - - template <typename E, - typename T = decltype(bulk_guarantee_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = bulk_guarantee_t::static_query<E>(); -#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) - // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - - friend ASIO_CONSTEXPR bool operator==( - const bulk_guarantee_t& a, const bulk_guarantee_t& b) - { - return a.value_ == b.value_; - } - - friend ASIO_CONSTEXPR bool operator!=( - const bulk_guarantee_t& a, const bulk_guarantee_t& b) - { - return a.value_ != b.value_; - } - - struct convertible_from_bulk_guarantee_t - { - ASIO_CONSTEXPR convertible_from_bulk_guarantee_t(bulk_guarantee_t) {} - }; - - template <typename Executor> - friend ASIO_CONSTEXPR bulk_guarantee_t query( - const Executor& ex, convertible_from_bulk_guarantee_t, - typename enable_if< - can_query<const Executor&, unsequenced_t>::value - >::type* = 0) -#if !defined(__clang__) // Clang crashes if noexcept is used here. -#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, - bulk_guarantee_t<>::unsequenced_t>::value)) -#else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, unsequenced_t>::value)) -#endif // defined(ASIO_MSVC) -#endif // !defined(__clang__) - { - return asio::query(ex, unsequenced_t()); - } - - template <typename Executor> - friend ASIO_CONSTEXPR bulk_guarantee_t query( - const Executor& ex, convertible_from_bulk_guarantee_t, - typename enable_if< - !can_query<const Executor&, unsequenced_t>::value - >::type* = 0, - typename enable_if< - can_query<const Executor&, sequenced_t>::value - >::type* = 0) -#if !defined(__clang__) // Clang crashes if noexcept is used here. -#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, - bulk_guarantee_t<>::sequenced_t>::value)) -#else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, sequenced_t>::value)) -#endif // defined(ASIO_MSVC) -#endif // !defined(__clang__) - { - return asio::query(ex, sequenced_t()); - } - - template <typename Executor> - friend ASIO_CONSTEXPR bulk_guarantee_t query( - const Executor& ex, convertible_from_bulk_guarantee_t, - typename enable_if< - !can_query<const Executor&, unsequenced_t>::value - >::type* = 0, - typename enable_if< - !can_query<const Executor&, sequenced_t>::value - >::type* = 0, - typename enable_if< - can_query<const Executor&, parallel_t>::value - >::type* = 0) -#if !defined(__clang__) // Clang crashes if noexcept is used here. -#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, bulk_guarantee_t<>::parallel_t>::value)) -#else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, parallel_t>::value)) -#endif // defined(ASIO_MSVC) -#endif // !defined(__clang__) - { - return asio::query(ex, parallel_t()); - } - - ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(unsequenced_t, unsequenced); - ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(sequenced_t, sequenced); - ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(parallel_t, parallel); - -#if !defined(ASIO_HAS_CONSTEXPR) - static const bulk_guarantee_t instance; -#endif // !defined(ASIO_HAS_CONSTEXPR) - -private: - int value_; -}; - -#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ - && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -template <int I> template <typename E, typename T> -const T bulk_guarantee_t<I>::static_query_v; -#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) - // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - -#if !defined(ASIO_HAS_CONSTEXPR) -template <int I> -const bulk_guarantee_t<I> bulk_guarantee_t<I>::instance; -#endif - -template <int I> -const typename bulk_guarantee_t<I>::unsequenced_t -bulk_guarantee_t<I>::unsequenced; - -template <int I> -const typename bulk_guarantee_t<I>::sequenced_t -bulk_guarantee_t<I>::sequenced; - -template <int I> -const typename bulk_guarantee_t<I>::parallel_t -bulk_guarantee_t<I>::parallel; - -namespace bulk_guarantee { - -template <int I = 0> -struct unsequenced_t -{ -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); - typedef bulk_guarantee_t<I> polymorphic_query_result_type; - - ASIO_CONSTEXPR unsequenced_t() - { - } - - template <typename T> - struct query_member : - traits::query_member< - typename bulk_guarantee_t<I>::template proxy<T>::type, - unsequenced_t> {}; - - template <typename T> - struct query_static_constexpr_member : - traits::query_static_constexpr_member< - typename bulk_guarantee_t<I>::template static_proxy<T>::type, - unsequenced_t> {}; - -#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ - && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type - static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) - { - return query_static_constexpr_member<T>::value(); - } - - template <typename T> - static ASIO_CONSTEXPR unsequenced_t static_query( - typename enable_if< - !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< - !query_member<T>::is_valid - >::type* = 0, - typename enable_if< - !traits::query_free<T, unsequenced_t>::is_valid - >::type* = 0, - typename enable_if< - !can_query<T, sequenced_t<I> >::value - >::type* = 0, - typename enable_if< - !can_query<T, parallel_t<I> >::value - >::type* = 0) ASIO_NOEXCEPT - { - return unsequenced_t(); - } - - template <typename E, typename T = decltype(unsequenced_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = unsequenced_t::static_query<E>(); -#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) - // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - - static ASIO_CONSTEXPR bulk_guarantee_t<I> value() - { - return unsequenced_t(); - } - - friend ASIO_CONSTEXPR bool operator==( - const unsequenced_t&, const unsequenced_t&) - { - return true; - } - - friend ASIO_CONSTEXPR bool operator!=( - const unsequenced_t&, const unsequenced_t&) - { - return false; - } - - friend ASIO_CONSTEXPR bool operator==( - const unsequenced_t&, const sequenced_t<I>&) - { - return false; - } - - friend ASIO_CONSTEXPR bool operator!=( - const unsequenced_t&, const sequenced_t<I>&) - { - return true; - } - - friend ASIO_CONSTEXPR bool operator==( - const unsequenced_t&, const parallel_t<I>&) - { - return false; - } - - friend ASIO_CONSTEXPR bool operator!=( - const unsequenced_t&, const parallel_t<I>&) - { - return true; - } -}; - -#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ - && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -template <int I> template <typename E, typename T> -const T unsequenced_t<I>::static_query_v; -#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) - // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - -template <int I = 0> -struct sequenced_t -{ -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); - typedef bulk_guarantee_t<I> polymorphic_query_result_type; - - ASIO_CONSTEXPR sequenced_t() - { - } - - template <typename T> - struct query_member : - traits::query_member< - typename bulk_guarantee_t<I>::template proxy<T>::type, - sequenced_t> {}; - - template <typename T> - struct query_static_constexpr_member : - traits::query_static_constexpr_member< - typename bulk_guarantee_t<I>::template static_proxy<T>::type, - sequenced_t> {}; - -#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ - && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type - static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) - { - return query_static_constexpr_member<T>::value(); - } - - template <typename E, typename T = decltype(sequenced_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = sequenced_t::static_query<E>(); -#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) - // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - - static ASIO_CONSTEXPR bulk_guarantee_t<I> value() - { - return sequenced_t(); - } - - friend ASIO_CONSTEXPR bool operator==( - const sequenced_t&, const sequenced_t&) - { - return true; - } - - friend ASIO_CONSTEXPR bool operator!=( - const sequenced_t&, const sequenced_t&) - { - return false; - } - - friend ASIO_CONSTEXPR bool operator==( - const sequenced_t&, const unsequenced_t<I>&) - { - return false; - } - - friend ASIO_CONSTEXPR bool operator!=( - const sequenced_t&, const unsequenced_t<I>&) - { - return true; - } - - friend ASIO_CONSTEXPR bool operator==( - const sequenced_t&, const parallel_t<I>&) - { - return false; - } - - friend ASIO_CONSTEXPR bool operator!=( - const sequenced_t&, const parallel_t<I>&) - { - return true; - } -}; - -#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ - && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -template <int I> template <typename E, typename T> -const T sequenced_t<I>::static_query_v; -#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) - // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - -template <int I> -struct parallel_t -{ -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); - typedef bulk_guarantee_t<I> polymorphic_query_result_type; - - ASIO_CONSTEXPR parallel_t() - { - } - - template <typename T> - struct query_member : - traits::query_member< - typename bulk_guarantee_t<I>::template proxy<T>::type, - parallel_t> {}; - - template <typename T> - struct query_static_constexpr_member : - traits::query_static_constexpr_member< - typename bulk_guarantee_t<I>::template static_proxy<T>::type, - parallel_t> {}; - -#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ - && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type - static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) - { - return query_static_constexpr_member<T>::value(); - } - - template <typename E, typename T = decltype(parallel_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = parallel_t::static_query<E>(); -#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) - // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - - static ASIO_CONSTEXPR bulk_guarantee_t<I> value() - { - return parallel_t(); - } - - friend ASIO_CONSTEXPR bool operator==( - const parallel_t&, const parallel_t&) - { - return true; - } - - friend ASIO_CONSTEXPR bool operator!=( - const parallel_t&, const parallel_t&) - { - return false; - } - - friend ASIO_CONSTEXPR bool operator==( - const parallel_t&, const unsequenced_t<I>&) - { - return false; - } - - friend ASIO_CONSTEXPR bool operator!=( - const parallel_t&, const unsequenced_t<I>&) - { - return true; - } - - friend ASIO_CONSTEXPR bool operator==( - const parallel_t&, const sequenced_t<I>&) - { - return false; - } - - friend ASIO_CONSTEXPR bool operator!=( - const parallel_t&, const sequenced_t<I>&) - { - return true; - } -}; - -#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ - && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -template <int I> template <typename E, typename T> -const T parallel_t<I>::static_query_v; -#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) - // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - -} // namespace bulk_guarantee -} // namespace detail - -typedef detail::bulk_guarantee_t<> bulk_guarantee_t; - -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -constexpr bulk_guarantee_t bulk_guarantee; -#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -namespace { static const bulk_guarantee_t& - bulk_guarantee = bulk_guarantee_t::instance; } -#endif - -} // namespace execution - -#if !defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename T> -struct is_applicable_property<T, execution::bulk_guarantee_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> -{ -}; - -template <typename T> -struct is_applicable_property<T, execution::bulk_guarantee_t::unsequenced_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> -{ -}; - -template <typename T> -struct is_applicable_property<T, execution::bulk_guarantee_t::sequenced_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> -{ -}; - -template <typename T> -struct is_applicable_property<T, execution::bulk_guarantee_t::parallel_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> -{ -}; - -#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES) - -namespace traits { - -#if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) - -template <typename T> -struct query_free_default<T, execution::bulk_guarantee_t, - typename enable_if< - can_query<T, execution::bulk_guarantee_t::unsequenced_t>::value - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::bulk_guarantee_t::unsequenced_t>::value)); - - typedef execution::bulk_guarantee_t result_type; -}; - -template <typename T> -struct query_free_default<T, execution::bulk_guarantee_t, - typename enable_if< - !can_query<T, execution::bulk_guarantee_t::unsequenced_t>::value - && can_query<T, execution::bulk_guarantee_t::sequenced_t>::value - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::bulk_guarantee_t::sequenced_t>::value)); - - typedef execution::bulk_guarantee_t result_type; -}; - -template <typename T> -struct query_free_default<T, execution::bulk_guarantee_t, - typename enable_if< - !can_query<T, execution::bulk_guarantee_t::unsequenced_t>::value - && !can_query<T, execution::bulk_guarantee_t::sequenced_t>::value - && can_query<T, execution::bulk_guarantee_t::parallel_t>::value - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::bulk_guarantee_t::parallel_t>::value)); - - typedef execution::bulk_guarantee_t result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) - -#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ - || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - -template <typename T> -struct static_query<T, execution::bulk_guarantee_t, - typename enable_if< - execution::detail::bulk_guarantee_t<0>:: - query_static_constexpr_member<T>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - - typedef typename execution::detail::bulk_guarantee_t<0>:: - query_static_constexpr_member<T>::result_type result_type; - - static ASIO_CONSTEXPR result_type value() - { - return execution::detail::bulk_guarantee_t<0>:: - query_static_constexpr_member<T>::value(); - } -}; - -template <typename T> -struct static_query<T, execution::bulk_guarantee_t, - typename enable_if< - !execution::detail::bulk_guarantee_t<0>:: - query_static_constexpr_member<T>::is_valid - && !execution::detail::bulk_guarantee_t<0>:: - query_member<T>::is_valid - && traits::static_query<T, - execution::bulk_guarantee_t::unsequenced_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - - typedef typename traits::static_query<T, - execution::bulk_guarantee_t::unsequenced_t>::result_type result_type; - - static ASIO_CONSTEXPR result_type value() - { - return traits::static_query<T, - execution::bulk_guarantee_t::unsequenced_t>::value(); - } -}; - -template <typename T> -struct static_query<T, execution::bulk_guarantee_t, - typename enable_if< - !execution::detail::bulk_guarantee_t<0>:: - query_static_constexpr_member<T>::is_valid - && !execution::detail::bulk_guarantee_t<0>:: - query_member<T>::is_valid - && !traits::static_query<T, - execution::bulk_guarantee_t::unsequenced_t>::is_valid - && traits::static_query<T, - execution::bulk_guarantee_t::sequenced_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - - typedef typename traits::static_query<T, - execution::bulk_guarantee_t::sequenced_t>::result_type result_type; - - static ASIO_CONSTEXPR result_type value() - { - return traits::static_query<T, - execution::bulk_guarantee_t::sequenced_t>::value(); - } -}; - -template <typename T> -struct static_query<T, execution::bulk_guarantee_t, - typename enable_if< - !execution::detail::bulk_guarantee_t<0>:: - query_static_constexpr_member<T>::is_valid - && !execution::detail::bulk_guarantee_t<0>:: - query_member<T>::is_valid - && !traits::static_query<T, - execution::bulk_guarantee_t::unsequenced_t>::is_valid - && !traits::static_query<T, - execution::bulk_guarantee_t::sequenced_t>::is_valid - && traits::static_query<T, - execution::bulk_guarantee_t::parallel_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - - typedef typename traits::static_query<T, - execution::bulk_guarantee_t::parallel_t>::result_type result_type; - - static ASIO_CONSTEXPR result_type value() - { - return traits::static_query<T, - execution::bulk_guarantee_t::parallel_t>::value(); - } -}; - -template <typename T> -struct static_query<T, execution::bulk_guarantee_t::unsequenced_t, - typename enable_if< - execution::detail::bulk_guarantee::unsequenced_t<0>:: - query_static_constexpr_member<T>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - - typedef typename execution::detail::bulk_guarantee::unsequenced_t<0>:: - query_static_constexpr_member<T>::result_type result_type; - - static ASIO_CONSTEXPR result_type value() - { - return execution::detail::bulk_guarantee::unsequenced_t<0>:: - query_static_constexpr_member<T>::value(); - } -}; - -template <typename T> -struct static_query<T, execution::bulk_guarantee_t::unsequenced_t, - typename enable_if< - !execution::detail::bulk_guarantee::unsequenced_t<0>:: - query_static_constexpr_member<T>::is_valid - && !execution::detail::bulk_guarantee::unsequenced_t<0>:: - query_member<T>::is_valid - && !traits::query_free<T, - execution::bulk_guarantee_t::unsequenced_t>::is_valid - && !can_query<T, execution::bulk_guarantee_t::sequenced_t>::value - && !can_query<T, execution::bulk_guarantee_t::parallel_t>::value - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - - typedef execution::bulk_guarantee_t::unsequenced_t result_type; - - static ASIO_CONSTEXPR result_type value() - { - return result_type(); - } -}; - -template <typename T> -struct static_query<T, execution::bulk_guarantee_t::sequenced_t, - typename enable_if< - execution::detail::bulk_guarantee::sequenced_t<0>:: - query_static_constexpr_member<T>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - - typedef typename execution::detail::bulk_guarantee::sequenced_t<0>:: - query_static_constexpr_member<T>::result_type result_type; - - static ASIO_CONSTEXPR result_type value() - { - return execution::detail::bulk_guarantee::sequenced_t<0>:: - query_static_constexpr_member<T>::value(); - } -}; - -template <typename T> -struct static_query<T, execution::bulk_guarantee_t::parallel_t, - typename enable_if< - execution::detail::bulk_guarantee::parallel_t<0>:: - query_static_constexpr_member<T>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - - typedef typename execution::detail::bulk_guarantee::parallel_t<0>:: - query_static_constexpr_member<T>::result_type result_type; - - static ASIO_CONSTEXPR result_type value() - { - return execution::detail::bulk_guarantee::parallel_t<0>:: - query_static_constexpr_member<T>::value(); - } -}; - -#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) - // || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - -#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - -template <typename T> -struct static_require<T, execution::bulk_guarantee_t::unsequenced_t, - typename enable_if< - static_query<T, execution::bulk_guarantee_t::unsequenced_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::bulk_guarantee_t::unsequenced_t>::result_type, - execution::bulk_guarantee_t::unsequenced_t>::value)); -}; - -template <typename T> -struct static_require<T, execution::bulk_guarantee_t::sequenced_t, - typename enable_if< - static_query<T, execution::bulk_guarantee_t::sequenced_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::bulk_guarantee_t::sequenced_t>::result_type, - execution::bulk_guarantee_t::sequenced_t>::value)); -}; - -template <typename T> -struct static_require<T, execution::bulk_guarantee_t::parallel_t, - typename enable_if< - static_query<T, execution::bulk_guarantee_t::parallel_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::bulk_guarantee_t::parallel_t>::result_type, - execution::bulk_guarantee_t::parallel_t>::value)); -}; - -#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - -} // namespace traits - -#endif // defined(GENERATING_DOCUMENTATION) - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_BULK_GUARANTEE_HPP diff --git a/3rdparty/asio/include/asio/execution/connect.hpp b/3rdparty/asio/include/asio/execution/connect.hpp deleted file mode 100644 index 527f123294f..00000000000 --- a/3rdparty/asio/include/asio/execution/connect.hpp +++ /dev/null @@ -1,489 +0,0 @@ -// -// execution/connect.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_CONNECT_HPP -#define ASIO_EXECUTION_CONNECT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/detail/as_invocable.hpp" -#include "asio/execution/detail/as_operation.hpp" -#include "asio/execution/detail/as_receiver.hpp" -#include "asio/execution/executor.hpp" -#include "asio/execution/operation_state.hpp" -#include "asio/execution/receiver.hpp" -#include "asio/execution/sender.hpp" -#include "asio/traits/connect_member.hpp" -#include "asio/traits/connect_free.hpp" - -#include "asio/detail/push_options.hpp" - -#if defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace execution { - -/// A customisation point that connects a sender to a receiver. -/** - * The name <tt>execution::connect</tt> denotes a customisation point object. - * For some subexpressions <tt>s</tt> and <tt>r</tt>, let <tt>S</tt> be a type - * such that <tt>decltype((s))</tt> is <tt>S</tt> and let <tt>R</tt> be a type - * such that <tt>decltype((r))</tt> is <tt>R</tt>. The expression - * <tt>execution::connect(s, r)</tt> is expression-equivalent to: - * - * @li <tt>s.connect(r)</tt>, if that expression is valid, if its type - * satisfies <tt>operation_state</tt>, and if <tt>S</tt> satisfies - * <tt>sender</tt>. - * - * @li Otherwise, <tt>connect(s, r)</tt>, if that expression is valid, if its - * type satisfies <tt>operation_state</tt>, and if <tt>S</tt> satisfies - * <tt>sender</tt>, with overload resolution performed in a context that - * includes the declaration <tt>void connect();</tt> and that does not include - * a declaration of <tt>execution::connect</tt>. - * - * @li Otherwise, <tt>as_operation{s, r}</tt>, if <tt>r</tt> is not an instance - * of <tt>as_receiver<F, S></tt> for some type <tt>F</tt>, and if - * <tt>receiver_of<R> && executor_of<remove_cvref_t<S>, - * as_invocable<remove_cvref_t<R>, S>></tt> is <tt>true</tt>, where - * <tt>as_operation</tt> is an implementation-defined class equivalent to - * @code template <class S, class R> - * struct as_operation - * { - * remove_cvref_t<S> e_; - * remove_cvref_t<R> r_; - * void start() noexcept try { - * execution::execute(std::move(e_), - * as_invocable<remove_cvref_t<R>, S>{r_}); - * } catch(...) { - * execution::set_error(std::move(r_), current_exception()); - * } - * }; @endcode - * and <tt>as_invocable</tt> is a class template equivalent to the following: - * @code template<class R> - * struct as_invocable - * { - * R* r_; - * explicit as_invocable(R& r) noexcept - * : r_(std::addressof(r)) {} - * as_invocable(as_invocable && other) noexcept - * : r_(std::exchange(other.r_, nullptr)) {} - * ~as_invocable() { - * if(r_) - * execution::set_done(std::move(*r_)); - * } - * void operator()() & noexcept try { - * execution::set_value(std::move(*r_)); - * r_ = nullptr; - * } catch(...) { - * execution::set_error(std::move(*r_), current_exception()); - * r_ = nullptr; - * } - * }; - * @endcode - * - * @li Otherwise, <tt>execution::connect(s, r)</tt> is ill-formed. - */ -inline constexpr unspecified connect = unspecified; - -/// A type trait that determines whether a @c connect expression is -/// well-formed. -/** - * Class template @c can_connect is a trait that is derived from - * @c true_type if the expression <tt>execution::connect(std::declval<S>(), - * std::declval<R>())</tt> is well formed; otherwise @c false_type. - */ -template <typename S, typename R> -struct can_connect : - integral_constant<bool, automatically_determined> -{ -}; - -/// A type trait to determine the result of a @c connect expression. -template <typename S, typename R> -struct connect_result -{ - /// The type of the connect expression. - /** - * The type of the expression <tt>execution::connect(std::declval<S>(), - * std::declval<R>())</tt>. - */ - typedef automatically_determined type; -}; - -/// A type alis to determine the result of a @c connect expression. -template <typename S, typename R> -using connect_result_t = typename connect_result<S, R>::type; - -} // namespace execution -} // namespace asio - -#else // defined(GENERATING_DOCUMENTATION) - -namespace asio_execution_connect_fn { - -using asio::conditional; -using asio::declval; -using asio::enable_if; -using asio::execution::detail::as_invocable; -using asio::execution::detail::as_operation; -using asio::execution::detail::is_as_receiver; -using asio::execution::is_executor_of; -using asio::execution::is_operation_state; -using asio::execution::is_receiver; -using asio::execution::is_sender; -using asio::false_type; -using asio::remove_cvref; -using asio::traits::connect_free; -using asio::traits::connect_member; - -void connect(); - -enum overload_type -{ - call_member, - call_free, - adapter, - ill_formed -}; - -template <typename S, typename R, typename = void, - typename = void, typename = void, typename = void> -struct call_traits -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef void result_type; -}; - -template <typename S, typename R> -struct call_traits<S, void(R), - typename enable_if< - connect_member<S, R>::is_valid - >::type, - typename enable_if< - is_operation_state<typename connect_member<S, R>::result_type>::value - >::type, - typename enable_if< - is_sender<typename remove_cvref<S>::type>::value - >::type> : - connect_member<S, R> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); -}; - -template <typename S, typename R> -struct call_traits<S, void(R), - typename enable_if< - !connect_member<S, R>::is_valid - >::type, - typename enable_if< - connect_free<S, R>::is_valid - >::type, - typename enable_if< - is_operation_state<typename connect_free<S, R>::result_type>::value - >::type, - typename enable_if< - is_sender<typename remove_cvref<S>::type>::value - >::type> : - connect_free<S, R> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); -}; - -template <typename S, typename R> -struct call_traits<S, void(R), - typename enable_if< - !connect_member<S, R>::is_valid - >::type, - typename enable_if< - !connect_free<S, R>::is_valid - >::type, - typename enable_if< - is_receiver<R>::value - >::type, - typename enable_if< - conditional< - !is_as_receiver< - typename remove_cvref<R>::type - >::value, - is_executor_of< - typename remove_cvref<S>::type, - as_invocable<typename remove_cvref<R>::type, S> - >, - false_type - >::type::value - >::type> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef as_operation<S, R> result_type; -}; - -struct impl -{ -#if defined(ASIO_HAS_MOVE) - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(R)>::overload == call_member, - typename call_traits<S, void(R)>::result_type - >::type - operator()(S&& s, R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(R)>::is_noexcept)) - { - return ASIO_MOVE_CAST(S)(s).connect(ASIO_MOVE_CAST(R)(r)); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(R)>::overload == call_free, - typename call_traits<S, void(R)>::result_type - >::type - operator()(S&& s, R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(R)>::is_noexcept)) - { - return connect(ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(R)(r)); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(R)>::overload == adapter, - typename call_traits<S, void(R)>::result_type - >::type - operator()(S&& s, R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(R)>::is_noexcept)) - { - return typename call_traits<S, void(R)>::result_type( - ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(R)(r)); - } -#else // defined(ASIO_HAS_MOVE) - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(R&)>::overload == call_member, - typename call_traits<S&, void(R&)>::result_type - >::type - operator()(S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(R&)>::is_noexcept)) - { - return s.connect(r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(R&)>::overload == call_member, - typename call_traits<const S&, void(R&)>::result_type - >::type - operator()(const S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(R&)>::is_noexcept)) - { - return s.connect(r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(R&)>::overload == call_free, - typename call_traits<S&, void(R&)>::result_type - >::type - operator()(S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(R&)>::is_noexcept)) - { - return connect(s, r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(R&)>::overload == call_free, - typename call_traits<const S&, void(R&)>::result_type - >::type - operator()(const S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(R&)>::is_noexcept)) - { - return connect(s, r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(R&)>::overload == adapter, - typename call_traits<S&, void(R&)>::result_type - >::type - operator()(S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(R&)>::is_noexcept)) - { - return typename call_traits<S&, void(R&)>::result_type(s, r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(R&)>::overload == adapter, - typename call_traits<const S&, void(R&)>::result_type - >::type - operator()(const S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(R&)>::is_noexcept)) - { - return typename call_traits<const S&, void(R&)>::result_type(s, r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(const R&)>::overload == call_member, - typename call_traits<S&, void(const R&)>::result_type - >::type - operator()(S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(const R&)>::is_noexcept)) - { - return s.connect(r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(const R&)>::overload == call_member, - typename call_traits<const S&, void(const R&)>::result_type - >::type - operator()(const S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(const R&)>::is_noexcept)) - { - return s.connect(r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(const R&)>::overload == call_free, - typename call_traits<S&, void(const R&)>::result_type - >::type - operator()(S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(const R&)>::is_noexcept)) - { - return connect(s, r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(const R&)>::overload == call_free, - typename call_traits<const S&, void(const R&)>::result_type - >::type - operator()(const S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(const R&)>::is_noexcept)) - { - return connect(s, r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(const R&)>::overload == adapter, - typename call_traits<S&, void(const R&)>::result_type - >::type - operator()(S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(const R&)>::is_noexcept)) - { - return typename call_traits<S&, void(const R&)>::result_type(s, r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(const R&)>::overload == adapter, - typename call_traits<const S&, void(const R&)>::result_type - >::type - operator()(const S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(const R&)>::is_noexcept)) - { - return typename call_traits<const S&, void(const R&)>::result_type(s, r); - } -#endif // defined(ASIO_HAS_MOVE) -}; - -template <typename T = impl> -struct static_instance -{ - static const T instance; -}; - -template <typename T> -const T static_instance<T>::instance = {}; - -} // namespace asio_execution_connect_fn -namespace asio { -namespace execution { -namespace { - -static ASIO_CONSTEXPR const asio_execution_connect_fn::impl& - connect = asio_execution_connect_fn::static_instance<>::instance; - -} // namespace - -template <typename S, typename R> -struct can_connect : - integral_constant<bool, - asio_execution_connect_fn::call_traits<S, void(R)>::overload != - asio_execution_connect_fn::ill_formed> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename R> -constexpr bool can_connect_v = can_connect<S, R>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename R> -struct is_nothrow_connect : - integral_constant<bool, - asio_execution_connect_fn::call_traits<S, void(R)>::is_noexcept> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename R> -constexpr bool is_nothrow_connect_v - = is_nothrow_connect<S, R>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename R> -struct connect_result -{ - typedef typename asio_execution_connect_fn::call_traits< - S, void(R)>::result_type type; -}; - -#if defined(ASIO_HAS_ALIAS_TEMPLATES) - -template <typename S, typename R> -using connect_result_t = typename connect_result<S, R>::type; - -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - -} // namespace execution -} // namespace asio - -#endif // defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_CONNECT_HPP diff --git a/3rdparty/asio/include/asio/execution/context.hpp b/3rdparty/asio/include/asio/execution/context.hpp index f751c7a6e65..a9df9c1c4b6 100644 --- a/3rdparty/asio/include/asio/execution/context.hpp +++ b/3rdparty/asio/include/asio/execution/context.hpp @@ -2,7 +2,7 @@ // execution/context.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,8 +18,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" #include "asio/is_applicable_property.hpp" #include "asio/traits/query_static_constexpr_member.hpp" #include "asio/traits/static_query.hpp" @@ -40,10 +38,9 @@ namespace execution { /// with an executor. struct context_t { - /// The context_t property applies to executors, senders, and schedulers. + /// The context_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The context_t property cannot be required. static constexpr bool is_requirable = false; @@ -70,29 +67,17 @@ struct context_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); + static constexpr bool is_requirable = false; + static constexpr bool is_preferable = false; #if defined(ASIO_HAS_STD_ANY) typedef std::any polymorphic_query_result_type; #endif // defined(ASIO_HAS_STD_ANY) - ASIO_CONSTEXPR context_t() + constexpr context_t() { } @@ -103,17 +88,17 @@ struct context_t struct type { template <typename P> - static constexpr auto query(ASIO_MOVE_ARG(P) p) + static constexpr auto query(P&& p) noexcept( noexcept( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) ) -> decltype( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) { - return T::query(ASIO_MOVE_CAST(P)(p)); + return T::query(static_cast<P&&>(p)); } }; #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) @@ -129,24 +114,17 @@ struct context_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(context_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = context_t::static_query<E>(); + static constexpr const T static_query_v = context_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - -#if !defined(ASIO_HAS_CONSTEXPR) - static const context_t instance; -#endif // !defined(ASIO_HAS_CONSTEXPR) }; #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ @@ -156,20 +134,11 @@ const T context_t<I>::static_query_v; #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_CONSTEXPR) -template <int I> -const context_t<I> context_t<I>::instance; -#endif - } // namespace detail typedef detail::context_t<> context_t; -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr context_t context; -#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -namespace { static const context_t& context = context_t::instance; } -#endif } // namespace execution @@ -177,18 +146,7 @@ namespace { static const context_t& context = context_t::instance; } template <typename T> struct is_applicable_property<T, execution::context_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; @@ -201,18 +159,18 @@ namespace traits { template <typename T> struct static_query<T, execution::context_t, - typename enable_if< + enable_if_t< execution::detail::context_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::context_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::context_t<0>:: query_static_constexpr_member<T>::value(); diff --git a/3rdparty/asio/include/asio/execution/context_as.hpp b/3rdparty/asio/include/asio/execution/context_as.hpp index 740918c7993..f51fb1dc4c7 100644 --- a/3rdparty/asio/include/asio/execution/context_as.hpp +++ b/3rdparty/asio/include/asio/execution/context_as.hpp @@ -2,7 +2,7 @@ // execution/context_as.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,8 +19,6 @@ #include "asio/detail/type_traits.hpp" #include "asio/execution/context.hpp" #include "asio/execution/executor.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" #include "asio/is_applicable_property.hpp" #include "asio/query.hpp" #include "asio/traits/query_static_constexpr_member.hpp" @@ -39,10 +37,9 @@ namespace execution { template <typename U> struct context_as_t { - /// The context_as_t property applies to executors, senders, and schedulers. + /// The context_as_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The context_t property cannot be required. static constexpr bool is_requirable = false; @@ -69,68 +66,53 @@ struct context_as_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename U> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<U>::value - || conditional< - is_executor<U>::value, - false_type, - is_sender<U> - >::type::value - || conditional< - is_executor<U>::value, - false_type, - is_scheduler<U> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<U>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); + static constexpr bool is_requirable = false; + static constexpr bool is_preferable = false; typedef T polymorphic_query_result_type; - ASIO_CONSTEXPR context_as_t() + constexpr context_as_t() { } - ASIO_CONSTEXPR context_as_t(context_t) + constexpr context_as_t(context_t) { } #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename E> - static ASIO_CONSTEXPR + static constexpr typename context_t::query_static_constexpr_member<E>::result_type static_query() - ASIO_NOEXCEPT_IF(( - context_t::query_static_constexpr_member<E>::is_noexcept)) + noexcept(context_t::query_static_constexpr_member<E>::is_noexcept) { return context_t::query_static_constexpr_member<E>::value(); } template <typename E, typename U = decltype(context_as_t::static_query<E>())> - static ASIO_CONSTEXPR const U static_query_v + static constexpr const U static_query_v = context_as_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename Executor, typename U> - friend ASIO_CONSTEXPR U query( + friend constexpr U query( const Executor& ex, const context_as_t<U>&, - typename enable_if< + enable_if_t< is_same<T, U>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< can_query<const Executor&, const context_t&>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, const context_t&>::value)) + noexcept(is_nothrow_query<const Executor&, const context_t&>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, const context_t&>::value)) + noexcept(is_nothrow_query<const Executor&, const context_t&>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -145,13 +127,11 @@ const U context_as_t<T>::static_query_v; #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if (defined(ASIO_HAS_VARIABLE_TEMPLATES) \ - && defined(ASIO_HAS_CONSTEXPR)) \ +#if defined(ASIO_HAS_VARIABLE_TEMPLATES) \ || defined(GENERATING_DOCUMENTATION) template <typename T> constexpr context_as_t<T> context_as{}; -#endif // (defined(ASIO_HAS_VARIABLE_TEMPLATES) - // && defined(ASIO_HAS_CONSTEXPR)) +#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) // || defined(GENERATING_DOCUMENTATION) } // namespace execution @@ -159,19 +139,8 @@ constexpr context_as_t<T> context_as{}; #if !defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T, typename U> -struct is_applicable_property<T, execution::context_as_t<U> > - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> +struct is_applicable_property<T, execution::context_as_t<U>> + : integral_constant<bool, execution::is_executor<T>::value> { }; @@ -184,9 +153,9 @@ namespace traits { template <typename T, typename U> struct static_query<T, execution::context_as_t<U>, - typename enable_if< + enable_if_t< static_query<T, execution::context_t>::is_valid - >::type> : static_query<T, execution::context_t> + >> : static_query<T, execution::context_t> { }; @@ -197,13 +166,13 @@ struct static_query<T, execution::context_as_t<U>, template <typename T, typename U> struct query_free<T, execution::context_as_t<U>, - typename enable_if< - can_query<const T&, const execution::context_t&>::value - >::type> + enable_if_t< + can_query<const T&, const execution::context_t&>::value + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<const T&, const execution::context_t&>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<const T&, const execution::context_t&>::value; typedef U result_type; }; diff --git a/3rdparty/asio/include/asio/execution/detail/as_invocable.hpp b/3rdparty/asio/include/asio/execution/detail/as_invocable.hpp deleted file mode 100644 index 13b6e44dd23..00000000000 --- a/3rdparty/asio/include/asio/execution/detail/as_invocable.hpp +++ /dev/null @@ -1,152 +0,0 @@ -// -// execution/detail/as_invocable.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_DETAIL_AS_INVOCABLE_HPP -#define ASIO_EXECUTION_DETAIL_AS_INVOCABLE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/atomic_count.hpp" -#include "asio/detail/memory.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/receiver_invocation_error.hpp" -#include "asio/execution/set_done.hpp" -#include "asio/execution/set_error.hpp" -#include "asio/execution/set_value.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace execution { -namespace detail { - -#if defined(ASIO_HAS_MOVE) - -template <typename Receiver, typename> -struct as_invocable -{ - Receiver* receiver_; - - explicit as_invocable(Receiver& r) ASIO_NOEXCEPT - : receiver_(asio::detail::addressof(r)) - { - } - - as_invocable(as_invocable&& other) ASIO_NOEXCEPT - : receiver_(other.receiver_) - { - other.receiver_ = 0; - } - - ~as_invocable() - { - if (receiver_) - execution::set_done(ASIO_MOVE_OR_LVALUE(Receiver)(*receiver_)); - } - - void operator()() ASIO_LVALUE_REF_QUAL ASIO_NOEXCEPT - { -#if !defined(ASIO_NO_EXCEPTIONS) - try - { -#endif // !defined(ASIO_NO_EXCEPTIONS) - execution::set_value(ASIO_MOVE_CAST(Receiver)(*receiver_)); - receiver_ = 0; -#if !defined(ASIO_NO_EXCEPTIONS) - } - catch (...) - { -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) - execution::set_error(ASIO_MOVE_CAST(Receiver)(*receiver_), - std::make_exception_ptr(receiver_invocation_error())); - receiver_ = 0; -#else // defined(ASIO_HAS_STD_EXCEPTION_PTR) - std::terminate(); -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - } -#endif // !defined(ASIO_NO_EXCEPTIONS) - } -}; - -#else // defined(ASIO_HAS_MOVE) - -template <typename Receiver, typename> -struct as_invocable -{ - Receiver* receiver_; - asio::detail::shared_ptr<asio::detail::atomic_count> ref_count_; - - explicit as_invocable(Receiver& r, - const asio::detail::shared_ptr< - asio::detail::atomic_count>& c) ASIO_NOEXCEPT - : receiver_(asio::detail::addressof(r)), - ref_count_(c) - { - } - - as_invocable(const as_invocable& other) ASIO_NOEXCEPT - : receiver_(other.receiver_), - ref_count_(other.ref_count_) - { - ++(*ref_count_); - } - - ~as_invocable() - { - if (--(*ref_count_) == 0) - execution::set_done(*receiver_); - } - - void operator()() ASIO_LVALUE_REF_QUAL ASIO_NOEXCEPT - { -#if !defined(ASIO_NO_EXCEPTIONS) - try - { -#endif // !defined(ASIO_NO_EXCEPTIONS) - execution::set_value(*receiver_); - ++(*ref_count_); - } -#if !defined(ASIO_NO_EXCEPTIONS) - catch (...) - { -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) - execution::set_error(*receiver_, - std::make_exception_ptr(receiver_invocation_error())); - ++(*ref_count_); -#else // defined(ASIO_HAS_STD_EXCEPTION_PTR) - std::terminate(); -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - } -#endif // !defined(ASIO_NO_EXCEPTIONS) - } -}; - -#endif // defined(ASIO_HAS_MOVE) - -template <typename T> -struct is_as_invocable : false_type -{ -}; - -template <typename Function, typename T> -struct is_as_invocable<as_invocable<Function, T> > : true_type -{ -}; - -} // namespace detail -} // namespace execution -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_DETAIL_AS_INVOCABLE_HPP diff --git a/3rdparty/asio/include/asio/execution/detail/as_operation.hpp b/3rdparty/asio/include/asio/execution/detail/as_operation.hpp deleted file mode 100644 index 565bf3634e6..00000000000 --- a/3rdparty/asio/include/asio/execution/detail/as_operation.hpp +++ /dev/null @@ -1,105 +0,0 @@ -// -// execution/detail/as_operation.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_DETAIL_AS_OPERATION_HPP -#define ASIO_EXECUTION_DETAIL_AS_OPERATION_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/memory.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/detail/as_invocable.hpp" -#include "asio/execution/execute.hpp" -#include "asio/execution/set_error.hpp" -#include "asio/traits/start_member.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace execution { -namespace detail { - -template <typename Executor, typename Receiver> -struct as_operation -{ - typename remove_cvref<Executor>::type ex_; - typename remove_cvref<Receiver>::type receiver_; -#if !defined(ASIO_HAS_MOVE) - asio::detail::shared_ptr<asio::detail::atomic_count> ref_count_; -#endif // !defined(ASIO_HAS_MOVE) - - template <typename E, typename R> - explicit as_operation(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(R) r) - : ex_(ASIO_MOVE_CAST(E)(e)), - receiver_(ASIO_MOVE_CAST(R)(r)) -#if !defined(ASIO_HAS_MOVE) - , ref_count_(new asio::detail::atomic_count(1)) -#endif // !defined(ASIO_HAS_MOVE) - { - } - - void start() ASIO_NOEXCEPT - { -#if !defined(ASIO_NO_EXCEPTIONS) - try - { -#endif // !defined(ASIO_NO_EXCEPTIONS) - execution::execute( - ASIO_MOVE_CAST(typename remove_cvref<Executor>::type)(ex_), - as_invocable<typename remove_cvref<Receiver>::type, - Executor>(receiver_ -#if !defined(ASIO_HAS_MOVE) - , ref_count_ -#endif // !defined(ASIO_HAS_MOVE) - )); -#if !defined(ASIO_NO_EXCEPTIONS) - } - catch (...) - { -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) - execution::set_error( - ASIO_MOVE_OR_LVALUE( - typename remove_cvref<Receiver>::type)( - receiver_), - std::current_exception()); -#else // defined(ASIO_HAS_STD_EXCEPTION_PTR) - std::terminate(); -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - } -#endif // !defined(ASIO_NO_EXCEPTIONS) - } -}; - -} // namespace detail -} // namespace execution -namespace traits { - -#if !defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT) - -template <typename Executor, typename Receiver> -struct start_member< - asio::execution::detail::as_operation<Executor, Receiver> > -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT) - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_DETAIL_AS_OPERATION_HPP diff --git a/3rdparty/asio/include/asio/execution/detail/as_receiver.hpp b/3rdparty/asio/include/asio/execution/detail/as_receiver.hpp deleted file mode 100644 index a10bdc7f9b4..00000000000 --- a/3rdparty/asio/include/asio/execution/detail/as_receiver.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// execution/detail/as_receiver.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_DETAIL_AS_RECEIVER_HPP -#define ASIO_EXECUTION_DETAIL_AS_RECEIVER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/traits/set_done_member.hpp" -#include "asio/traits/set_error_member.hpp" -#include "asio/traits/set_value_member.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace execution { -namespace detail { - -template <typename Function, typename> -struct as_receiver -{ - Function f_; - - template <typename F> - explicit as_receiver(ASIO_MOVE_ARG(F) f, int) - : f_(ASIO_MOVE_CAST(F)(f)) - { - } - -#if defined(ASIO_MSVC) && defined(ASIO_HAS_MOVE) - as_receiver(as_receiver&& other) - : f_(ASIO_MOVE_CAST(Function)(other.f_)) - { - } -#endif // defined(ASIO_MSVC) && defined(ASIO_HAS_MOVE) - - void set_value() - ASIO_NOEXCEPT_IF(noexcept(declval<Function&>()())) - { - f_(); - } - - template <typename E> - void set_error(E) ASIO_NOEXCEPT - { - std::terminate(); - } - - void set_done() ASIO_NOEXCEPT - { - } -}; - -template <typename T> -struct is_as_receiver : false_type -{ -}; - -template <typename Function, typename T> -struct is_as_receiver<as_receiver<Function, T> > : true_type -{ -}; - -} // namespace detail -} // namespace execution -namespace traits { - -#if !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - -template <typename Function, typename T> -struct set_value_member< - asio::execution::detail::as_receiver<Function, T>, void()> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); -#if defined(ASIO_HAS_NOEXCEPT) - ASIO_STATIC_CONSTEXPR(bool, - is_noexcept = noexcept(declval<Function&>()())); -#else // defined(ASIO_HAS_NOEXCEPT) - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); -#endif // defined(ASIO_HAS_NOEXCEPT) - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - -#if !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - -template <typename Function, typename T, typename E> -struct set_error_member< - asio::execution::detail::as_receiver<Function, T>, E> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - -#if !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - -template <typename Function, typename T> -struct set_done_member< - asio::execution::detail::as_receiver<Function, T> > -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_DETAIL_AS_RECEIVER_HPP diff --git a/3rdparty/asio/include/asio/execution/detail/bulk_sender.hpp b/3rdparty/asio/include/asio/execution/detail/bulk_sender.hpp deleted file mode 100644 index 0e4e5c12d5b..00000000000 --- a/3rdparty/asio/include/asio/execution/detail/bulk_sender.hpp +++ /dev/null @@ -1,261 +0,0 @@ -// -// execution/detail/bulk_sender.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_DETAIL_BULK_SENDER_HPP -#define ASIO_EXECUTION_DETAIL_BULK_SENDER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/connect.hpp" -#include "asio/execution/executor.hpp" -#include "asio/execution/set_done.hpp" -#include "asio/execution/set_error.hpp" -#include "asio/traits/connect_member.hpp" -#include "asio/traits/set_done_member.hpp" -#include "asio/traits/set_error_member.hpp" -#include "asio/traits/set_value_member.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace execution { -namespace detail { - -template <typename Receiver, typename Function, typename Number, typename Index> -struct bulk_receiver -{ - typename remove_cvref<Receiver>::type receiver_; - typename decay<Function>::type f_; - typename decay<Number>::type n_; - - template <typename R, typename F, typename N> - explicit bulk_receiver(ASIO_MOVE_ARG(R) r, - ASIO_MOVE_ARG(F) f, ASIO_MOVE_ARG(N) n) - : receiver_(ASIO_MOVE_CAST(R)(r)), - f_(ASIO_MOVE_CAST(F)(f)), - n_(ASIO_MOVE_CAST(N)(n)) - { - } - - void set_value() - { - for (Index i = 0; i < n_; ++i) - f_(i); - - execution::set_value( - ASIO_MOVE_OR_LVALUE( - typename remove_cvref<Receiver>::type)(receiver_)); - } - - template <typename Error> - void set_error(ASIO_MOVE_ARG(Error) e) ASIO_NOEXCEPT - { - execution::set_error( - ASIO_MOVE_OR_LVALUE( - typename remove_cvref<Receiver>::type)(receiver_), - ASIO_MOVE_CAST(Error)(e)); - } - - void set_done() ASIO_NOEXCEPT - { - execution::set_done( - ASIO_MOVE_OR_LVALUE( - typename remove_cvref<Receiver>::type)(receiver_)); - } -}; - -template <typename Sender, typename Receiver, - typename Function, typename Number> -struct bulk_receiver_traits -{ - typedef bulk_receiver< - Receiver, Function, Number, - typename execution::executor_index< - typename remove_cvref<Sender>::type - >::type - > type; - -#if defined(ASIO_HAS_MOVE) - typedef type arg_type; -#else // defined(ASIO_HAS_MOVE) - typedef const type& arg_type; -#endif // defined(ASIO_HAS_MOVE) -}; - -template <typename Sender, typename Function, typename Number> -struct bulk_sender : sender_base -{ - typename remove_cvref<Sender>::type sender_; - typename decay<Function>::type f_; - typename decay<Number>::type n_; - - template <typename S, typename F, typename N> - explicit bulk_sender(ASIO_MOVE_ARG(S) s, - ASIO_MOVE_ARG(F) f, ASIO_MOVE_ARG(N) n) - : sender_(ASIO_MOVE_CAST(S)(s)), - f_(ASIO_MOVE_CAST(F)(f)), - n_(ASIO_MOVE_CAST(N)(n)) - { - } - - template <typename Receiver> - typename connect_result< - ASIO_MOVE_OR_LVALUE_TYPE(typename remove_cvref<Sender>::type), - typename bulk_receiver_traits< - Sender, Receiver, Function, Number - >::arg_type - >::type connect(ASIO_MOVE_ARG(Receiver) r, - typename enable_if< - can_connect< - typename remove_cvref<Sender>::type, - typename bulk_receiver_traits< - Sender, Receiver, Function, Number - >::arg_type - >::value - >::type* = 0) ASIO_RVALUE_REF_QUAL ASIO_NOEXCEPT - { - return execution::connect( - ASIO_MOVE_OR_LVALUE(typename remove_cvref<Sender>::type)(sender_), - typename bulk_receiver_traits<Sender, Receiver, Function, Number>::type( - ASIO_MOVE_CAST(Receiver)(r), - ASIO_MOVE_CAST(typename decay<Function>::type)(f_), - ASIO_MOVE_CAST(typename decay<Number>::type)(n_))); - } - - template <typename Receiver> - typename connect_result< - const typename remove_cvref<Sender>::type&, - typename bulk_receiver_traits< - Sender, Receiver, Function, Number - >::arg_type - >::type connect(ASIO_MOVE_ARG(Receiver) r, - typename enable_if< - can_connect< - const typename remove_cvref<Sender>::type&, - typename bulk_receiver_traits< - Sender, Receiver, Function, Number - >::arg_type - >::value - >::type* = 0) const ASIO_LVALUE_REF_QUAL ASIO_NOEXCEPT - { - return execution::connect(sender_, - typename bulk_receiver_traits<Sender, Receiver, Function, Number>::type( - ASIO_MOVE_CAST(Receiver)(r), f_, n_)); - } -}; - -} // namespace detail -} // namespace execution -namespace traits { - -#if !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - -template <typename Receiver, typename Function, typename Number, typename Index> -struct set_value_member< - execution::detail::bulk_receiver<Receiver, Function, Number, Index>, - void()> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - -#if !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - -template <typename Receiver, typename Function, - typename Number, typename Index, typename Error> -struct set_error_member< - execution::detail::bulk_receiver<Receiver, Function, Number, Index>, - Error> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - -#if !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - -template <typename Receiver, typename Function, typename Number, typename Index> -struct set_done_member< - execution::detail::bulk_receiver<Receiver, Function, Number, Index> > -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - -#if !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) - -template <typename Sender, typename Function, - typename Number, typename Receiver> -struct connect_member< - execution::detail::bulk_sender<Sender, Function, Number>, - Receiver, - typename enable_if< - execution::can_connect< - ASIO_MOVE_OR_LVALUE_TYPE(typename remove_cvref<Sender>::type), - typename execution::detail::bulk_receiver_traits< - Sender, Receiver, Function, Number - >::arg_type - >::value - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef typename execution::connect_result< - ASIO_MOVE_OR_LVALUE_TYPE(typename remove_cvref<Sender>::type), - typename execution::detail::bulk_receiver_traits< - Sender, Receiver, Function, Number - >::arg_type - >::type result_type; -}; - -template <typename Sender, typename Function, - typename Number, typename Receiver> -struct connect_member< - const execution::detail::bulk_sender<Sender, Function, Number>, - Receiver, - typename enable_if< - execution::can_connect< - const typename remove_cvref<Sender>::type&, - typename execution::detail::bulk_receiver_traits< - Sender, Receiver, Function, Number - >::arg_type - >::value - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef typename execution::connect_result< - const typename remove_cvref<Sender>::type&, - typename execution::detail::bulk_receiver_traits< - Sender, Receiver, Function, Number - >::arg_type - >::type result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_DETAIL_BULK_SENDER_HPP diff --git a/3rdparty/asio/include/asio/execution/detail/submit_receiver.hpp b/3rdparty/asio/include/asio/execution/detail/submit_receiver.hpp deleted file mode 100644 index 6faa119d224..00000000000 --- a/3rdparty/asio/include/asio/execution/detail/submit_receiver.hpp +++ /dev/null @@ -1,233 +0,0 @@ -// -// execution/detail/submit_receiver.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_DETAIL_SUBMIT_RECEIVER_HPP -#define ASIO_EXECUTION_DETAIL_SUBMIT_RECEIVER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" -#include "asio/execution/connect.hpp" -#include "asio/execution/receiver.hpp" -#include "asio/execution/set_done.hpp" -#include "asio/execution/set_error.hpp" -#include "asio/execution/set_value.hpp" -#include "asio/traits/set_done_member.hpp" -#include "asio/traits/set_error_member.hpp" -#include "asio/traits/set_value_member.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace execution { -namespace detail { - -template <typename Sender, typename Receiver> -struct submit_receiver; - -template <typename Sender, typename Receiver> -struct submit_receiver_wrapper -{ - submit_receiver<Sender, Receiver>* p_; - - explicit submit_receiver_wrapper(submit_receiver<Sender, Receiver>* p) - : p_(p) - { - } - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename... Args> - typename enable_if<is_receiver_of<Receiver, Args...>::value>::type - set_value(ASIO_MOVE_ARG(Args)... args) ASIO_RVALUE_REF_QUAL - ASIO_NOEXCEPT_IF((is_nothrow_receiver_of<Receiver, Args...>::value)) - { - execution::set_value( - ASIO_MOVE_OR_LVALUE( - typename remove_cvref<Receiver>::type)(p_->r_), - ASIO_MOVE_CAST(Args)(args)...); - delete p_; - } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - void set_value() ASIO_RVALUE_REF_QUAL - ASIO_NOEXCEPT_IF((is_nothrow_receiver_of<Receiver>::value)) - { - execution::set_value( - ASIO_MOVE_OR_LVALUE( - typename remove_cvref<Receiver>::type)(p_->r_)); - delete p_; - } - -#define ASIO_PRIVATE_SUBMIT_RECEIVER_SET_VALUE_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - typename enable_if<is_receiver_of<Receiver, \ - ASIO_VARIADIC_TARGS(n)>::value>::type \ - set_value(ASIO_VARIADIC_MOVE_PARAMS(n)) ASIO_RVALUE_REF_QUAL \ - ASIO_NOEXCEPT_IF((is_nothrow_receiver_of< \ - Receiver, ASIO_VARIADIC_TARGS(n)>::value)) \ - { \ - execution::set_value( \ - ASIO_MOVE_OR_LVALUE( \ - typename remove_cvref<Receiver>::type)(p_->r_), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - delete p_; \ - } \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SUBMIT_RECEIVER_SET_VALUE_DEF) -#undef ASIO_PRIVATE_SUBMIT_RECEIVER_SET_VALUE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename E> - void set_error(ASIO_MOVE_ARG(E) e) - ASIO_RVALUE_REF_QUAL ASIO_NOEXCEPT - { - execution::set_error( - ASIO_MOVE_OR_LVALUE( - typename remove_cvref<Receiver>::type)(p_->r_), - ASIO_MOVE_CAST(E)(e)); - delete p_; - } - - void set_done() ASIO_RVALUE_REF_QUAL ASIO_NOEXCEPT - { - execution::set_done( - ASIO_MOVE_OR_LVALUE( - typename remove_cvref<Receiver>::type)(p_->r_)); - delete p_; - } -}; - -template <typename Sender, typename Receiver> -struct submit_receiver -{ - typename remove_cvref<Receiver>::type r_; -#if defined(ASIO_HAS_MOVE) - typename connect_result<Sender, - submit_receiver_wrapper<Sender, Receiver> >::type state_; -#else // defined(ASIO_HAS_MOVE) - typename connect_result<Sender, - const submit_receiver_wrapper<Sender, Receiver>& >::type state_; -#endif // defined(ASIO_HAS_MOVE) - -#if defined(ASIO_HAS_MOVE) - template <typename S, typename R> - explicit submit_receiver(ASIO_MOVE_ARG(S) s, ASIO_MOVE_ARG(R) r) - : r_(ASIO_MOVE_CAST(R)(r)), - state_(execution::connect(ASIO_MOVE_CAST(S)(s), - submit_receiver_wrapper<Sender, Receiver>(this))) - { - } -#else // defined(ASIO_HAS_MOVE) - explicit submit_receiver(Sender s, Receiver r) - : r_(r), - state_(execution::connect(s, - submit_receiver_wrapper<Sender, Receiver>(this))) - { - } -#endif // defined(ASIO_HAS_MOVE) -}; - -} // namespace detail -} // namespace execution -namespace traits { - -#if !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename Sender, typename Receiver, typename... Args> -struct set_value_member< - asio::execution::detail::submit_receiver_wrapper< - Sender, Receiver>, - void(Args...)> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (asio::execution::is_nothrow_receiver_of<Receiver, Args...>::value)); - typedef void result_type; -}; - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename Sender, typename Receiver> -struct set_value_member< - asio::execution::detail::submit_receiver_wrapper< - Sender, Receiver>, - void()> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - asio::execution::is_nothrow_receiver_of<Receiver>::value); - typedef void result_type; -}; - -#define ASIO_PRIVATE_SUBMIT_RECEIVER_TRAIT_DEF(n) \ - template <typename Sender, typename Receiver, \ - ASIO_VARIADIC_TPARAMS(n)> \ - struct set_value_member< \ - asio::execution::detail::submit_receiver_wrapper< \ - Sender, Receiver>, \ - void(ASIO_VARIADIC_TARGS(n))> \ - { \ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); \ - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = \ - (asio::execution::is_nothrow_receiver_of<Receiver, \ - ASIO_VARIADIC_TARGS(n)>::value)); \ - typedef void result_type; \ - }; \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SUBMIT_RECEIVER_TRAIT_DEF) -#undef ASIO_PRIVATE_SUBMIT_RECEIVER_TRAIT_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#endif // !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - -#if !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - -template <typename Sender, typename Receiver, typename E> -struct set_error_member< - asio::execution::detail::submit_receiver_wrapper< - Sender, Receiver>, E> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - -#if !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - -template <typename Sender, typename Receiver> -struct set_done_member< - asio::execution::detail::submit_receiver_wrapper< - Sender, Receiver> > -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_DETAIL_SUBMIT_RECEIVER_HPP diff --git a/3rdparty/asio/include/asio/execution/detail/void_receiver.hpp b/3rdparty/asio/include/asio/execution/detail/void_receiver.hpp deleted file mode 100644 index fb2d53f58ee..00000000000 --- a/3rdparty/asio/include/asio/execution/detail/void_receiver.hpp +++ /dev/null @@ -1,90 +0,0 @@ -// -// execution/detail/void_receiver.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_DETAIL_VOID_RECEIVER_HPP -#define ASIO_EXECUTION_DETAIL_VOID_RECEIVER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/traits/set_done_member.hpp" -#include "asio/traits/set_error_member.hpp" -#include "asio/traits/set_value_member.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace execution { -namespace detail { - -struct void_receiver -{ - void set_value() ASIO_NOEXCEPT - { - } - - template <typename E> - void set_error(ASIO_MOVE_ARG(E)) ASIO_NOEXCEPT - { - } - - void set_done() ASIO_NOEXCEPT - { - } -}; - -} // namespace detail -} // namespace execution -namespace traits { - -#if !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - -template <> -struct set_value_member<asio::execution::detail::void_receiver, void()> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - -#if !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - -template <typename E> -struct set_error_member<asio::execution::detail::void_receiver, E> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - -#if !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - -template <> -struct set_done_member<asio::execution::detail::void_receiver> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef void result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_DETAIL_VOID_RECEIVER_HPP diff --git a/3rdparty/asio/include/asio/execution/execute.hpp b/3rdparty/asio/include/asio/execution/execute.hpp deleted file mode 100644 index 54eb31bebab..00000000000 --- a/3rdparty/asio/include/asio/execution/execute.hpp +++ /dev/null @@ -1,283 +0,0 @@ -// -// execution/execute.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_EXECUTE_HPP -#define ASIO_EXECUTION_EXECUTE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/detail/as_invocable.hpp" -#include "asio/execution/detail/as_receiver.hpp" -#include "asio/traits/execute_member.hpp" -#include "asio/traits/execute_free.hpp" - -#include "asio/detail/push_options.hpp" - -#if defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace execution { - -/// A customisation point that executes a function on an executor. -/** - * The name <tt>execution::execute</tt> denotes a customisation point object. - * - * For some subexpressions <tt>e</tt> and <tt>f</tt>, let <tt>E</tt> be a type - * such that <tt>decltype((e))</tt> is <tt>E</tt> and let <tt>F</tt> be a type - * such that <tt>decltype((f))</tt> is <tt>F</tt>. The expression - * <tt>execution::execute(e, f)</tt> is ill-formed if <tt>F</tt> does not model - * <tt>invocable</tt>, or if <tt>E</tt> does not model either <tt>executor</tt> - * or <tt>sender</tt>. Otherwise, it is expression-equivalent to: - * - * @li <tt>e.execute(f)</tt>, if that expression is valid. If the function - * selected does not execute the function object <tt>f</tt> on the executor - * <tt>e</tt>, the program is ill-formed with no diagnostic required. - * - * @li Otherwise, <tt>execute(e, f)</tt>, if that expression is valid, with - * overload resolution performed in a context that includes the declaration - * <tt>void execute();</tt> and that does not include a declaration of - * <tt>execution::execute</tt>. If the function selected by overload - * resolution does not execute the function object <tt>f</tt> on the executor - * <tt>e</tt>, the program is ill-formed with no diagnostic required. - */ -inline constexpr unspecified execute = unspecified; - -/// A type trait that determines whether a @c execute expression is well-formed. -/** - * Class template @c can_execute is a trait that is derived from - * @c true_type if the expression <tt>execution::execute(std::declval<T>(), - * std::declval<F>())</tt> is well formed; otherwise @c false_type. - */ -template <typename T, typename F> -struct can_execute : - integral_constant<bool, automatically_determined> -{ -}; - -} // namespace execution -} // namespace asio - -#else // defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace execution { - -template <typename T, typename R> -struct is_sender_to; - -namespace detail { - -template <typename S, typename R> -void submit_helper(ASIO_MOVE_ARG(S) s, ASIO_MOVE_ARG(R) r); - -} // namespace detail -} // namespace execution -} // namespace asio -namespace asio_execution_execute_fn { - -using asio::conditional; -using asio::decay; -using asio::declval; -using asio::enable_if; -using asio::execution::detail::as_receiver; -using asio::execution::detail::is_as_invocable; -using asio::execution::is_sender_to; -using asio::false_type; -using asio::result_of; -using asio::traits::execute_free; -using asio::traits::execute_member; -using asio::true_type; -using asio::void_type; - -void execute(); - -enum overload_type -{ - call_member, - call_free, - adapter, - ill_formed -}; - -template <typename Impl, typename T, typename F, typename = void, - typename = void, typename = void, typename = void, typename = void> -struct call_traits -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); -}; - -template <typename Impl, typename T, typename F> -struct call_traits<Impl, T, void(F), - typename enable_if< - execute_member<typename Impl::template proxy<T>::type, F>::is_valid - >::type> : - execute_member<typename Impl::template proxy<T>::type, F> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); -}; - -template <typename Impl, typename T, typename F> -struct call_traits<Impl, T, void(F), - typename enable_if< - !execute_member<typename Impl::template proxy<T>, F>::is_valid - >::type, - typename enable_if< - execute_free<T, F>::is_valid - >::type> : - execute_free<T, F> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); -}; - -template <typename Impl, typename T, typename F> -struct call_traits<Impl, T, void(F), - typename enable_if< - !execute_member<typename Impl::template proxy<T>::type, F>::is_valid - >::type, - typename enable_if< - !execute_free<T, F>::is_valid - >::type, - typename void_type< - typename result_of<typename decay<F>::type&()>::type - >::type, - typename enable_if< - !is_as_invocable<typename decay<F>::type>::value - >::type, - typename enable_if< - is_sender_to<T, as_receiver<typename decay<F>::type, T> >::value - >::type> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter); - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef void result_type; -}; - -struct impl -{ - template <typename T> - struct proxy - { -#if defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) - struct type - { - template <typename F> - auto execute(ASIO_MOVE_ARG(F) f) - noexcept( - noexcept( - declval<typename conditional<true, T, F>::type>().execute( - ASIO_MOVE_CAST(F)(f)) - ) - ) - -> decltype( - declval<typename conditional<true, T, F>::type>().execute( - ASIO_MOVE_CAST(F)(f)) - ); - }; -#else // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) - typedef T type; -#endif // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) - }; - - template <typename T, typename F> - ASIO_CONSTEXPR typename enable_if< - call_traits<impl, T, void(F)>::overload == call_member, - typename call_traits<impl, T, void(F)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(F) f) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(F)>::is_noexcept)) - { - return ASIO_MOVE_CAST(T)(t).execute(ASIO_MOVE_CAST(F)(f)); - } - - template <typename T, typename F> - ASIO_CONSTEXPR typename enable_if< - call_traits<impl, T, void(F)>::overload == call_free, - typename call_traits<impl, T, void(F)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(F) f) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(F)>::is_noexcept)) - { - return execute(ASIO_MOVE_CAST(T)(t), ASIO_MOVE_CAST(F)(f)); - } - - template <typename T, typename F> - ASIO_CONSTEXPR typename enable_if< - call_traits<impl, T, void(F)>::overload == adapter, - typename call_traits<impl, T, void(F)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(F) f) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(F)>::is_noexcept)) - { - return asio::execution::detail::submit_helper( - ASIO_MOVE_CAST(T)(t), - as_receiver<typename decay<F>::type, T>( - ASIO_MOVE_CAST(F)(f), 0)); - } -}; - -template <typename T = impl> -struct static_instance -{ - static const T instance; -}; - -template <typename T> -const T static_instance<T>::instance = {}; - -} // namespace asio_execution_execute_fn -namespace asio { -namespace execution { -namespace { - -static ASIO_CONSTEXPR const asio_execution_execute_fn::impl& - execute = asio_execution_execute_fn::static_instance<>::instance; - -} // namespace - -typedef asio_execution_execute_fn::impl execute_t; - -template <typename T, typename F> -struct can_execute : - integral_constant<bool, - asio_execution_execute_fn::call_traits< - execute_t, T, void(F)>::overload != - asio_execution_execute_fn::ill_formed> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename T, typename F> -constexpr bool can_execute_v = can_execute<T, F>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -} // namespace execution -} // namespace asio - -#endif // defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_EXECUTE_HPP diff --git a/3rdparty/asio/include/asio/execution/executor.hpp b/3rdparty/asio/include/asio/execution/executor.hpp index 7e05d5a0f8c..1f34981fa78 100644 --- a/3rdparty/asio/include/asio/execution/executor.hpp +++ b/3rdparty/asio/include/asio/execution/executor.hpp @@ -2,7 +2,7 @@ // execution/executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,16 +17,14 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/execution/execute.hpp" #include "asio/execution/invocable_archetype.hpp" #include "asio/traits/equality_comparable.hpp" +#include "asio/traits/execute_member.hpp" -#if defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT) \ - && defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) \ +#if defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) \ && defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) # define ASIO_HAS_DEDUCED_EXECUTION_IS_EXECUTOR_TRAIT 1 -#endif // defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT) - // && defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) +#endif // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) // && defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) #include "asio/detail/push_options.hpp" @@ -44,72 +42,33 @@ struct is_executor_of_impl : false_type template <typename T, typename F> struct is_executor_of_impl<T, F, - typename enable_if< - can_execute<typename add_const<T>::type, F>::value - >::type, - typename void_type< - typename result_of<typename decay<F>::type&()>::type - >::type, - typename enable_if< - is_constructible<typename decay<F>::type, F>::value - >::type, - typename enable_if< - is_move_constructible<typename decay<F>::type>::value - >::type, -#if defined(ASIO_HAS_NOEXCEPT) - typename enable_if< + enable_if_t< + traits::execute_member<add_const_t<T>, F>::is_valid + >, + void_t< + result_of_t<decay_t<F>&()> + >, + enable_if_t< + is_constructible<decay_t<F>, F>::value + >, + enable_if_t< + is_move_constructible<decay_t<F>>::value + >, + enable_if_t< is_nothrow_copy_constructible<T>::value - >::type, - typename enable_if< + >, + enable_if_t< is_nothrow_destructible<T>::value - >::type, -#else // defined(ASIO_HAS_NOEXCEPT) - typename enable_if< - is_copy_constructible<T>::value - >::type, - typename enable_if< - is_destructible<T>::value - >::type, -#endif // defined(ASIO_HAS_NOEXCEPT) - typename enable_if< + >, + enable_if_t< traits::equality_comparable<T>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< traits::equality_comparable<T>::is_noexcept - >::type> : true_type + >> : true_type { }; -template <typename T, typename = void> -struct executor_shape -{ - typedef std::size_t type; -}; - -template <typename T> -struct executor_shape<T, - typename void_type< - typename T::shape_type - >::type> -{ - typedef typename T::shape_type type; -}; - -template <typename T, typename Default, typename = void> -struct executor_index -{ - typedef Default type; -}; - -template <typename T, typename Default> -struct executor_index<T, Default, - typename void_type< - typename T::index_type - >::type> -{ - typedef typename T::index_type type; -}; - } // namespace detail /// The is_executor trait detects whether a type T satisfies the @@ -132,7 +91,7 @@ struct is_executor : #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> -ASIO_CONSTEXPR const bool is_executor_v = is_executor<T>::value; +constexpr const bool is_executor_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) @@ -149,101 +108,6 @@ ASIO_CONCEPT executor = is_executor<T>::value; #endif // defined(ASIO_HAS_CONCEPTS) -/// The is_executor_of trait detects whether a type T satisfies the -/// execution::executor_of concept for some set of value arguments. -/** - * Class template @c is_executor_of is a type trait that is derived from @c - * true_type if the type @c T meets the concept definition for an executor - * that is invocable with a function object of type @c F, otherwise @c - * false_type. - */ -template <typename T, typename F> -struct is_executor_of : -#if defined(GENERATING_DOCUMENTATION) - integral_constant<bool, automatically_determined> -#else // defined(GENERATING_DOCUMENTATION) - integral_constant<bool, - is_executor<T>::value && detail::is_executor_of_impl<T, F>::value - > -#endif // defined(GENERATING_DOCUMENTATION) -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename T, typename F> -ASIO_CONSTEXPR const bool is_executor_of_v = - is_executor_of<T, F>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -#if defined(ASIO_HAS_CONCEPTS) - -template <typename T, typename F> -ASIO_CONCEPT executor_of = is_executor_of<T, F>::value; - -#define ASIO_EXECUTION_EXECUTOR_OF(f) \ - ::asio::execution::executor_of<f> - -#else // defined(ASIO_HAS_CONCEPTS) - -#define ASIO_EXECUTION_EXECUTOR_OF typename - -#endif // defined(ASIO_HAS_CONCEPTS) - -/// The executor_shape trait detects the type used by an executor to represent -/// the shape of a bulk operation. -/** - * Class template @c executor_shape is a type trait with a nested type alias - * @c type whose type is @c T::shape_type if @c T::shape_type is valid, - * otherwise @c std::size_t. - */ -template <typename T> -struct executor_shape -#if !defined(GENERATING_DOCUMENTATION) - : detail::executor_shape<T> -#endif // !defined(GENERATING_DOCUMENTATION) -{ -#if defined(GENERATING_DOCUMENTATION) - /// @c T::shape_type if @c T::shape_type is valid, otherwise @c std::size_t. - typedef automatically_determined type; -#endif // defined(GENERATING_DOCUMENTATION) -}; - -#if defined(ASIO_HAS_ALIAS_TEMPLATES) - -template <typename T> -using executor_shape_t = typename executor_shape<T>::type; - -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - -/// The executor_index trait detects the type used by an executor to represent -/// an index within a bulk operation. -/** - * Class template @c executor_index is a type trait with a nested type alias - * @c type whose type is @c T::index_type if @c T::index_type is valid, - * otherwise @c executor_shape_t<T>. - */ -template <typename T> -struct executor_index -#if !defined(GENERATING_DOCUMENTATION) - : detail::executor_index<T, typename executor_shape<T>::type> -#endif // !defined(GENERATING_DOCUMENTATION) -{ -#if defined(GENERATING_DOCUMENTATION) - /// @c T::index_type if @c T::index_type is valid, otherwise - /// @c executor_shape_t<T>. - typedef automatically_determined type; -#endif // defined(GENERATING_DOCUMENTATION) -}; - -#if defined(ASIO_HAS_ALIAS_TEMPLATES) - -template <typename T> -using executor_index_t = typename executor_index<T>::type; - -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - } // namespace execution } // namespace asio diff --git a/3rdparty/asio/include/asio/execution/impl/bad_executor.ipp b/3rdparty/asio/include/asio/execution/impl/bad_executor.ipp index 7505e5c85c1..4e185acb059 100644 --- a/3rdparty/asio/include/asio/execution/impl/bad_executor.ipp +++ b/3rdparty/asio/include/asio/execution/impl/bad_executor.ipp @@ -2,7 +2,7 @@ // exection/impl/bad_executor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,11 +23,11 @@ namespace asio { namespace execution { -bad_executor::bad_executor() ASIO_NOEXCEPT +bad_executor::bad_executor() noexcept { } -const char* bad_executor::what() const ASIO_NOEXCEPT_OR_NOTHROW +const char* bad_executor::what() const noexcept { return "bad executor"; } diff --git a/3rdparty/asio/include/asio/execution/impl/receiver_invocation_error.ipp b/3rdparty/asio/include/asio/execution/impl/receiver_invocation_error.ipp deleted file mode 100644 index 5fd4e91191a..00000000000 --- a/3rdparty/asio/include/asio/execution/impl/receiver_invocation_error.ipp +++ /dev/null @@ -1,36 +0,0 @@ -// -// exection/impl/receiver_invocation_error.ipp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_IMPL_RECEIVER_INVOCATION_ERROR_IPP -#define ASIO_EXECUTION_IMPL_RECEIVER_INVOCATION_ERROR_IPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/execution/receiver_invocation_error.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace execution { - -receiver_invocation_error::receiver_invocation_error() - : std::runtime_error("receiver invocation error") -{ -} - -} // namespace execution -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_IMPL_RECEIVER_INVOCATION_ERROR_IPP diff --git a/3rdparty/asio/include/asio/execution/invocable_archetype.hpp b/3rdparty/asio/include/asio/execution/invocable_archetype.hpp index b141979caff..50223279e1f 100644 --- a/3rdparty/asio/include/asio/execution/invocable_archetype.hpp +++ b/3rdparty/asio/include/asio/execution/invocable_archetype.hpp @@ -2,7 +2,7 @@ // execution/invocable_archetype.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,7 +17,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" #include "asio/detail/push_options.hpp" @@ -28,38 +27,11 @@ namespace execution { /// execution::executor concept. struct invocable_archetype { -#if !defined(GENERATING_DOCUMENTATION) - // Necessary for compatibility with a C++03 implementation of result_of. - typedef void result_type; -#endif // !defined(GENERATING_DOCUMENTATION) - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \ - || defined(GENERATING_DOCUMENTATION) - /// Function call operator. template <typename... Args> - void operator()(ASIO_MOVE_ARG(Args)...) - { - } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - - void operator()() + void operator()(Args&&...) { } - -#define ASIO_PRIVATE_INVOCABLE_ARCHETYPE_CALL_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - void operator()(ASIO_VARIADIC_UNNAMED_MOVE_PARAMS(n)) \ - { \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INVOCABLE_ARCHETYPE_CALL_DEF) -#undef ASIO_PRIVATE_INVOCABLE_ARCHETYPE_CALL_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) }; } // namespace execution diff --git a/3rdparty/asio/include/asio/execution/mapping.hpp b/3rdparty/asio/include/asio/execution/mapping.hpp index 33924c81466..4c6e1791869 100644 --- a/3rdparty/asio/include/asio/execution/mapping.hpp +++ b/3rdparty/asio/include/asio/execution/mapping.hpp @@ -2,7 +2,7 @@ // execution/mapping.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,8 +18,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" #include "asio/is_applicable_property.hpp" #include "asio/query.hpp" #include "asio/traits/query_free.hpp" @@ -40,10 +38,9 @@ namespace execution { /// of execution agents on to threads of execution. struct mapping_t { - /// The mapping_t property applies to executors, senders, and schedulers. + /// The mapping_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The top-level mapping_t property cannot be required. static constexpr bool is_requirable = false; @@ -58,11 +55,9 @@ struct mapping_t /// threads of execution. struct thread_t { - /// The mapping_t::thread_t property applies to executors, senders, and - /// schedulers. + /// The mapping_t::thread_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The mapping_t::thread_t property can be required. static constexpr bool is_requirable = true; @@ -87,11 +82,9 @@ struct mapping_t /// new threads of execution. struct new_thread_t { - /// The mapping_t::new_thread_t property applies to executors, senders, and - /// schedulers. + /// The mapping_t::new_thread_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The mapping_t::new_thread_t property can be required. static constexpr bool is_requirable = true; @@ -116,11 +109,9 @@ struct mapping_t /// implementation-defined. struct other_t { - /// The mapping_t::other_t property applies to executors, senders, and - /// schedulers. + /// The mapping_t::other_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The mapping_t::other_t property can be required. static constexpr bool is_requirable = true; @@ -193,45 +184,33 @@ struct mapping_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); + static constexpr bool is_requirable = false; + static constexpr bool is_preferable = false; typedef mapping_t polymorphic_query_result_type; typedef detail::mapping::thread_t<I> thread_t; typedef detail::mapping::new_thread_t<I> new_thread_t; typedef detail::mapping::other_t<I> other_t; - ASIO_CONSTEXPR mapping_t() + constexpr mapping_t() : value_(-1) { } - ASIO_CONSTEXPR mapping_t(thread_t) + constexpr mapping_t(thread_t) : value_(0) { } - ASIO_CONSTEXPR mapping_t(new_thread_t) + constexpr mapping_t(new_thread_t) : value_(1) { } - ASIO_CONSTEXPR mapping_t(other_t) + constexpr mapping_t(other_t) : value_(2) { } @@ -243,16 +222,14 @@ struct mapping_t struct type { template <typename P> - auto query(ASIO_MOVE_ARG(P) p) const + auto query(P&& p) const noexcept( noexcept( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ) ) -> decltype( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ); }; #else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) @@ -267,17 +244,17 @@ struct mapping_t struct type { template <typename P> - static constexpr auto query(ASIO_MOVE_ARG(P) p) + static constexpr auto query(P&& p) noexcept( noexcept( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) ) -> decltype( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) { - return T::query(ASIO_MOVE_CAST(P)(p)); + return T::query(static_cast<P&&>(p)); } }; #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) @@ -297,88 +274,87 @@ struct mapping_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, thread_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, thread_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, thread_t>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, new_thread_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::static_query<T, thread_t>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, new_thread_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, new_thread_t>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, other_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::static_query<T, thread_t>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::static_query<T, new_thread_t>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, other_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, other_t>::value(); } template <typename E, typename T = decltype(mapping_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = mapping_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - friend ASIO_CONSTEXPR bool operator==( + friend constexpr bool operator==( const mapping_t& a, const mapping_t& b) { return a.value_ == b.value_; } - friend ASIO_CONSTEXPR bool operator!=( + friend constexpr bool operator!=( const mapping_t& a, const mapping_t& b) { return a.value_ != b.value_; @@ -386,22 +362,20 @@ struct mapping_t struct convertible_from_mapping_t { - ASIO_CONSTEXPR convertible_from_mapping_t(mapping_t) {} + constexpr convertible_from_mapping_t(mapping_t) {} }; template <typename Executor> - friend ASIO_CONSTEXPR mapping_t query( + friend constexpr mapping_t query( const Executor& ex, convertible_from_mapping_t, - typename enable_if< + enable_if_t< can_query<const Executor&, thread_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, mapping_t<>::thread_t>::value)) + noexcept(is_nothrow_query<const Executor&, mapping_t<>::thread_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, thread_t>::value)) + noexcept(is_nothrow_query<const Executor&, thread_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -409,21 +383,20 @@ struct mapping_t } template <typename Executor> - friend ASIO_CONSTEXPR mapping_t query( + friend constexpr mapping_t query( const Executor& ex, convertible_from_mapping_t, - typename enable_if< + enable_if_t< !can_query<const Executor&, thread_t>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< can_query<const Executor&, new_thread_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, mapping_t<>::new_thread_t>::value)) + noexcept( + is_nothrow_query<const Executor&, mapping_t<>::new_thread_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, new_thread_t>::value)) + noexcept(is_nothrow_query<const Executor&, new_thread_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -431,24 +404,22 @@ struct mapping_t } template <typename Executor> - friend ASIO_CONSTEXPR mapping_t query( + friend constexpr mapping_t query( const Executor& ex, convertible_from_mapping_t, - typename enable_if< + enable_if_t< !can_query<const Executor&, thread_t>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !can_query<const Executor&, new_thread_t>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< can_query<const Executor&, other_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, mapping_t<>::other_t>::value)) + noexcept(is_nothrow_query<const Executor&, mapping_t<>::other_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, other_t>::value)) + noexcept(is_nothrow_query<const Executor&, other_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -459,10 +430,6 @@ struct mapping_t ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(new_thread_t, new_thread); ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(other_t, other); -#if !defined(ASIO_HAS_CONSTEXPR) - static const mapping_t instance; -#endif // !defined(ASIO_HAS_CONSTEXPR) - private: int value_; }; @@ -474,11 +441,6 @@ const T mapping_t<I>::static_query_v; #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_CONSTEXPR) -template <int I> -const mapping_t<I> mapping_t<I>::instance; -#endif - template <int I> const typename mapping_t<I>::thread_t mapping_t<I>::thread; @@ -495,26 +457,14 @@ struct thread_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; typedef mapping_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR thread_t() + constexpr thread_t() { } @@ -531,58 +481,75 @@ struct thread_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename T> - static ASIO_CONSTEXPR thread_t static_query( - typename enable_if< + static constexpr thread_t static_query( + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::query_free<T, thread_t>::is_valid - >::type* = 0, - typename enable_if< - !can_query<T, new_thread_t<I> >::value - >::type* = 0, - typename enable_if< - !can_query<T, other_t<I> >::value - >::type* = 0) ASIO_NOEXCEPT + >* = 0, + enable_if_t< + !can_query<T, new_thread_t<I>>::value + >* = 0, + enable_if_t< + !can_query<T, other_t<I>>::value + >* = 0) noexcept { return thread_t(); } template <typename E, typename T = decltype(thread_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = thread_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR mapping_t<I> value() + static constexpr mapping_t<I> value() { return thread_t(); } - friend ASIO_CONSTEXPR bool operator==( - const thread_t&, const thread_t&) + friend constexpr bool operator==(const thread_t&, const thread_t&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( - const thread_t&, const thread_t&) + friend constexpr bool operator!=(const thread_t&, const thread_t&) + { + return false; + } + + friend constexpr bool operator==(const thread_t&, const new_thread_t<I>&) { return false; } + + friend constexpr bool operator!=(const thread_t&, const new_thread_t<I>&) + { + return true; + } + + friend constexpr bool operator==(const thread_t&, const other_t<I>&) + { + return false; + } + + friend constexpr bool operator!=(const thread_t&, const other_t<I>&) + { + return true; + } }; #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ @@ -597,26 +564,14 @@ struct new_thread_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; typedef mapping_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR new_thread_t() + constexpr new_thread_t() { } @@ -633,37 +588,52 @@ struct new_thread_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(new_thread_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = new_thread_t::static_query<E>(); + static constexpr const T static_query_v = new_thread_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR mapping_t<I> value() + static constexpr mapping_t<I> value() { return new_thread_t(); } - friend ASIO_CONSTEXPR bool operator==( - const new_thread_t&, const new_thread_t&) + friend constexpr bool operator==(const new_thread_t&, const new_thread_t&) + { + return true; + } + + friend constexpr bool operator!=(const new_thread_t&, const new_thread_t&) + { + return false; + } + + friend constexpr bool operator==(const new_thread_t&, const thread_t<I>&) + { + return false; + } + + friend constexpr bool operator!=(const new_thread_t&, const thread_t<I>&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( - const new_thread_t&, const new_thread_t&) + friend constexpr bool operator==(const new_thread_t&, const other_t<I>&) { return false; } + + friend constexpr bool operator!=(const new_thread_t&, const other_t<I>&) + { + return true; + } }; #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ @@ -678,26 +648,14 @@ struct other_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; typedef mapping_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR other_t() + constexpr other_t() { } @@ -714,37 +672,53 @@ struct other_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(other_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = other_t::static_query<E>(); + static constexpr const T static_query_v = other_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR mapping_t<I> value() + static constexpr mapping_t<I> value() { return other_t(); } - friend ASIO_CONSTEXPR bool operator==( - const other_t&, const other_t&) + friend constexpr bool operator==(const other_t&, const other_t&) + { + return true; + } + + friend constexpr bool operator!=(const other_t&, const other_t&) + { + return false; + } + + friend constexpr bool operator==(const other_t&, const thread_t<I>&) + { + return false; + } + + friend constexpr bool operator!=(const other_t&, const thread_t<I>&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( - const other_t&, const other_t&) + friend constexpr bool operator==(const other_t&, const new_thread_t<I>&) { return false; } + + friend constexpr bool operator!=(const other_t&, const new_thread_t<I>&) + { + return true; + } }; #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ @@ -759,11 +733,7 @@ const T other_t<I>::static_query_v; typedef detail::mapping_t<> mapping_t; -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr mapping_t mapping; -#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -namespace { static const mapping_t& mapping = mapping_t::instance; } -#endif } // namespace execution @@ -771,69 +741,25 @@ namespace { static const mapping_t& mapping = mapping_t::instance; } template <typename T> struct is_applicable_property<T, execution::mapping_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::mapping_t::thread_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::mapping_t::new_thread_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::mapping_t::other_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; @@ -845,42 +771,42 @@ namespace traits { template <typename T> struct query_free_default<T, execution::mapping_t, - typename enable_if< + enable_if_t< can_query<T, execution::mapping_t::thread_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::mapping_t::thread_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::mapping_t::thread_t>::value; typedef execution::mapping_t result_type; }; template <typename T> struct query_free_default<T, execution::mapping_t, - typename enable_if< + enable_if_t< !can_query<T, execution::mapping_t::thread_t>::value && can_query<T, execution::mapping_t::new_thread_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::mapping_t::new_thread_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::mapping_t::new_thread_t>::value; typedef execution::mapping_t result_type; }; template <typename T> struct query_free_default<T, execution::mapping_t, - typename enable_if< + enable_if_t< !can_query<T, execution::mapping_t::thread_t>::value && !can_query<T, execution::mapping_t::new_thread_t>::value && can_query<T, execution::mapping_t::other_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::mapping_t::other_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::mapping_t::other_t>::value; typedef execution::mapping_t result_type; }; @@ -892,18 +818,18 @@ struct query_free_default<T, execution::mapping_t, template <typename T> struct static_query<T, execution::mapping_t, - typename enable_if< + enable_if_t< execution::detail::mapping_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::mapping_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::mapping_t<0>:: query_static_constexpr_member<T>::value(); @@ -912,21 +838,21 @@ struct static_query<T, execution::mapping_t, template <typename T> struct static_query<T, execution::mapping_t, - typename enable_if< + enable_if_t< !execution::detail::mapping_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::mapping_t<0>:: query_member<T>::is_valid && traits::static_query<T, execution::mapping_t::thread_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::mapping_t::thread_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::mapping_t::thread_t>::value(); } @@ -934,22 +860,22 @@ struct static_query<T, execution::mapping_t, template <typename T> struct static_query<T, execution::mapping_t, - typename enable_if< + enable_if_t< !execution::detail::mapping_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::mapping_t<0>:: query_member<T>::is_valid && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid && traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::mapping_t::new_thread_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::mapping_t::new_thread_t>::value(); } @@ -957,7 +883,7 @@ struct static_query<T, execution::mapping_t, template <typename T> struct static_query<T, execution::mapping_t, - typename enable_if< + enable_if_t< !execution::detail::mapping_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::mapping_t<0>:: @@ -965,15 +891,15 @@ struct static_query<T, execution::mapping_t, && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid && !traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid && traits::static_query<T, execution::mapping_t::other_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::mapping_t::other_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::mapping_t::other_t>::value(); } @@ -981,18 +907,18 @@ struct static_query<T, execution::mapping_t, template <typename T> struct static_query<T, execution::mapping_t::thread_t, - typename enable_if< + enable_if_t< execution::detail::mapping::thread_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::mapping::thread_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::mapping::thread_t<0>:: query_static_constexpr_member<T>::value(); @@ -1001,7 +927,7 @@ struct static_query<T, execution::mapping_t::thread_t, template <typename T> struct static_query<T, execution::mapping_t::thread_t, - typename enable_if< + enable_if_t< !execution::detail::mapping::thread_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::mapping::thread_t<0>:: @@ -1009,14 +935,14 @@ struct static_query<T, execution::mapping_t::thread_t, && !traits::query_free<T, execution::mapping_t::thread_t>::is_valid && !can_query<T, execution::mapping_t::new_thread_t>::value && !can_query<T, execution::mapping_t::other_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::mapping_t::thread_t result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return result_type(); } @@ -1024,18 +950,18 @@ struct static_query<T, execution::mapping_t::thread_t, template <typename T> struct static_query<T, execution::mapping_t::new_thread_t, - typename enable_if< + enable_if_t< execution::detail::mapping::new_thread_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::mapping::new_thread_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::mapping::new_thread_t<0>:: query_static_constexpr_member<T>::value(); @@ -1044,18 +970,18 @@ struct static_query<T, execution::mapping_t::new_thread_t, template <typename T> struct static_query<T, execution::mapping_t::other_t, - typename enable_if< + enable_if_t< execution::detail::mapping::other_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::mapping::other_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::mapping::other_t<0>:: query_static_constexpr_member<T>::value(); @@ -1065,46 +991,6 @@ struct static_query<T, execution::mapping_t::other_t, #endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - -template <typename T> -struct static_require<T, execution::mapping_t::thread_t, - typename enable_if< - static_query<T, execution::mapping_t::thread_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::mapping_t::thread_t>::result_type, - execution::mapping_t::thread_t>::value)); -}; - -template <typename T> -struct static_require<T, execution::mapping_t::new_thread_t, - typename enable_if< - static_query<T, execution::mapping_t::new_thread_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::mapping_t::new_thread_t>::result_type, - execution::mapping_t::new_thread_t>::value)); -}; - -template <typename T> -struct static_require<T, execution::mapping_t::other_t, - typename enable_if< - static_query<T, execution::mapping_t::other_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::mapping_t::other_t>::result_type, - execution::mapping_t::other_t>::value)); -}; - -#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - } // namespace traits #endif // defined(GENERATING_DOCUMENTATION) diff --git a/3rdparty/asio/include/asio/execution/occupancy.hpp b/3rdparty/asio/include/asio/execution/occupancy.hpp index e1842a46ab0..c986c88113d 100644 --- a/3rdparty/asio/include/asio/execution/occupancy.hpp +++ b/3rdparty/asio/include/asio/execution/occupancy.hpp @@ -2,7 +2,7 @@ // execution/occupancy.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,8 +18,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" #include "asio/is_applicable_property.hpp" #include "asio/traits/query_static_constexpr_member.hpp" #include "asio/traits/static_query.hpp" @@ -36,10 +34,9 @@ namespace execution { /// should occupy the associated execution context. struct occupancy_t { - /// The occupancy_t property applies to executors, senders, and schedulers. + /// The occupancy_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The occupancy_t property cannot be required. static constexpr bool is_requirable = false; @@ -66,26 +63,14 @@ struct occupancy_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); + static constexpr bool is_requirable = false; + static constexpr bool is_preferable = false; typedef std::size_t polymorphic_query_result_type; - ASIO_CONSTEXPR occupancy_t() + constexpr occupancy_t() { } @@ -96,17 +81,17 @@ struct occupancy_t struct type { template <typename P> - static constexpr auto query(ASIO_MOVE_ARG(P) p) + static constexpr auto query(P&& p) noexcept( noexcept( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) ) -> decltype( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) { - return T::query(ASIO_MOVE_CAST(P)(p)); + return T::query(static_cast<P&&>(p)); } }; #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) @@ -122,24 +107,17 @@ struct occupancy_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(occupancy_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = occupancy_t::static_query<E>(); + static constexpr const T static_query_v = occupancy_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - -#if !defined(ASIO_HAS_CONSTEXPR) - static const occupancy_t instance; -#endif // !defined(ASIO_HAS_CONSTEXPR) }; #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ @@ -149,20 +127,11 @@ const T occupancy_t<I>::static_query_v; #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_CONSTEXPR) -template <int I> -const occupancy_t<I> occupancy_t<I>::instance; -#endif - } // namespace detail typedef detail::occupancy_t<> occupancy_t; -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr occupancy_t occupancy; -#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -namespace { static const occupancy_t& occupancy = occupancy_t::instance; } -#endif } // namespace execution @@ -170,18 +139,7 @@ namespace { static const occupancy_t& occupancy = occupancy_t::instance; } template <typename T> struct is_applicable_property<T, execution::occupancy_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; @@ -194,18 +152,18 @@ namespace traits { template <typename T> struct static_query<T, execution::occupancy_t, - typename enable_if< + enable_if_t< execution::detail::occupancy_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::occupancy_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::occupancy_t<0>:: query_static_constexpr_member<T>::value(); diff --git a/3rdparty/asio/include/asio/execution/operation_state.hpp b/3rdparty/asio/include/asio/execution/operation_state.hpp deleted file mode 100644 index 8fb7a94b8ca..00000000000 --- a/3rdparty/asio/include/asio/execution/operation_state.hpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// execution/operation_state.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_OPERATION_STATE_HPP -#define ASIO_EXECUTION_OPERATION_STATE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/start.hpp" - -#if defined(ASIO_HAS_DEDUCED_START_FREE_TRAIT) \ - && defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT) -# define ASIO_HAS_DEDUCED_EXECUTION_IS_OPERATION_STATE_TRAIT 1 -#endif // defined(ASIO_HAS_DEDUCED_START_FREE_TRAIT) - // && defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace execution { -namespace detail { - -template <typename T> -struct is_operation_state_base : - integral_constant<bool, - is_destructible<T>::value - && is_object<T>::value - > -{ -}; - -} // namespace detail - -/// The is_operation_state trait detects whether a type T satisfies the -/// execution::operation_state concept. -/** - * Class template @c is_operation_state is a type trait that is derived from - * @c true_type if the type @c T meets the concept definition for an - * @c operation_state, otherwise @c false_type. - */ -template <typename T> -struct is_operation_state : -#if defined(GENERATING_DOCUMENTATION) - integral_constant<bool, automatically_determined> -#else // defined(GENERATING_DOCUMENTATION) - conditional< - can_start<typename add_lvalue_reference<T>::type>::value - && is_nothrow_start<typename add_lvalue_reference<T>::type>::value, - detail::is_operation_state_base<T>, - false_type - >::type -#endif // defined(GENERATING_DOCUMENTATION) -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename T> -ASIO_CONSTEXPR const bool is_operation_state_v = - is_operation_state<T>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -#if defined(ASIO_HAS_CONCEPTS) - -template <typename T> -ASIO_CONCEPT operation_state = is_operation_state<T>::value; - -#define ASIO_EXECUTION_OPERATION_STATE \ - ::asio::execution::operation_state - -#else // defined(ASIO_HAS_CONCEPTS) - -#define ASIO_EXECUTION_OPERATION_STATE typename - -#endif // defined(ASIO_HAS_CONCEPTS) - -} // namespace execution -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_OPERATION_STATE_HPP diff --git a/3rdparty/asio/include/asio/execution/outstanding_work.hpp b/3rdparty/asio/include/asio/execution/outstanding_work.hpp index 48ed71d1563..600792b95b4 100644 --- a/3rdparty/asio/include/asio/execution/outstanding_work.hpp +++ b/3rdparty/asio/include/asio/execution/outstanding_work.hpp @@ -2,7 +2,7 @@ // execution/outstanding_work.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,8 +18,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" #include "asio/is_applicable_property.hpp" #include "asio/query.hpp" #include "asio/traits/query_free.hpp" @@ -39,11 +37,9 @@ namespace execution { /// A property to describe whether task submission is likely in the future. struct outstanding_work_t { - /// The outstanding_work_t property applies to executors, senders, and - /// schedulers. + /// The outstanding_work_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The top-level outstanding_work_t property cannot be required. static constexpr bool is_requirable = false; @@ -58,11 +54,9 @@ struct outstanding_work_t /// future submission of a function object. struct untracked_t { - /// The outstanding_work_t::untracked_t property applies to executors, - /// senders, and schedulers. + /// The outstanding_work_t::untracked_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The outstanding_work_t::untracked_t property can be required. static constexpr bool is_requirable = true; @@ -87,11 +81,9 @@ struct outstanding_work_t /// future submission of a function object. struct tracked_t { - /// The outstanding_work_t::untracked_t property applies to executors, - /// senders, and schedulers. + /// The outstanding_work_t::untracked_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The outstanding_work_t::tracked_t property can be required. static constexpr bool is_requirable = true; @@ -159,39 +151,27 @@ struct outstanding_work_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); + static constexpr bool is_requirable = false; + static constexpr bool is_preferable = false; typedef outstanding_work_t polymorphic_query_result_type; typedef detail::outstanding_work::untracked_t<I> untracked_t; typedef detail::outstanding_work::tracked_t<I> tracked_t; - ASIO_CONSTEXPR outstanding_work_t() + constexpr outstanding_work_t() : value_(-1) { } - ASIO_CONSTEXPR outstanding_work_t(untracked_t) + constexpr outstanding_work_t(untracked_t) : value_(0) { } - ASIO_CONSTEXPR outstanding_work_t(tracked_t) + constexpr outstanding_work_t(tracked_t) : value_(1) { } @@ -203,16 +183,14 @@ struct outstanding_work_t struct type { template <typename P> - auto query(ASIO_MOVE_ARG(P) p) const + auto query(P&& p) const noexcept( noexcept( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ) ) -> decltype( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ); }; #else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) @@ -227,17 +205,17 @@ struct outstanding_work_t struct type { template <typename P> - static constexpr auto query(ASIO_MOVE_ARG(P) p) + static constexpr auto query(P&& p) noexcept( noexcept( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) ) -> decltype( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) { - return T::query(ASIO_MOVE_CAST(P)(p)); + return T::query(static_cast<P&&>(p)); } }; #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) @@ -257,66 +235,65 @@ struct outstanding_work_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, untracked_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, untracked_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, untracked_t>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, tracked_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::static_query<T, untracked_t>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, tracked_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, tracked_t>::value(); } template <typename E, typename T = decltype(outstanding_work_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = outstanding_work_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - friend ASIO_CONSTEXPR bool operator==( + friend constexpr bool operator==( const outstanding_work_t& a, const outstanding_work_t& b) { return a.value_ == b.value_; } - friend ASIO_CONSTEXPR bool operator!=( + friend constexpr bool operator!=( const outstanding_work_t& a, const outstanding_work_t& b) { return a.value_ != b.value_; @@ -324,25 +301,23 @@ struct outstanding_work_t struct convertible_from_outstanding_work_t { - ASIO_CONSTEXPR convertible_from_outstanding_work_t(outstanding_work_t) + constexpr convertible_from_outstanding_work_t(outstanding_work_t) { } }; template <typename Executor> - friend ASIO_CONSTEXPR outstanding_work_t query( + friend constexpr outstanding_work_t query( const Executor& ex, convertible_from_outstanding_work_t, - typename enable_if< + enable_if_t< can_query<const Executor&, untracked_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, - outstanding_work_t<>::untracked_t>::value)) + noexcept(is_nothrow_query<const Executor&, + outstanding_work_t<>::untracked_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, untracked_t>::value)) + noexcept(is_nothrow_query<const Executor&, untracked_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -350,22 +325,20 @@ struct outstanding_work_t } template <typename Executor> - friend ASIO_CONSTEXPR outstanding_work_t query( + friend constexpr outstanding_work_t query( const Executor& ex, convertible_from_outstanding_work_t, - typename enable_if< + enable_if_t< !can_query<const Executor&, untracked_t>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< can_query<const Executor&, tracked_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, - outstanding_work_t<>::tracked_t>::value)) + noexcept(is_nothrow_query<const Executor&, + outstanding_work_t<>::tracked_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, tracked_t>::value)) + noexcept(is_nothrow_query<const Executor&, tracked_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -375,10 +348,6 @@ struct outstanding_work_t ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(untracked_t, untracked); ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(tracked_t, tracked); -#if !defined(ASIO_HAS_CONSTEXPR) - static const outstanding_work_t instance; -#endif // !defined(ASIO_HAS_CONSTEXPR) - private: int value_; }; @@ -390,11 +359,6 @@ const T outstanding_work_t<I>::static_query_v; #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_CONSTEXPR) -template <int I> -const outstanding_work_t<I> outstanding_work_t<I>::instance; -#endif - template <int I> const typename outstanding_work_t<I>::untracked_t outstanding_work_t<I>::untracked; @@ -410,26 +374,14 @@ struct untracked_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; typedef outstanding_work_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR untracked_t() + constexpr untracked_t() { } @@ -447,55 +399,61 @@ struct untracked_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename T> - static ASIO_CONSTEXPR untracked_t static_query( - typename enable_if< + static constexpr untracked_t static_query( + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::query_free<T, untracked_t>::is_valid - >::type* = 0, - typename enable_if< - !can_query<T, tracked_t<I> >::value - >::type* = 0) ASIO_NOEXCEPT + >* = 0, + enable_if_t< + !can_query<T, tracked_t<I>>::value + >* = 0) noexcept { return untracked_t(); } template <typename E, typename T = decltype(untracked_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = untracked_t::static_query<E>(); + static constexpr const T static_query_v = untracked_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR outstanding_work_t<I> value() + static constexpr outstanding_work_t<I> value() { return untracked_t(); } - friend ASIO_CONSTEXPR bool operator==( - const untracked_t&, const untracked_t&) + friend constexpr bool operator==(const untracked_t&, const untracked_t&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( - const untracked_t&, const untracked_t&) + friend constexpr bool operator!=(const untracked_t&, const untracked_t&) { return false; } + + friend constexpr bool operator==(const untracked_t&, const tracked_t<I>&) + { + return false; + } + + friend constexpr bool operator!=(const untracked_t&, const tracked_t<I>&) + { + return true; + } }; #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ @@ -510,26 +468,14 @@ struct tracked_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; typedef outstanding_work_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR tracked_t() + constexpr tracked_t() { } @@ -547,37 +493,43 @@ struct tracked_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(tracked_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v - = tracked_t::static_query<E>(); + static constexpr const T static_query_v = tracked_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR outstanding_work_t<I> value() + static constexpr outstanding_work_t<I> value() { return tracked_t(); } - friend ASIO_CONSTEXPR bool operator==( - const tracked_t&, const tracked_t&) + friend constexpr bool operator==(const tracked_t&, const tracked_t&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( - const tracked_t&, const tracked_t&) + friend constexpr bool operator!=(const tracked_t&, const tracked_t&) { return false; } + + friend constexpr bool operator==(const tracked_t&, const untracked_t<I>&) + { + return false; + } + + friend constexpr bool operator!=(const tracked_t&, const untracked_t<I>&) + { + return true; + } }; #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ @@ -592,12 +544,7 @@ const T tracked_t<I>::static_query_v; typedef detail::outstanding_work_t<> outstanding_work_t; -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr outstanding_work_t outstanding_work; -#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -namespace { static const outstanding_work_t& - outstanding_work = outstanding_work_t::instance; } -#endif } // namespace execution @@ -605,52 +552,19 @@ namespace { static const outstanding_work_t& template <typename T> struct is_applicable_property<T, execution::outstanding_work_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::outstanding_work_t::untracked_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::outstanding_work_t::tracked_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; @@ -662,27 +576,27 @@ namespace traits { template <typename T> struct query_free_default<T, execution::outstanding_work_t, - typename enable_if< + enable_if_t< can_query<T, execution::outstanding_work_t::untracked_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::outstanding_work_t::untracked_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::outstanding_work_t::untracked_t>::value; typedef execution::outstanding_work_t result_type; }; template <typename T> struct query_free_default<T, execution::outstanding_work_t, - typename enable_if< + enable_if_t< !can_query<T, execution::outstanding_work_t::untracked_t>::value && can_query<T, execution::outstanding_work_t::tracked_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::outstanding_work_t::tracked_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::outstanding_work_t::tracked_t>::value; typedef execution::outstanding_work_t result_type; }; @@ -694,18 +608,18 @@ struct query_free_default<T, execution::outstanding_work_t, template <typename T> struct static_query<T, execution::outstanding_work_t, - typename enable_if< + enable_if_t< execution::detail::outstanding_work_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::outstanding_work_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::outstanding_work_t<0>:: query_static_constexpr_member<T>::value(); @@ -714,22 +628,22 @@ struct static_query<T, execution::outstanding_work_t, template <typename T> struct static_query<T, execution::outstanding_work_t, - typename enable_if< + enable_if_t< !execution::detail::outstanding_work_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::outstanding_work_t<0>:: query_member<T>::is_valid && traits::static_query<T, execution::outstanding_work_t::untracked_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::outstanding_work_t::untracked_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::outstanding_work_t::untracked_t>::value(); @@ -738,7 +652,7 @@ struct static_query<T, execution::outstanding_work_t, template <typename T> struct static_query<T, execution::outstanding_work_t, - typename enable_if< + enable_if_t< !execution::detail::outstanding_work_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::outstanding_work_t<0>:: @@ -747,15 +661,15 @@ struct static_query<T, execution::outstanding_work_t, execution::outstanding_work_t::untracked_t>::is_valid && traits::static_query<T, execution::outstanding_work_t::tracked_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::outstanding_work_t::tracked_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::outstanding_work_t::tracked_t>::value(); @@ -764,18 +678,18 @@ struct static_query<T, execution::outstanding_work_t, template <typename T> struct static_query<T, execution::outstanding_work_t::untracked_t, - typename enable_if< + enable_if_t< execution::detail::outstanding_work::untracked_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::outstanding_work::untracked_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::outstanding_work::untracked_t<0>:: query_static_constexpr_member<T>::value(); @@ -784,7 +698,7 @@ struct static_query<T, execution::outstanding_work_t::untracked_t, template <typename T> struct static_query<T, execution::outstanding_work_t::untracked_t, - typename enable_if< + enable_if_t< !execution::detail::outstanding_work::untracked_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::outstanding_work::untracked_t<0>:: @@ -792,14 +706,14 @@ struct static_query<T, execution::outstanding_work_t::untracked_t, && !traits::query_free<T, execution::outstanding_work_t::untracked_t>::is_valid && !can_query<T, execution::outstanding_work_t::tracked_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::outstanding_work_t::untracked_t result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return result_type(); } @@ -807,18 +721,18 @@ struct static_query<T, execution::outstanding_work_t::untracked_t, template <typename T> struct static_query<T, execution::outstanding_work_t::tracked_t, - typename enable_if< + enable_if_t< execution::detail::outstanding_work::tracked_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::outstanding_work::tracked_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::outstanding_work::tracked_t<0>:: query_static_constexpr_member<T>::value(); @@ -828,34 +742,6 @@ struct static_query<T, execution::outstanding_work_t::tracked_t, #endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - -template <typename T> -struct static_require<T, execution::outstanding_work_t::untracked_t, - typename enable_if< - static_query<T, execution::outstanding_work_t::untracked_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::outstanding_work_t::untracked_t>::result_type, - execution::outstanding_work_t::untracked_t>::value)); -}; - -template <typename T> -struct static_require<T, execution::outstanding_work_t::tracked_t, - typename enable_if< - static_query<T, execution::outstanding_work_t::tracked_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::outstanding_work_t::tracked_t>::result_type, - execution::outstanding_work_t::tracked_t>::value)); -}; - -#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - } // namespace traits #endif // defined(GENERATING_DOCUMENTATION) diff --git a/3rdparty/asio/include/asio/execution/prefer_only.hpp b/3rdparty/asio/include/asio/execution/prefer_only.hpp index e608a7707db..1a990ebf392 100644 --- a/3rdparty/asio/include/asio/execution/prefer_only.hpp +++ b/3rdparty/asio/include/asio/execution/prefer_only.hpp @@ -2,7 +2,7 @@ // execution/prefer_only.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -65,16 +65,17 @@ namespace detail { template <typename InnerProperty, typename = void> struct prefer_only_is_preferable { - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); + static constexpr bool is_preferable = false; }; template <typename InnerProperty> struct prefer_only_is_preferable<InnerProperty, - typename enable_if< + enable_if_t< InnerProperty::is_preferable - >::type> + > + > { - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_preferable = true; }; template <typename InnerProperty, typename = void> @@ -84,9 +85,10 @@ struct prefer_only_polymorphic_query_result_type template <typename InnerProperty> struct prefer_only_polymorphic_query_result_type<InnerProperty, - typename void_type< + void_t< typename InnerProperty::polymorphic_query_result_type - >::type> + > + > { typedef typename InnerProperty::polymorphic_query_result_type polymorphic_query_result_type; @@ -103,14 +105,14 @@ struct prefer_only_property } }; -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) template <typename InnerProperty> struct prefer_only_property<InnerProperty, - typename void_type< + void_t< decltype(asio::declval<const InnerProperty>().value()) - >::type> + > + > { InnerProperty property; @@ -119,17 +121,15 @@ struct prefer_only_property<InnerProperty, { } - ASIO_CONSTEXPR auto value() const - ASIO_NOEXCEPT_IF(( - noexcept(asio::declval<const InnerProperty>().value()))) + constexpr auto value() const + noexcept(noexcept(asio::declval<const InnerProperty>().value())) -> decltype(asio::declval<const InnerProperty>().value()) { return property.value(); } }; -#else // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#else // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) struct prefer_only_memfns_base { @@ -158,11 +158,12 @@ char prefer_only_value_memfn_helper( template <typename InnerProperty> struct prefer_only_property<InnerProperty, - typename enable_if< + enable_if_t< sizeof(prefer_only_value_memfn_helper<InnerProperty>(0)) != 1 && !is_same<typename InnerProperty::polymorphic_query_result_type, void>::value - >::type> + > + > { InnerProperty property; @@ -171,15 +172,14 @@ struct prefer_only_property<InnerProperty, { } - ASIO_CONSTEXPR typename InnerProperty::polymorphic_query_result_type + constexpr typename InnerProperty::polymorphic_query_result_type value() const { return property.value(); } }; -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) } // namespace detail @@ -189,9 +189,9 @@ struct prefer_only : detail::prefer_only_polymorphic_query_result_type<InnerProperty>, detail::prefer_only_property<InnerProperty> { - ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); + static constexpr bool is_requirable = false; - ASIO_CONSTEXPR prefer_only(const InnerProperty& p) + constexpr prefer_only(const InnerProperty& p) : detail::prefer_only_property<InnerProperty>(p) { } @@ -199,35 +199,33 @@ struct prefer_only : #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, InnerProperty>::result_type static_query() - ASIO_NOEXCEPT_IF(( - traits::static_query<T, InnerProperty>::is_noexcept)) + noexcept(traits::static_query<T, InnerProperty>::is_noexcept) { return traits::static_query<T, InnerProperty>::value(); } template <typename E, typename T = decltype(prefer_only::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = prefer_only::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename Executor, typename Property> - friend ASIO_CONSTEXPR - typename prefer_result<const Executor&, const InnerProperty&>::type + friend constexpr + prefer_result_t<const Executor&, const InnerProperty&> prefer(const Executor& ex, const prefer_only<Property>& p, - typename enable_if< + enable_if_t< is_same<Property, InnerProperty>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< can_prefer<const Executor&, const InnerProperty&>::value - >::type* = 0) + >* = 0) #if !defined(ASIO_MSVC) \ && !defined(__clang__) // Clang crashes if noexcept is used here. - ASIO_NOEXCEPT_IF(( - is_nothrow_prefer<const Executor&, const InnerProperty&>::value)) + noexcept(is_nothrow_prefer<const Executor&, const InnerProperty&>::value) #endif // !defined(ASIO_MSVC) // && !defined(__clang__) { @@ -235,19 +233,18 @@ struct prefer_only : } template <typename Executor, typename Property> - friend ASIO_CONSTEXPR - typename query_result<const Executor&, const InnerProperty&>::type + friend constexpr + query_result_t<const Executor&, const InnerProperty&> query(const Executor& ex, const prefer_only<Property>& p, - typename enable_if< + enable_if_t< is_same<Property, InnerProperty>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< can_query<const Executor&, const InnerProperty&>::value - >::type* = 0) + >* = 0) #if !defined(ASIO_MSVC) \ && !defined(__clang__) // Clang crashes if noexcept is used here. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, const InnerProperty&>::value)) + noexcept(is_nothrow_query<const Executor&, const InnerProperty&>::value) #endif // !defined(ASIO_MSVC) // && !defined(__clang__) { @@ -265,7 +262,7 @@ const T prefer_only<InnerProperty>::static_query_v; } // namespace execution template <typename T, typename InnerProperty> -struct is_applicable_property<T, execution::prefer_only<InnerProperty> > +struct is_applicable_property<T, execution::prefer_only<InnerProperty>> : is_applicable_property<T, InnerProperty> { }; @@ -276,7 +273,7 @@ namespace traits { || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T, typename InnerProperty> -struct static_query<T, execution::prefer_only<InnerProperty> > : +struct static_query<T, execution::prefer_only<InnerProperty>> : static_query<T, const InnerProperty&> { }; @@ -288,16 +285,16 @@ struct static_query<T, execution::prefer_only<InnerProperty> > : template <typename T, typename InnerProperty> struct prefer_free_default<T, execution::prefer_only<InnerProperty>, - typename enable_if< + enable_if_t< can_prefer<const T&, const InnerProperty&>::value - >::type> + > + > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_prefer<const T&, const InnerProperty&>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_prefer<const T&, const InnerProperty&>::value; - typedef typename prefer_result<const T&, - const InnerProperty&>::type result_type; + typedef prefer_result_t<const T&, const InnerProperty&> result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) @@ -306,16 +303,16 @@ struct prefer_free_default<T, execution::prefer_only<InnerProperty>, template <typename T, typename InnerProperty> struct query_free<T, execution::prefer_only<InnerProperty>, - typename enable_if< + enable_if_t< can_query<const T&, const InnerProperty&>::value - >::type> + > + > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<const T&, const InnerProperty&>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<const T&, const InnerProperty&>::value; - typedef typename query_result<const T&, - const InnerProperty&>::type result_type; + typedef query_result_t<const T&, const InnerProperty&> result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) diff --git a/3rdparty/asio/include/asio/execution/receiver.hpp b/3rdparty/asio/include/asio/execution/receiver.hpp deleted file mode 100644 index 4f205aa5240..00000000000 --- a/3rdparty/asio/include/asio/execution/receiver.hpp +++ /dev/null @@ -1,280 +0,0 @@ -// -// execution/receiver.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_RECEIVER_HPP -#define ASIO_EXECUTION_RECEIVER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" -#include "asio/execution/set_done.hpp" -#include "asio/execution/set_error.hpp" -#include "asio/execution/set_value.hpp" - -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) -# include <exception> -#else // defined(ASIO_HAS_STD_EXCEPTION_PTR) -# include "asio/error_code.hpp" -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - -#if defined(ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT) \ - && defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) \ - && defined(ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT) \ - && defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) \ - && defined(ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT) \ - && defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) \ - && defined(ASIO_HAS_DEDUCED_RECEIVER_OF_FREE_TRAIT) \ - && defined(ASIO_HAS_DEDUCED_RECEIVER_OF_MEMBER_TRAIT) -# define ASIO_HAS_DEDUCED_EXECUTION_IS_RECEIVER_TRAIT 1 -#endif // defined(ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT) - // && defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - // && defined(ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT) - // && defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - // && defined(ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT) - // && defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - // && defined(ASIO_HAS_DEDUCED_RECEIVER_OF_FREE_TRAIT) - // && defined(ASIO_HAS_DEDUCED_RECEIVER_OF_MEMBER_TRAIT) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace execution { -namespace detail { - -template <typename T, typename E> -struct is_receiver_base : - integral_constant<bool, - is_move_constructible<typename remove_cvref<T>::type>::value - && is_constructible<typename remove_cvref<T>::type, T>::value - > -{ -}; - -} // namespace detail - -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) -# define ASIO_EXECUTION_RECEIVER_ERROR_DEFAULT = std::exception_ptr -#else // defined(ASIO_HAS_STD_EXCEPTION_PTR) -# define ASIO_EXECUTION_RECEIVER_ERROR_DEFAULT \ - = ::asio::error_code -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - -/// The is_receiver trait detects whether a type T satisfies the -/// execution::receiver concept. -/** - * Class template @c is_receiver is a type trait that is derived from @c - * true_type if the type @c T meets the concept definition for a receiver for - * error type @c E, otherwise @c false_type. - */ -template <typename T, typename E ASIO_EXECUTION_RECEIVER_ERROR_DEFAULT> -struct is_receiver : -#if defined(GENERATING_DOCUMENTATION) - integral_constant<bool, automatically_determined> -#else // defined(GENERATING_DOCUMENTATION) - conditional< - can_set_done<typename remove_cvref<T>::type>::value - && is_nothrow_set_done<typename remove_cvref<T>::type>::value - && can_set_error<typename remove_cvref<T>::type, E>::value - && is_nothrow_set_error<typename remove_cvref<T>::type, E>::value, - detail::is_receiver_base<T, E>, - false_type - >::type -#endif // defined(GENERATING_DOCUMENTATION) -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename T, typename E ASIO_EXECUTION_RECEIVER_ERROR_DEFAULT> -ASIO_CONSTEXPR const bool is_receiver_v = is_receiver<T, E>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -#if defined(ASIO_HAS_CONCEPTS) - -template <typename T, typename E ASIO_EXECUTION_RECEIVER_ERROR_DEFAULT> -ASIO_CONCEPT receiver = is_receiver<T, E>::value; - -#define ASIO_EXECUTION_RECEIVER ::asio::execution::receiver - -#else // defined(ASIO_HAS_CONCEPTS) - -#define ASIO_EXECUTION_RECEIVER typename - -#endif // defined(ASIO_HAS_CONCEPTS) - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \ - || defined(GENERATING_DOCUMENTATION) - -/// The is_receiver_of trait detects whether a type T satisfies the -/// execution::receiver_of concept for some set of value arguments. -/** - * Class template @c is_receiver_of is a type trait that is derived from @c - * true_type if the type @c T meets the concept definition for a receiver for - * value arguments @c Vs, otherwise @c false_type. - */ -template <typename T, typename... Vs> -struct is_receiver_of : -#if defined(GENERATING_DOCUMENTATION) - integral_constant<bool, automatically_determined> -#else // defined(GENERATING_DOCUMENTATION) - conditional< - is_receiver<T>::value, - can_set_value<typename remove_cvref<T>::type, Vs...>, - false_type - >::type -#endif // defined(GENERATING_DOCUMENTATION) -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename T, typename... Vs> -ASIO_CONSTEXPR const bool is_receiver_of_v = - is_receiver_of<T, Vs...>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -#if defined(ASIO_HAS_CONCEPTS) - -template <typename T, typename... Vs> -ASIO_CONCEPT receiver_of = is_receiver_of<T, Vs...>::value; - -#define ASIO_EXECUTION_RECEIVER_OF_0 \ - ::asio::execution::receiver_of - -#define ASIO_EXECUTION_RECEIVER_OF_1(v) \ - ::asio::execution::receiver_of<v> - -#else // defined(ASIO_HAS_CONCEPTS) - -#define ASIO_EXECUTION_RECEIVER_OF_0 typename -#define ASIO_EXECUTION_RECEIVER_OF_1(v) typename - -#endif // defined(ASIO_HAS_CONCEPTS) - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - -template <typename T, typename = void, - typename = void, typename = void, typename = void, typename = void, - typename = void, typename = void, typename = void, typename = void> -struct is_receiver_of; - -template <typename T> -struct is_receiver_of<T> : - conditional< - is_receiver<T>::value, - can_set_value<typename remove_cvref<T>::type>, - false_type - >::type -{ -}; - -#define ASIO_PRIVATE_RECEIVER_OF_TRAITS_DEF(n) \ - template <typename T, ASIO_VARIADIC_TPARAMS(n)> \ - struct is_receiver_of<T, ASIO_VARIADIC_TARGS(n)> : \ - conditional< \ - conditional<true, is_receiver<T>, void>::type::value, \ - can_set_value< \ - typename remove_cvref<T>::type, \ - ASIO_VARIADIC_TARGS(n)>, \ - false_type \ - >::type \ - { \ - }; \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_RECEIVER_OF_TRAITS_DEF) -#undef ASIO_PRIVATE_RECEIVER_OF_TRAITS_DEF - -#define ASIO_EXECUTION_RECEIVER_OF_0 typename -#define ASIO_EXECUTION_RECEIVER_OF_1(v) typename - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \ - || defined(GENERATING_DOCUMENTATION) - -/// The is_nothrow_receiver_of trait detects whether a type T satisfies the -/// execution::receiver_of concept for some set of value arguments, with a -/// noexcept @c set_value operation. -/** - * Class template @c is_nothrow_receiver_of is a type trait that is derived - * from @c true_type if the type @c T meets the concept definition for a - * receiver for value arguments @c Vs, and the expression - * <tt>execution::set_value(declval<T>(), declval<Ts>()...)</tt> is noexcept, - * otherwise @c false_type. - */ -template <typename T, typename... Vs> -struct is_nothrow_receiver_of : -#if defined(GENERATING_DOCUMENTATION) - integral_constant<bool, automatically_determined> -#else // defined(GENERATING_DOCUMENTATION) - integral_constant<bool, - is_receiver_of<T, Vs...>::value - && is_nothrow_set_value<typename remove_cvref<T>::type, Vs...>::value - > -#endif // defined(GENERATING_DOCUMENTATION) -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename T, typename... Vs> -ASIO_CONSTEXPR const bool is_nothrow_receiver_of_v = - is_nothrow_receiver_of<T, Vs...>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - -template <typename T, typename = void, - typename = void, typename = void, typename = void, typename = void, - typename = void, typename = void, typename = void, typename = void> -struct is_nothrow_receiver_of; - -template <typename T> -struct is_nothrow_receiver_of<T> : - integral_constant<bool, - is_receiver_of<T>::value - && is_nothrow_set_value<typename remove_cvref<T>::type>::value - > -{ -}; - -#define ASIO_PRIVATE_NOTHROW_RECEIVER_OF_TRAITS_DEF(n) \ - template <typename T, ASIO_VARIADIC_TPARAMS(n)> \ - struct is_nothrow_receiver_of<T, ASIO_VARIADIC_TARGS(n)> : \ - integral_constant<bool, \ - is_receiver_of<T, ASIO_VARIADIC_TARGS(n)>::value \ - && is_nothrow_set_value<typename remove_cvref<T>::type, \ - ASIO_VARIADIC_TARGS(n)>::value \ - > \ - { \ - }; \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_NOTHROW_RECEIVER_OF_TRAITS_DEF) -#undef ASIO_PRIVATE_NOTHROW_RECEIVER_OF_TRAITS_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - -} // namespace execution -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_RECEIVER_HPP diff --git a/3rdparty/asio/include/asio/execution/receiver_invocation_error.hpp b/3rdparty/asio/include/asio/execution/receiver_invocation_error.hpp deleted file mode 100644 index 00557da85e1..00000000000 --- a/3rdparty/asio/include/asio/execution/receiver_invocation_error.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// execution/receiver_invocation_error.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_RECEIVER_INVOCATION_ERROR_HPP -#define ASIO_EXECUTION_RECEIVER_INVOCATION_ERROR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include <stdexcept> - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace execution { - -/// Exception reported via @c set_error when an exception escapes from -/// @c set_value. -class receiver_invocation_error - : public std::runtime_error -#if defined(ASIO_HAS_STD_NESTED_EXCEPTION) - , public std::nested_exception -#endif // defined(ASIO_HAS_STD_NESTED_EXCEPTION) -{ -public: - /// Constructor. - ASIO_DECL receiver_invocation_error(); -}; - -} // namespace execution -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#if defined(ASIO_HEADER_ONLY) -# include "asio/execution/impl/receiver_invocation_error.ipp" -#endif // defined(ASIO_HEADER_ONLY) - -#endif // ASIO_EXECUTION_RECEIVER_INVOCATION_ERROR_HPP diff --git a/3rdparty/asio/include/asio/execution/relationship.hpp b/3rdparty/asio/include/asio/execution/relationship.hpp index 95160e07f1a..e4f27555e24 100644 --- a/3rdparty/asio/include/asio/execution/relationship.hpp +++ b/3rdparty/asio/include/asio/execution/relationship.hpp @@ -2,7 +2,7 @@ // execution/relationship.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,8 +18,6 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" -#include "asio/execution/scheduler.hpp" -#include "asio/execution/sender.hpp" #include "asio/is_applicable_property.hpp" #include "asio/query.hpp" #include "asio/traits/query_free.hpp" @@ -40,10 +38,9 @@ namespace execution { /// the calling context. struct relationship_t { - /// The relationship_t property applies to executors, senders, and schedulers. + /// The relationship_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The top-level relationship_t property cannot be required. static constexpr bool is_requirable = false; @@ -58,11 +55,9 @@ struct relationship_t /// continuation of the calling context. struct fork_t { - /// The relationship_t::fork_t property applies to executors, senders, and - /// schedulers. + /// The relationship_t::fork_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The relationship_t::fork_t property can be required. static constexpr bool is_requirable = true; @@ -87,11 +82,9 @@ struct relationship_t /// of the calling context. struct continuation_t { - /// The relationship_t::continuation_t property applies to executors, - /// senders, and schedulers. + /// The relationship_t::continuation_t property applies to executors. template <typename T> - static constexpr bool is_applicable_property_v = - is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>; + static constexpr bool is_applicable_property_v = is_executor_v<T>; /// The relationship_t::continuation_t property can be required. static constexpr bool is_requirable = true; @@ -158,39 +151,27 @@ struct relationship_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); + static constexpr bool is_requirable = false; + static constexpr bool is_preferable = false; typedef relationship_t polymorphic_query_result_type; typedef detail::relationship::fork_t<I> fork_t; typedef detail::relationship::continuation_t<I> continuation_t; - ASIO_CONSTEXPR relationship_t() + constexpr relationship_t() : value_(-1) { } - ASIO_CONSTEXPR relationship_t(fork_t) + constexpr relationship_t(fork_t) : value_(0) { } - ASIO_CONSTEXPR relationship_t(continuation_t) + constexpr relationship_t(continuation_t) : value_(1) { } @@ -202,16 +183,14 @@ struct relationship_t struct type { template <typename P> - auto query(ASIO_MOVE_ARG(P) p) const + auto query(P&& p) const noexcept( noexcept( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ) ) -> decltype( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ); }; #else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) @@ -226,17 +205,17 @@ struct relationship_t struct type { template <typename P> - static constexpr auto query(ASIO_MOVE_ARG(P) p) + static constexpr auto query(P&& p) noexcept( noexcept( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) ) -> decltype( - conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p)) + conditional_t<true, T, P>::query(static_cast<P&&>(p)) ) { - return T::query(ASIO_MOVE_CAST(P)(p)); + return T::query(static_cast<P&&>(p)); } }; #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) @@ -256,66 +235,65 @@ struct relationship_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, fork_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, fork_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, fork_t>::value(); } template <typename T> - static ASIO_CONSTEXPR + static constexpr typename traits::static_query<T, continuation_t>::result_type static_query( - typename enable_if< + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::static_query<T, fork_t>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< traits::static_query<T, continuation_t>::is_valid - >::type* = 0) ASIO_NOEXCEPT + >* = 0) noexcept { return traits::static_query<T, continuation_t>::value(); } template <typename E, typename T = decltype(relationship_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = relationship_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - friend ASIO_CONSTEXPR bool operator==( + friend constexpr bool operator==( const relationship_t& a, const relationship_t& b) { return a.value_ == b.value_; } - friend ASIO_CONSTEXPR bool operator!=( + friend constexpr bool operator!=( const relationship_t& a, const relationship_t& b) { return a.value_ != b.value_; @@ -323,24 +301,22 @@ struct relationship_t struct convertible_from_relationship_t { - ASIO_CONSTEXPR convertible_from_relationship_t(relationship_t) + constexpr convertible_from_relationship_t(relationship_t) { } }; template <typename Executor> - friend ASIO_CONSTEXPR relationship_t query( + friend constexpr relationship_t query( const Executor& ex, convertible_from_relationship_t, - typename enable_if< + enable_if_t< can_query<const Executor&, fork_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, relationship_t<>::fork_t>::value)) + noexcept(is_nothrow_query<const Executor&, relationship_t<>::fork_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, fork_t>::value)) + noexcept(is_nothrow_query<const Executor&, fork_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -348,22 +324,20 @@ struct relationship_t } template <typename Executor> - friend ASIO_CONSTEXPR relationship_t query( + friend constexpr relationship_t query( const Executor& ex, convertible_from_relationship_t, - typename enable_if< + enable_if_t< !can_query<const Executor&, fork_t>::value - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< can_query<const Executor&, continuation_t>::value - >::type* = 0) + >* = 0) #if !defined(__clang__) // Clang crashes if noexcept is used here. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified. - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, - relationship_t<>::continuation_t>::value)) + noexcept(is_nothrow_query<const Executor&, + relationship_t<>::continuation_t>::value) #else // defined(ASIO_MSVC) - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, continuation_t>::value)) + noexcept(is_nothrow_query<const Executor&, continuation_t>::value) #endif // defined(ASIO_MSVC) #endif // !defined(__clang__) { @@ -373,10 +347,6 @@ struct relationship_t ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(fork_t, fork); ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(continuation_t, continuation); -#if !defined(ASIO_HAS_CONSTEXPR) - static const relationship_t instance; -#endif // !defined(ASIO_HAS_CONSTEXPR) - private: int value_; }; @@ -388,14 +358,8 @@ const T relationship_t<I>::static_query_v; #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_CONSTEXPR) template <int I> -const relationship_t<I> relationship_t<I>::instance; -#endif - -template <int I> -const typename relationship_t<I>::fork_t -relationship_t<I>::fork; +const typename relationship_t<I>::fork_t relationship_t<I>::fork; template <int I> const typename relationship_t<I>::continuation_t @@ -408,26 +372,14 @@ struct fork_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; typedef relationship_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR fork_t() + constexpr fork_t() { } @@ -444,55 +396,61 @@ struct fork_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename T> - static ASIO_CONSTEXPR fork_t static_query( - typename enable_if< + static constexpr fork_t static_query( + enable_if_t< !query_static_constexpr_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !query_member<T>::is_valid - >::type* = 0, - typename enable_if< + >* = 0, + enable_if_t< !traits::query_free<T, fork_t>::is_valid - >::type* = 0, - typename enable_if< - !can_query<T, continuation_t<I> >::value - >::type* = 0) ASIO_NOEXCEPT + >* = 0, + enable_if_t< + !can_query<T, continuation_t<I>>::value + >* = 0) noexcept { return fork_t(); } template <typename E, typename T = decltype(fork_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = fork_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR relationship_t<I> value() + static constexpr relationship_t<I> value() { return fork_t(); } - friend ASIO_CONSTEXPR bool operator==( - const fork_t&, const fork_t&) + friend constexpr bool operator==(const fork_t&, const fork_t&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( - const fork_t&, const fork_t&) + friend constexpr bool operator!=(const fork_t&, const fork_t&) + { + return false; + } + + friend constexpr bool operator==(const fork_t&, const continuation_t<I>&) { return false; } + + friend constexpr bool operator!=(const fork_t&, const continuation_t<I>&) + { + return true; + } }; #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ @@ -507,26 +465,14 @@ struct continuation_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T> - ASIO_STATIC_CONSTEXPR(bool, - is_applicable_property_v = ( - is_executor<T>::value - || conditional< - is_executor<T>::value, - false_type, - is_sender<T> - >::type::value - || conditional< - is_executor<T>::value, - false_type, - is_scheduler<T> - >::type::value)); + static constexpr bool is_applicable_property_v = is_executor<T>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - ASIO_STATIC_CONSTEXPR(bool, is_requirable = true); - ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; typedef relationship_t<I> polymorphic_query_result_type; - ASIO_CONSTEXPR continuation_t() + constexpr continuation_t() { } @@ -544,38 +490,44 @@ struct continuation_t #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template <typename T> - static ASIO_CONSTEXPR - typename query_static_constexpr_member<T>::result_type + static constexpr typename query_static_constexpr_member<T>::result_type static_query() - ASIO_NOEXCEPT_IF(( - query_static_constexpr_member<T>::is_noexcept)) + noexcept(query_static_constexpr_member<T>::is_noexcept) { return query_static_constexpr_member<T>::value(); } template <typename E, typename T = decltype(continuation_t::static_query<E>())> - static ASIO_CONSTEXPR const T static_query_v + static constexpr const T static_query_v = continuation_t::static_query<E>(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) - static ASIO_CONSTEXPR relationship_t<I> value() + static constexpr relationship_t<I> value() { return continuation_t(); } - friend ASIO_CONSTEXPR bool operator==( - const continuation_t&, const continuation_t&) + friend constexpr bool operator==(const continuation_t&, const continuation_t&) { return true; } - friend ASIO_CONSTEXPR bool operator!=( - const continuation_t&, const continuation_t&) + friend constexpr bool operator!=(const continuation_t&, const continuation_t&) { return false; } + + friend constexpr bool operator==(const continuation_t&, const fork_t<I>&) + { + return false; + } + + friend constexpr bool operator!=(const continuation_t&, const fork_t<I>&) + { + return true; + } }; #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ @@ -590,12 +542,7 @@ const T continuation_t<I>::static_query_v; typedef detail::relationship_t<> relationship_t; -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr relationship_t relationship; -#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -namespace { static const relationship_t& - relationship = relationship_t::instance; } -#endif } // namespace execution @@ -603,52 +550,19 @@ namespace { static const relationship_t& template <typename T> struct is_applicable_property<T, execution::relationship_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::relationship_t::fork_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; template <typename T> struct is_applicable_property<T, execution::relationship_t::continuation_t> - : integral_constant<bool, - execution::is_executor<T>::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_sender<T> - >::type::value - || conditional< - execution::is_executor<T>::value, - false_type, - execution::is_scheduler<T> - >::type::value> + : integral_constant<bool, execution::is_executor<T>::value> { }; @@ -660,27 +574,27 @@ namespace traits { template <typename T> struct query_free_default<T, execution::relationship_t, - typename enable_if< + enable_if_t< can_query<T, execution::relationship_t::fork_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::relationship_t::fork_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::relationship_t::fork_t>::value; typedef execution::relationship_t result_type; }; template <typename T> struct query_free_default<T, execution::relationship_t, - typename enable_if< + enable_if_t< !can_query<T, execution::relationship_t::fork_t>::value && can_query<T, execution::relationship_t::continuation_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<T, execution::relationship_t::continuation_t>::value)); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<T, execution::relationship_t::continuation_t>::value; typedef execution::relationship_t result_type; }; @@ -692,18 +606,18 @@ struct query_free_default<T, execution::relationship_t, template <typename T> struct static_query<T, execution::relationship_t, - typename enable_if< + enable_if_t< execution::detail::relationship_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::relationship_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::relationship_t<0>:: query_static_constexpr_member<T>::value(); @@ -712,22 +626,22 @@ struct static_query<T, execution::relationship_t, template <typename T> struct static_query<T, execution::relationship_t, - typename enable_if< + enable_if_t< !execution::detail::relationship_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::relationship_t<0>:: query_member<T>::is_valid && traits::static_query<T, execution::relationship_t::fork_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::relationship_t::fork_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::relationship_t::fork_t>::value(); @@ -736,7 +650,7 @@ struct static_query<T, execution::relationship_t, template <typename T> struct static_query<T, execution::relationship_t, - typename enable_if< + enable_if_t< !execution::detail::relationship_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::relationship_t<0>:: @@ -745,15 +659,15 @@ struct static_query<T, execution::relationship_t, execution::relationship_t::fork_t>::is_valid && traits::static_query<T, execution::relationship_t::continuation_t>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename traits::static_query<T, execution::relationship_t::continuation_t>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return traits::static_query<T, execution::relationship_t::continuation_t>::value(); @@ -762,18 +676,18 @@ struct static_query<T, execution::relationship_t, template <typename T> struct static_query<T, execution::relationship_t::fork_t, - typename enable_if< + enable_if_t< execution::detail::relationship::fork_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::relationship::fork_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::relationship::fork_t<0>:: query_static_constexpr_member<T>::value(); @@ -782,7 +696,7 @@ struct static_query<T, execution::relationship_t::fork_t, template <typename T> struct static_query<T, execution::relationship_t::fork_t, - typename enable_if< + enable_if_t< !execution::detail::relationship::fork_t<0>:: query_static_constexpr_member<T>::is_valid && !execution::detail::relationship::fork_t<0>:: @@ -790,14 +704,14 @@ struct static_query<T, execution::relationship_t::fork_t, && !traits::query_free<T, execution::relationship_t::fork_t>::is_valid && !can_query<T, execution::relationship_t::continuation_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef execution::relationship_t::fork_t result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return result_type(); } @@ -805,18 +719,18 @@ struct static_query<T, execution::relationship_t::fork_t, template <typename T> struct static_query<T, execution::relationship_t::continuation_t, - typename enable_if< + enable_if_t< execution::detail::relationship::continuation_t<0>:: query_static_constexpr_member<T>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef typename execution::detail::relationship::continuation_t<0>:: query_static_constexpr_member<T>::result_type result_type; - static ASIO_CONSTEXPR result_type value() + static constexpr result_type value() { return execution::detail::relationship::continuation_t<0>:: query_static_constexpr_member<T>::value(); @@ -826,34 +740,6 @@ struct static_query<T, execution::relationship_t::continuation_t, #endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) -#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - -template <typename T> -struct static_require<T, execution::relationship_t::fork_t, - typename enable_if< - static_query<T, execution::relationship_t::fork_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::relationship_t::fork_t>::result_type, - execution::relationship_t::fork_t>::value)); -}; - -template <typename T> -struct static_require<T, execution::relationship_t::continuation_t, - typename enable_if< - static_query<T, execution::relationship_t::continuation_t>::is_valid - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = - (is_same<typename static_query<T, - execution::relationship_t::continuation_t>::result_type, - execution::relationship_t::continuation_t>::value)); -}; - -#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - } // namespace traits #endif // defined(GENERATING_DOCUMENTATION) diff --git a/3rdparty/asio/include/asio/execution/schedule.hpp b/3rdparty/asio/include/asio/execution/schedule.hpp deleted file mode 100644 index fde0cdda599..00000000000 --- a/3rdparty/asio/include/asio/execution/schedule.hpp +++ /dev/null @@ -1,287 +0,0 @@ -// -// execution/schedule.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_SCHEDULE_HPP -#define ASIO_EXECUTION_SCHEDULE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/executor.hpp" -#include "asio/traits/schedule_member.hpp" -#include "asio/traits/schedule_free.hpp" - -#include "asio/detail/push_options.hpp" - -#if defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace execution { - -/// A customisation point that is used to obtain a sender from a scheduler. -/** - * The name <tt>execution::schedule</tt> denotes a customisation point object. - * For some subexpression <tt>s</tt>, let <tt>S</tt> be a type such that - * <tt>decltype((s))</tt> is <tt>S</tt>. The expression - * <tt>execution::schedule(s)</tt> is expression-equivalent to: - * - * @li <tt>s.schedule()</tt>, if that expression is valid and its type models - * <tt>sender</tt>. - * - * @li Otherwise, <tt>schedule(s)</tt>, if that expression is valid and its - * type models <tt>sender</tt> with overload resolution performed in a context - * that includes the declaration <tt>void schedule();</tt> and that does not - * include a declaration of <tt>execution::schedule</tt>. - * - * @li Otherwise, <tt>S</tt> if <tt>S</tt> satisfies <tt>executor</tt>. - * - * @li Otherwise, <tt>execution::schedule(s)</tt> is ill-formed. - */ -inline constexpr unspecified schedule = unspecified; - -/// A type trait that determines whether a @c schedule expression is -/// well-formed. -/** - * Class template @c can_schedule is a trait that is derived from @c true_type - * if the expression <tt>execution::schedule(std::declval<S>())</tt> is well - * formed; otherwise @c false_type. - */ -template <typename S> -struct can_schedule : - integral_constant<bool, automatically_determined> -{ -}; - -} // namespace execution -} // namespace asio - -#else // defined(GENERATING_DOCUMENTATION) - -namespace asio_execution_schedule_fn { - -using asio::decay; -using asio::declval; -using asio::enable_if; -using asio::execution::is_executor; -using asio::traits::schedule_free; -using asio::traits::schedule_member; - -void schedule(); - -enum overload_type -{ - identity, - call_member, - call_free, - ill_formed -}; - -template <typename S, typename = void, typename = void, typename = void> -struct call_traits -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef void result_type; -}; - -template <typename S> -struct call_traits<S, - typename enable_if< - schedule_member<S>::is_valid - >::type> : - schedule_member<S> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); -}; - -template <typename S> -struct call_traits<S, - typename enable_if< - !schedule_member<S>::is_valid - >::type, - typename enable_if< - schedule_free<S>::is_valid - >::type> : - schedule_free<S> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); -}; - -template <typename S> -struct call_traits<S, - typename enable_if< - !schedule_member<S>::is_valid - >::type, - typename enable_if< - !schedule_free<S>::is_valid - >::type, - typename enable_if< - is_executor<typename decay<S>::type>::value - >::type> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = identity); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - -#if defined(ASIO_HAS_MOVE) - typedef ASIO_MOVE_ARG(S) result_type; -#else // defined(ASIO_HAS_MOVE) - typedef ASIO_MOVE_ARG(typename decay<S>::type) result_type; -#endif // defined(ASIO_HAS_MOVE) -}; - -struct impl -{ - template <typename S> - ASIO_CONSTEXPR typename enable_if< - call_traits<S>::overload == identity, - typename call_traits<S>::result_type - >::type - operator()(ASIO_MOVE_ARG(S) s) const - ASIO_NOEXCEPT_IF(( - call_traits<S>::is_noexcept)) - { - return ASIO_MOVE_CAST(S)(s); - } - -#if defined(ASIO_HAS_MOVE) - template <typename S> - ASIO_CONSTEXPR typename enable_if< - call_traits<S>::overload == call_member, - typename call_traits<S>::result_type - >::type - operator()(S&& s) const - ASIO_NOEXCEPT_IF(( - call_traits<S>::is_noexcept)) - { - return ASIO_MOVE_CAST(S)(s).schedule(); - } - - template <typename S> - ASIO_CONSTEXPR typename enable_if< - call_traits<S>::overload == call_free, - typename call_traits<S>::result_type - >::type - operator()(S&& s) const - ASIO_NOEXCEPT_IF(( - call_traits<S>::is_noexcept)) - { - return schedule(ASIO_MOVE_CAST(S)(s)); - } -#else // defined(ASIO_HAS_MOVE) - template <typename S> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&>::overload == call_member, - typename call_traits<S&>::result_type - >::type - operator()(S& s) const - ASIO_NOEXCEPT_IF(( - call_traits<S&>::is_noexcept)) - { - return s.schedule(); - } - - template <typename S> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&>::overload == call_member, - typename call_traits<const S&>::result_type - >::type - operator()(const S& s) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&>::is_noexcept)) - { - return s.schedule(); - } - - template <typename S> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&>::overload == call_free, - typename call_traits<S&>::result_type - >::type - operator()(S& s) const - ASIO_NOEXCEPT_IF(( - call_traits<S&>::is_noexcept)) - { - return schedule(s); - } - - template <typename S> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&>::overload == call_free, - typename call_traits<const S&>::result_type - >::type - operator()(const S& s) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&>::is_noexcept)) - { - return schedule(s); - } -#endif // defined(ASIO_HAS_MOVE) -}; - -template <typename T = impl> -struct static_instance -{ - static const T instance; -}; - -template <typename T> -const T static_instance<T>::instance = {}; - -} // namespace asio_execution_schedule_fn -namespace asio { -namespace execution { -namespace { - -static ASIO_CONSTEXPR const asio_execution_schedule_fn::impl& - schedule = asio_execution_schedule_fn::static_instance<>::instance; - -} // namespace - -template <typename S> -struct can_schedule : - integral_constant<bool, - asio_execution_schedule_fn::call_traits<S>::overload != - asio_execution_schedule_fn::ill_formed> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S> -constexpr bool can_schedule_v = can_schedule<S>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S> -struct is_nothrow_schedule : - integral_constant<bool, - asio_execution_schedule_fn::call_traits<S>::is_noexcept> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S> -constexpr bool is_nothrow_schedule_v - = is_nothrow_schedule<S>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -} // namespace execution -} // namespace asio - -#endif // defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_SCHEDULE_HPP diff --git a/3rdparty/asio/include/asio/execution/scheduler.hpp b/3rdparty/asio/include/asio/execution/scheduler.hpp deleted file mode 100644 index b99ab3c7e9f..00000000000 --- a/3rdparty/asio/include/asio/execution/scheduler.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// -// execution/scheduler.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_SCHEDULER_HPP -#define ASIO_EXECUTION_SCHEDULER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/schedule.hpp" -#include "asio/traits/equality_comparable.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace execution { -namespace detail { - -template <typename T> -struct is_scheduler_base : - integral_constant<bool, - is_copy_constructible<typename remove_cvref<T>::type>::value - && traits::equality_comparable<typename remove_cvref<T>::type>::is_valid - > -{ -}; - -} // namespace detail - -/// The is_scheduler trait detects whether a type T satisfies the -/// execution::scheduler concept. -/** - * Class template @c is_scheduler is a type trait that is derived from @c - * true_type if the type @c T meets the concept definition for a scheduler for - * error type @c E, otherwise @c false_type. - */ -template <typename T> -struct is_scheduler : -#if defined(GENERATING_DOCUMENTATION) - integral_constant<bool, automatically_determined> -#else // defined(GENERATING_DOCUMENTATION) - conditional< - can_schedule<T>::value, - detail::is_scheduler_base<T>, - false_type - >::type -#endif // defined(GENERATING_DOCUMENTATION) -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename T> -ASIO_CONSTEXPR const bool is_scheduler_v = is_scheduler<T>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -#if defined(ASIO_HAS_CONCEPTS) - -template <typename T> -ASIO_CONCEPT scheduler = is_scheduler<T>::value; - -#define ASIO_EXECUTION_SCHEDULER ::asio::execution::scheduler - -#else // defined(ASIO_HAS_CONCEPTS) - -#define ASIO_EXECUTION_SCHEDULER typename - -#endif // defined(ASIO_HAS_CONCEPTS) - -} // namespace execution -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_SCHEDULER_HPP diff --git a/3rdparty/asio/include/asio/execution/sender.hpp b/3rdparty/asio/include/asio/execution/sender.hpp deleted file mode 100644 index 4e4ba476b01..00000000000 --- a/3rdparty/asio/include/asio/execution/sender.hpp +++ /dev/null @@ -1,311 +0,0 @@ -// -// execution/sender.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_SENDER_HPP -#define ASIO_EXECUTION_SENDER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/detail/as_invocable.hpp" -#include "asio/execution/detail/void_receiver.hpp" -#include "asio/execution/executor.hpp" -#include "asio/execution/receiver.hpp" - -#include "asio/detail/push_options.hpp" - -#if defined(ASIO_HAS_ALIAS_TEMPLATES) \ - && defined(ASIO_HAS_VARIADIC_TEMPLATES) \ - && defined(ASIO_HAS_DECLTYPE) \ - && !defined(ASIO_MSVC) || (_MSC_VER >= 1910) -# define ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT 1 -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - // && defined(ASIO_HAS_VARIADIC_TEMPLATES) - // && defined(ASIO_HAS_DECLTYPE) - // && !defined(ASIO_MSVC) || (_MSC_VER >= 1910) - -namespace asio { -namespace execution { -namespace detail { - -namespace sender_base_ns { struct sender_base {}; } - -template <typename S, typename = void> -struct sender_traits_base -{ - typedef void asio_execution_sender_traits_base_is_unspecialised; -}; - -template <typename S> -struct sender_traits_base<S, - typename enable_if< - is_base_of<sender_base_ns::sender_base, S>::value - >::type> -{ -}; - -template <typename S, typename = void, typename = void, typename = void> -struct has_sender_types : false_type -{ -}; - -#if defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) - -template < - template < - template <typename...> class Tuple, - template <typename...> class Variant - > class> -struct has_value_types -{ - typedef void type; -}; - -template < - template < - template <typename...> class Variant - > class> -struct has_error_types -{ - typedef void type; -}; - -template <typename S> -struct has_sender_types<S, - typename has_value_types<S::template value_types>::type, - typename has_error_types<S::template error_types>::type, - typename conditional<S::sends_done, void, void>::type> : true_type -{ -}; - -template <typename S> -struct sender_traits_base<S, - typename enable_if< - has_sender_types<S>::value - >::type> -{ - template < - template <typename...> class Tuple, - template <typename...> class Variant> - using value_types = typename S::template value_types<Tuple, Variant>; - - template <template <typename...> class Variant> - using error_types = typename S::template error_types<Variant>; - - ASIO_STATIC_CONSTEXPR(bool, sends_done = S::sends_done); -}; - -#endif // defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) - -template <typename S> -struct sender_traits_base<S, - typename enable_if< - !has_sender_types<S>::value - && detail::is_executor_of_impl<S, - as_invocable<void_receiver, S> >::value - >::type> -{ -#if defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) \ - && defined(ASIO_HAS_STD_EXCEPTION_PTR) - - template < - template <typename...> class Tuple, - template <typename...> class Variant> - using value_types = Variant<Tuple<>>; - - template <template <typename...> class Variant> - using error_types = Variant<std::exception_ptr>; - - ASIO_STATIC_CONSTEXPR(bool, sends_done = true); - -#endif // defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) - // && defined(ASIO_HAS_STD_EXCEPTION_PTR) -}; - -} // namespace detail - -/// Base class used for tagging senders. -#if defined(GENERATING_DOCUMENTATION) -typedef unspecified sender_base; -#else // defined(GENERATING_DOCUMENTATION) -typedef detail::sender_base_ns::sender_base sender_base; -#endif // defined(GENERATING_DOCUMENTATION) - -/// Traits for senders. -template <typename S> -struct sender_traits -#if !defined(GENERATING_DOCUMENTATION) - : detail::sender_traits_base<S> -#endif // !defined(GENERATING_DOCUMENTATION) -{ -}; - -namespace detail { - -template <typename S, typename = void> -struct has_sender_traits : true_type -{ -}; - -template <typename S> -struct has_sender_traits<S, - typename enable_if< - is_same< - typename asio::execution::sender_traits< - S>::asio_execution_sender_traits_base_is_unspecialised, - void - >::value - >::type> : false_type -{ -}; - -} // namespace detail - -/// The is_sender trait detects whether a type T satisfies the -/// execution::sender concept. - -/** - * Class template @c is_sender is a type trait that is derived from @c - * true_type if the type @c T meets the concept definition for a sender, - * otherwise @c false_type. - */ -template <typename T> -struct is_sender : -#if defined(GENERATING_DOCUMENTATION) - integral_constant<bool, automatically_determined> -#else // defined(GENERATING_DOCUMENTATION) - conditional< - detail::has_sender_traits<typename remove_cvref<T>::type>::value, - is_move_constructible<typename remove_cvref<T>::type>, - false_type - >::type -#endif // defined(GENERATING_DOCUMENTATION) -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename T> -ASIO_CONSTEXPR const bool is_sender_v = is_sender<T>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -#if defined(ASIO_HAS_CONCEPTS) - -template <typename T> -ASIO_CONCEPT sender = is_sender<T>::value; - -#define ASIO_EXECUTION_SENDER ::asio::execution::sender - -#else // defined(ASIO_HAS_CONCEPTS) - -#define ASIO_EXECUTION_SENDER typename - -#endif // defined(ASIO_HAS_CONCEPTS) - -template <typename S, typename R> -struct can_connect; - -/// The is_sender_to trait detects whether a type T satisfies the -/// execution::sender_to concept for some receiver. -/** - * Class template @c is_sender_to is a type trait that is derived from @c - * true_type if the type @c T meets the concept definition for a sender - * for some receiver type R, otherwise @c false. - */ -template <typename T, typename R> -struct is_sender_to : -#if defined(GENERATING_DOCUMENTATION) - integral_constant<bool, automatically_determined> -#else // defined(GENERATING_DOCUMENTATION) - integral_constant<bool, - is_sender<T>::value - && is_receiver<R>::value - && can_connect<T, R>::value - > -#endif // defined(GENERATING_DOCUMENTATION) -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename T, typename R> -ASIO_CONSTEXPR const bool is_sender_to_v = - is_sender_to<T, R>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -#if defined(ASIO_HAS_CONCEPTS) - -template <typename T, typename R> -ASIO_CONCEPT sender_to = is_sender_to<T, R>::value; - -#define ASIO_EXECUTION_SENDER_TO(r) \ - ::asio::execution::sender_to<r> - -#else // defined(ASIO_HAS_CONCEPTS) - -#define ASIO_EXECUTION_SENDER_TO(r) typename - -#endif // defined(ASIO_HAS_CONCEPTS) - -/// The is_typed_sender trait detects whether a type T satisfies the -/// execution::typed_sender concept. -/** - * Class template @c is_typed_sender is a type trait that is derived from @c - * true_type if the type @c T meets the concept definition for a typed sender, - * otherwise @c false. - */ -template <typename T> -struct is_typed_sender : -#if defined(GENERATING_DOCUMENTATION) - integral_constant<bool, automatically_determined> -#else // defined(GENERATING_DOCUMENTATION) - integral_constant<bool, - is_sender<T>::value - && detail::has_sender_types< - sender_traits<typename remove_cvref<T>::type> >::value - > -#endif // defined(GENERATING_DOCUMENTATION) -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename T> -ASIO_CONSTEXPR const bool is_typed_sender_v = is_typed_sender<T>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -#if defined(ASIO_HAS_CONCEPTS) - -template <typename T> -ASIO_CONCEPT typed_sender = is_typed_sender<T>::value; - -#define ASIO_EXECUTION_TYPED_SENDER \ - ::asio::execution::typed_sender - -#else // defined(ASIO_HAS_CONCEPTS) - -#define ASIO_EXECUTION_TYPED_SENDER typename - -#endif // defined(ASIO_HAS_CONCEPTS) - -} // namespace execution -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#include "asio/execution/connect.hpp" - -#endif // ASIO_EXECUTION_SENDER_HPP diff --git a/3rdparty/asio/include/asio/execution/set_done.hpp b/3rdparty/asio/include/asio/execution/set_done.hpp deleted file mode 100644 index ae26869a020..00000000000 --- a/3rdparty/asio/include/asio/execution/set_done.hpp +++ /dev/null @@ -1,250 +0,0 @@ -// -// execution/set_done.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_SET_DONE_HPP -#define ASIO_EXECUTION_SET_DONE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/traits/set_done_member.hpp" -#include "asio/traits/set_done_free.hpp" - -#include "asio/detail/push_options.hpp" - -#if defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace execution { - -/// A customisation point that delivers a done notification to a receiver. -/** - * The name <tt>execution::set_done</tt> denotes a customisation point object. - * The expression <tt>execution::set_done(R)</tt> for some subexpression - * <tt>R</tt> is expression-equivalent to: - * - * @li <tt>R.set_done()</tt>, if that expression is valid. If the function - * selected does not signal the receiver <tt>R</tt>'s done channel, the - * program is ill-formed with no diagnostic required. - * - * @li Otherwise, <tt>set_done(R)</tt>, if that expression is valid, with - * overload resolution performed in a context that includes the declaration - * <tt>void set_done();</tt> and that does not include a declaration of - * <tt>execution::set_done</tt>. If the function selected by overload - * resolution does not signal the receiver <tt>R</tt>'s done channel, the - * program is ill-formed with no diagnostic required. - * - * @li Otherwise, <tt>execution::set_done(R)</tt> is ill-formed. - */ -inline constexpr unspecified set_done = unspecified; - -/// A type trait that determines whether a @c set_done expression is -/// well-formed. -/** - * Class template @c can_set_done is a trait that is derived from - * @c true_type if the expression <tt>execution::set_done(std::declval<R>(), - * std::declval<E>())</tt> is well formed; otherwise @c false_type. - */ -template <typename R> -struct can_set_done : - integral_constant<bool, automatically_determined> -{ -}; - -} // namespace execution -} // namespace asio - -#else // defined(GENERATING_DOCUMENTATION) - -namespace asio_execution_set_done_fn { - -using asio::decay; -using asio::declval; -using asio::enable_if; -using asio::traits::set_done_free; -using asio::traits::set_done_member; - -void set_done(); - -enum overload_type -{ - call_member, - call_free, - ill_formed -}; - -template <typename R, typename = void, typename = void> -struct call_traits -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef void result_type; -}; - -template <typename R> -struct call_traits<R, - typename enable_if< - set_done_member<R>::is_valid - >::type> : - set_done_member<R> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); -}; - -template <typename R> -struct call_traits<R, - typename enable_if< - !set_done_member<R>::is_valid - >::type, - typename enable_if< - set_done_free<R>::is_valid - >::type> : - set_done_free<R> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); -}; - -struct impl -{ -#if defined(ASIO_HAS_MOVE) - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R>::overload == call_member, - typename call_traits<R>::result_type - >::type - operator()(R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R>::is_noexcept)) - { - return ASIO_MOVE_CAST(R)(r).set_done(); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R>::overload == call_free, - typename call_traits<R>::result_type - >::type - operator()(R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R>::is_noexcept)) - { - return set_done(ASIO_MOVE_CAST(R)(r)); - } -#else // defined(ASIO_HAS_MOVE) - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R&>::overload == call_member, - typename call_traits<R&>::result_type - >::type - operator()(R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R&>::is_noexcept)) - { - return r.set_done(); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const R&>::overload == call_member, - typename call_traits<const R&>::result_type - >::type - operator()(const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const R&>::is_noexcept)) - { - return r.set_done(); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R&>::overload == call_free, - typename call_traits<R&>::result_type - >::type - operator()(R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R&>::is_noexcept)) - { - return set_done(r); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const R&>::overload == call_free, - typename call_traits<const R&>::result_type - >::type - operator()(const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const R&>::is_noexcept)) - { - return set_done(r); - } -#endif // defined(ASIO_HAS_MOVE) -}; - -template <typename T = impl> -struct static_instance -{ - static const T instance; -}; - -template <typename T> -const T static_instance<T>::instance = {}; - -} // namespace asio_execution_set_done_fn -namespace asio { -namespace execution { -namespace { - -static ASIO_CONSTEXPR const asio_execution_set_done_fn::impl& - set_done = asio_execution_set_done_fn::static_instance<>::instance; - -} // namespace - -template <typename R> -struct can_set_done : - integral_constant<bool, - asio_execution_set_done_fn::call_traits<R>::overload != - asio_execution_set_done_fn::ill_formed> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R> -constexpr bool can_set_done_v = can_set_done<R>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R> -struct is_nothrow_set_done : - integral_constant<bool, - asio_execution_set_done_fn::call_traits<R>::is_noexcept> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R> -constexpr bool is_nothrow_set_done_v - = is_nothrow_set_done<R>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -} // namespace execution -} // namespace asio - -#endif // defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_SET_DONE_HPP diff --git a/3rdparty/asio/include/asio/execution/set_error.hpp b/3rdparty/asio/include/asio/execution/set_error.hpp deleted file mode 100644 index 2aa3de3a6fc..00000000000 --- a/3rdparty/asio/include/asio/execution/set_error.hpp +++ /dev/null @@ -1,250 +0,0 @@ -// -// execution/set_error.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_SET_ERROR_HPP -#define ASIO_EXECUTION_SET_ERROR_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/traits/set_error_member.hpp" -#include "asio/traits/set_error_free.hpp" - -#include "asio/detail/push_options.hpp" - -#if defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace execution { - -/// A customisation point that delivers an error notification to a receiver. -/** - * The name <tt>execution::set_error</tt> denotes a customisation point object. - * The expression <tt>execution::set_error(R, E)</tt> for some subexpressions - * <tt>R</tt> and <tt>E</tt> are expression-equivalent to: - * - * @li <tt>R.set_error(E)</tt>, if that expression is valid. If the function - * selected does not send the error <tt>E</tt> to the receiver <tt>R</tt>'s - * error channel, the program is ill-formed with no diagnostic required. - * - * @li Otherwise, <tt>set_error(R, E)</tt>, if that expression is valid, with - * overload resolution performed in a context that includes the declaration - * <tt>void set_error();</tt> and that does not include a declaration of - * <tt>execution::set_error</tt>. If the function selected by overload - * resolution does not send the error <tt>E</tt> to the receiver <tt>R</tt>'s - * error channel, the program is ill-formed with no diagnostic required. - * - * @li Otherwise, <tt>execution::set_error(R, E)</tt> is ill-formed. - */ -inline constexpr unspecified set_error = unspecified; - -/// A type trait that determines whether a @c set_error expression is -/// well-formed. -/** - * Class template @c can_set_error is a trait that is derived from - * @c true_type if the expression <tt>execution::set_error(std::declval<R>(), - * std::declval<E>())</tt> is well formed; otherwise @c false_type. - */ -template <typename R, typename E> -struct can_set_error : - integral_constant<bool, automatically_determined> -{ -}; - -} // namespace execution -} // namespace asio - -#else // defined(GENERATING_DOCUMENTATION) - -namespace asio_execution_set_error_fn { - -using asio::decay; -using asio::declval; -using asio::enable_if; -using asio::traits::set_error_free; -using asio::traits::set_error_member; - -void set_error(); - -enum overload_type -{ - call_member, - call_free, - ill_formed -}; - -template <typename R, typename E, typename = void, typename = void> -struct call_traits -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef void result_type; -}; - -template <typename R, typename E> -struct call_traits<R, void(E), - typename enable_if< - set_error_member<R, E>::is_valid - >::type> : - set_error_member<R, E> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); -}; - -template <typename R, typename E> -struct call_traits<R, void(E), - typename enable_if< - !set_error_member<R, E>::is_valid - >::type, - typename enable_if< - set_error_free<R, E>::is_valid - >::type> : - set_error_free<R, E> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); -}; - -struct impl -{ -#if defined(ASIO_HAS_MOVE) - template <typename R, typename E> - ASIO_CONSTEXPR typename enable_if< - call_traits<R, void(E)>::overload == call_member, - typename call_traits<R, void(E)>::result_type - >::type - operator()(R&& r, E&& e) const - ASIO_NOEXCEPT_IF(( - call_traits<R, void(E)>::is_noexcept)) - { - return ASIO_MOVE_CAST(R)(r).set_error(ASIO_MOVE_CAST(E)(e)); - } - - template <typename R, typename E> - ASIO_CONSTEXPR typename enable_if< - call_traits<R, void(E)>::overload == call_free, - typename call_traits<R, void(E)>::result_type - >::type - operator()(R&& r, E&& e) const - ASIO_NOEXCEPT_IF(( - call_traits<R, void(E)>::is_noexcept)) - { - return set_error(ASIO_MOVE_CAST(R)(r), ASIO_MOVE_CAST(E)(e)); - } -#else // defined(ASIO_HAS_MOVE) - template <typename R, typename E> - ASIO_CONSTEXPR typename enable_if< - call_traits<R&, void(const E&)>::overload == call_member, - typename call_traits<R&, void(const E&)>::result_type - >::type - operator()(R& r, const E& e) const - ASIO_NOEXCEPT_IF(( - call_traits<R&, void(const E&)>::is_noexcept)) - { - return r.set_error(e); - } - - template <typename R, typename E> - ASIO_CONSTEXPR typename enable_if< - call_traits<const R&, void(const E&)>::overload == call_member, - typename call_traits<const R&, void(const E&)>::result_type - >::type - operator()(const R& r, const E& e) const - ASIO_NOEXCEPT_IF(( - call_traits<const R&, void(const E&)>::is_noexcept)) - { - return r.set_error(e); - } - - template <typename R, typename E> - ASIO_CONSTEXPR typename enable_if< - call_traits<R&, void(const E&)>::overload == call_free, - typename call_traits<R&, void(const E&)>::result_type - >::type - operator()(R& r, const E& e) const - ASIO_NOEXCEPT_IF(( - call_traits<R&, void(const E&)>::is_noexcept)) - { - return set_error(r, e); - } - - template <typename R, typename E> - ASIO_CONSTEXPR typename enable_if< - call_traits<const R&, void(const E&)>::overload == call_free, - typename call_traits<const R&, void(const E&)>::result_type - >::type - operator()(const R& r, const E& e) const - ASIO_NOEXCEPT_IF(( - call_traits<const R&, void(const E&)>::is_noexcept)) - { - return set_error(r, e); - } -#endif // defined(ASIO_HAS_MOVE) -}; - -template <typename T = impl> -struct static_instance -{ - static const T instance; -}; - -template <typename T> -const T static_instance<T>::instance = {}; - -} // namespace asio_execution_set_error_fn -namespace asio { -namespace execution { -namespace { - -static ASIO_CONSTEXPR const asio_execution_set_error_fn::impl& - set_error = asio_execution_set_error_fn::static_instance<>::instance; - -} // namespace - -template <typename R, typename E> -struct can_set_error : - integral_constant<bool, - asio_execution_set_error_fn::call_traits<R, void(E)>::overload != - asio_execution_set_error_fn::ill_formed> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R, typename E> -constexpr bool can_set_error_v = can_set_error<R, E>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R, typename E> -struct is_nothrow_set_error : - integral_constant<bool, - asio_execution_set_error_fn::call_traits<R, void(E)>::is_noexcept> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R, typename E> -constexpr bool is_nothrow_set_error_v - = is_nothrow_set_error<R, E>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -} // namespace execution -} // namespace asio - -#endif // defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_SET_ERROR_HPP diff --git a/3rdparty/asio/include/asio/execution/set_value.hpp b/3rdparty/asio/include/asio/execution/set_value.hpp deleted file mode 100644 index 90d29dda540..00000000000 --- a/3rdparty/asio/include/asio/execution/set_value.hpp +++ /dev/null @@ -1,483 +0,0 @@ -// -// execution/set_value.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_SET_VALUE_HPP -#define ASIO_EXECUTION_SET_VALUE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" -#include "asio/traits/set_value_member.hpp" -#include "asio/traits/set_value_free.hpp" - -#include "asio/detail/push_options.hpp" - -#if defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace execution { - -/// A customisation point that delivers a value to a receiver. -/** - * The name <tt>execution::set_value</tt> denotes a customisation point object. - * The expression <tt>execution::set_value(R, Vs...)</tt> for some - * subexpressions <tt>R</tt> and <tt>Vs...</tt> is expression-equivalent to: - * - * @li <tt>R.set_value(Vs...)</tt>, if that expression is valid. If the - * function selected does not send the value(s) <tt>Vs...</tt> to the receiver - * <tt>R</tt>'s value channel, the program is ill-formed with no diagnostic - * required. - * - * @li Otherwise, <tt>set_value(R, Vs...)</tt>, if that expression is valid, - * with overload resolution performed in a context that includes the - * declaration <tt>void set_value();</tt> and that does not include a - * declaration of <tt>execution::set_value</tt>. If the function selected by - * overload resolution does not send the value(s) <tt>Vs...</tt> to the - * receiver <tt>R</tt>'s value channel, the program is ill-formed with no - * diagnostic required. - * - * @li Otherwise, <tt>execution::set_value(R, Vs...)</tt> is ill-formed. - */ -inline constexpr unspecified set_value = unspecified; - -/// A type trait that determines whether a @c set_value expression is -/// well-formed. -/** - * Class template @c can_set_value is a trait that is derived from - * @c true_type if the expression <tt>execution::set_value(std::declval<R>(), - * std::declval<Vs>()...)</tt> is well formed; otherwise @c false_type. - */ -template <typename R, typename... Vs> -struct can_set_value : - integral_constant<bool, automatically_determined> -{ -}; - -} // namespace execution -} // namespace asio - -#else // defined(GENERATING_DOCUMENTATION) - -namespace asio_execution_set_value_fn { - -using asio::decay; -using asio::declval; -using asio::enable_if; -using asio::traits::set_value_free; -using asio::traits::set_value_member; - -void set_value(); - -enum overload_type -{ - call_member, - call_free, - ill_formed -}; - -template <typename R, typename Vs, typename = void, typename = void> -struct call_traits -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef void result_type; -}; - -template <typename R, typename Vs> -struct call_traits<R, Vs, - typename enable_if< - set_value_member<R, Vs>::is_valid - >::type> : - set_value_member<R, Vs> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); -}; - -template <typename R, typename Vs> -struct call_traits<R, Vs, - typename enable_if< - !set_value_member<R, Vs>::is_valid - >::type, - typename enable_if< - set_value_free<R, Vs>::is_valid - >::type> : - set_value_free<R, Vs> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); -}; - -struct impl -{ -#if defined(ASIO_HAS_MOVE) - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename R, typename... Vs> - ASIO_CONSTEXPR typename enable_if< - call_traits<R, void(Vs...)>::overload == call_member, - typename call_traits<R, void(Vs...)>::result_type - >::type - operator()(R&& r, Vs&&... v) const - ASIO_NOEXCEPT_IF(( - call_traits<R, void(Vs...)>::is_noexcept)) - { - return ASIO_MOVE_CAST(R)(r).set_value(ASIO_MOVE_CAST(Vs)(v)...); - } - - template <typename R, typename... Vs> - ASIO_CONSTEXPR typename enable_if< - call_traits<R, void(Vs...)>::overload == call_free, - typename call_traits<R, void(Vs...)>::result_type - >::type - operator()(R&& r, Vs&&... v) const - ASIO_NOEXCEPT_IF(( - call_traits<R, void(Vs...)>::is_noexcept)) - { - return set_value(ASIO_MOVE_CAST(R)(r), - ASIO_MOVE_CAST(Vs)(v)...); - } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R, void()>::overload == call_member, - typename call_traits<R, void()>::result_type - >::type - operator()(R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R, void()>::is_noexcept)) - { - return ASIO_MOVE_CAST(R)(r).set_value(); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R, void()>::overload == call_free, - typename call_traits<R, void()>::result_type - >::type - operator()(R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R, void()>::is_noexcept)) - { - return set_value(ASIO_MOVE_CAST(R)(r)); - } - -#define ASIO_PRIVATE_SET_VALUE_CALL_DEF(n) \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - ASIO_CONSTEXPR typename enable_if< \ - call_traits<R, \ - void(ASIO_VARIADIC_TARGS(n))>::overload == call_member, \ - typename call_traits<R, void(ASIO_VARIADIC_TARGS(n))>::result_type \ - >::type \ - operator()(R&& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - ASIO_NOEXCEPT_IF(( \ - call_traits<R, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ - { \ - return ASIO_MOVE_CAST(R)(r).set_value( \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - ASIO_CONSTEXPR typename enable_if< \ - call_traits<R, void(ASIO_VARIADIC_TARGS(n))>::overload == call_free, \ - typename call_traits<R, void(ASIO_VARIADIC_TARGS(n))>::result_type \ - >::type \ - operator()(R&& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - ASIO_NOEXCEPT_IF(( \ - call_traits<R, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ - { \ - return set_value(ASIO_MOVE_CAST(R)(r), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_CALL_DEF) -#undef ASIO_PRIVATE_SET_VALUE_CALL_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#else // defined(ASIO_HAS_MOVE) - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename R, typename... Vs> - ASIO_CONSTEXPR typename enable_if< - call_traits<R&, void(const Vs&...)>::overload == call_member, - typename call_traits<R&, void(const Vs&...)>::result_type - >::type - operator()(R& r, const Vs&... v) const - ASIO_NOEXCEPT_IF(( - call_traits<R&, void(const Vs&...)>::is_noexcept)) - { - return r.set_value(v...); - } - - template <typename R, typename... Vs> - ASIO_CONSTEXPR typename enable_if< - call_traits<const R&, void(const Vs&...)>::overload == call_member, - typename call_traits<const R&, void(const Vs&...)>::result_type - >::type - operator()(const R& r, const Vs&... v) const - ASIO_NOEXCEPT_IF(( - call_traits<const R&, void(const Vs&...)>::is_noexcept)) - { - return r.set_value(v...); - } - - template <typename R, typename... Vs> - ASIO_CONSTEXPR typename enable_if< - call_traits<R&, void(const Vs&...)>::overload == call_free, - typename call_traits<R&, void(const Vs&...)>::result_type - >::type - operator()(R& r, const Vs&... v) const - ASIO_NOEXCEPT_IF(( - call_traits<R&, void(const Vs&...)>::is_noexcept)) - { - return set_value(r, v...); - } - - template <typename R, typename... Vs> - ASIO_CONSTEXPR typename enable_if< - call_traits<const R&, void(const Vs&...)>::overload == call_free, - typename call_traits<const R&, void(const Vs&...)>::result_type - >::type - operator()(const R& r, const Vs&... v) const - ASIO_NOEXCEPT_IF(( - call_traits<const R&, void(const Vs&...)>::is_noexcept)) - { - return set_value(r, v...); - } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R&, void()>::overload == call_member, - typename call_traits<R&, void()>::result_type - >::type - operator()(R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R&, void()>::is_noexcept)) - { - return r.set_value(); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const R&, void()>::overload == call_member, - typename call_traits<const R&, void()>::result_type - >::type - operator()(const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const R&, void()>::is_noexcept)) - { - return r.set_value(); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R&, void()>::overload == call_free, - typename call_traits<R&, void()>::result_type - >::type - operator()(R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R&, void()>::is_noexcept)) - { - return set_value(r); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const R&, void()>::overload == call_free, - typename call_traits<const R&, void()>::result_type - >::type - operator()(const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const R&, void()>::is_noexcept)) - { - return set_value(r); - } - -#define ASIO_PRIVATE_SET_VALUE_CALL_DEF(n) \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - ASIO_CONSTEXPR typename enable_if< \ - call_traits<R&, \ - void(ASIO_VARIADIC_TARGS(n))>::overload == call_member, \ - typename call_traits<R&, void(ASIO_VARIADIC_TARGS(n))>::result_type \ - >::type \ - operator()(R& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - ASIO_NOEXCEPT_IF(( \ - call_traits<R&, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ - { \ - return r.set_value(ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - ASIO_CONSTEXPR typename enable_if< \ - call_traits<const R&, \ - void(ASIO_VARIADIC_TARGS(n))>::overload == call_member, \ - typename call_traits<const R&, \ - void(ASIO_VARIADIC_TARGS(n))>::result_type \ - >::type \ - operator()(const R& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - ASIO_NOEXCEPT_IF(( \ - call_traits<const R&, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ - { \ - return r.set_value(ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - ASIO_CONSTEXPR typename enable_if< \ - call_traits<R&, \ - void(ASIO_VARIADIC_TARGS(n))>::overload == call_free, \ - typename call_traits<R&, void(ASIO_VARIADIC_TARGS(n))>::result_type \ - >::type \ - operator()(R& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - ASIO_NOEXCEPT_IF(( \ - call_traits<R&, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ - { \ - return set_value(r, ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - ASIO_CONSTEXPR typename enable_if< \ - call_traits<const R&, \ - void(ASIO_VARIADIC_TARGS(n))>::overload == call_free, \ - typename call_traits<const R&, \ - void(ASIO_VARIADIC_TARGS(n))>::result_type \ - >::type \ - operator()(const R& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \ - ASIO_NOEXCEPT_IF(( \ - call_traits<const R&, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \ - { \ - return set_value(r, ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_CALL_DEF) -#undef ASIO_PRIVATE_SET_VALUE_CALL_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#endif // defined(ASIO_HAS_MOVE) -}; - -template <typename T = impl> -struct static_instance -{ - static const T instance; -}; - -template <typename T> -const T static_instance<T>::instance = {}; - -} // namespace asio_execution_set_value_fn -namespace asio { -namespace execution { -namespace { - -static ASIO_CONSTEXPR const asio_execution_set_value_fn::impl& - set_value = asio_execution_set_value_fn::static_instance<>::instance; - -} // namespace - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename R, typename... Vs> -struct can_set_value : - integral_constant<bool, - asio_execution_set_value_fn::call_traits<R, void(Vs...)>::overload != - asio_execution_set_value_fn::ill_formed> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R, typename... Vs> -constexpr bool can_set_value_v = can_set_value<R, Vs...>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R, typename... Vs> -struct is_nothrow_set_value : - integral_constant<bool, - asio_execution_set_value_fn::call_traits<R, void(Vs...)>::is_noexcept> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R, typename... Vs> -constexpr bool is_nothrow_set_value_v - = is_nothrow_set_value<R, Vs...>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename R, typename = void, - typename = void, typename = void, typename = void, typename = void, - typename = void, typename = void, typename = void, typename = void> -struct can_set_value; - -template <typename R, typename = void, - typename = void, typename = void, typename = void, typename = void, - typename = void, typename = void, typename = void, typename = void> -struct is_nothrow_set_value; - -template <typename R> -struct can_set_value<R> : - integral_constant<bool, - asio_execution_set_value_fn::call_traits<R, void()>::overload != - asio_execution_set_value_fn::ill_formed> -{ -}; - -template <typename R> -struct is_nothrow_set_value<R> : - integral_constant<bool, - asio_execution_set_value_fn::call_traits<R, void()>::is_noexcept> -{ -}; - -#define ASIO_PRIVATE_SET_VALUE_TRAITS_DEF(n) \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct can_set_value<R, ASIO_VARIADIC_TARGS(n)> : \ - integral_constant<bool, \ - asio_execution_set_value_fn::call_traits<R, \ - void(ASIO_VARIADIC_TARGS(n))>::overload != \ - asio_execution_set_value_fn::ill_formed> \ - { \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct is_nothrow_set_value<R, ASIO_VARIADIC_TARGS(n)> : \ - integral_constant<bool, \ - asio_execution_set_value_fn::call_traits<R, \ - void(ASIO_VARIADIC_TARGS(n))>::is_noexcept> \ - { \ - }; \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_TRAITS_DEF) -#undef ASIO_PRIVATE_SET_VALUE_TRAITS_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -} // namespace execution -} // namespace asio - -#endif // defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_SET_VALUE_HPP diff --git a/3rdparty/asio/include/asio/execution/start.hpp b/3rdparty/asio/include/asio/execution/start.hpp deleted file mode 100644 index 80592356570..00000000000 --- a/3rdparty/asio/include/asio/execution/start.hpp +++ /dev/null @@ -1,247 +0,0 @@ -// -// execution/start.hpp -// ~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_START_HPP -#define ASIO_EXECUTION_START_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/traits/start_member.hpp" -#include "asio/traits/start_free.hpp" - -#include "asio/detail/push_options.hpp" - -#if defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace execution { - -/// A customisation point that notifies an operation state object to start -/// its associated operation. -/** - * The name <tt>execution::start</tt> denotes a customisation point object. - * The expression <tt>execution::start(R)</tt> for some subexpression - * <tt>R</tt> is expression-equivalent to: - * - * @li <tt>R.start()</tt>, if that expression is valid. - * - * @li Otherwise, <tt>start(R)</tt>, if that expression is valid, with - * overload resolution performed in a context that includes the declaration - * <tt>void start();</tt> and that does not include a declaration of - * <tt>execution::start</tt>. - * - * @li Otherwise, <tt>execution::start(R)</tt> is ill-formed. - */ -inline constexpr unspecified start = unspecified; - -/// A type trait that determines whether a @c start expression is -/// well-formed. -/** - * Class template @c can_start is a trait that is derived from - * @c true_type if the expression <tt>execution::start(std::declval<R>(), - * std::declval<E>())</tt> is well formed; otherwise @c false_type. - */ -template <typename R> -struct can_start : - integral_constant<bool, automatically_determined> -{ -}; - -} // namespace execution -} // namespace asio - -#else // defined(GENERATING_DOCUMENTATION) - -namespace asio_execution_start_fn { - -using asio::decay; -using asio::declval; -using asio::enable_if; -using asio::traits::start_free; -using asio::traits::start_member; - -void start(); - -enum overload_type -{ - call_member, - call_free, - ill_formed -}; - -template <typename R, typename = void, typename = void> -struct call_traits -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef void result_type; -}; - -template <typename R> -struct call_traits<R, - typename enable_if< - start_member<R>::is_valid - >::type> : - start_member<R> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); -}; - -template <typename R> -struct call_traits<R, - typename enable_if< - !start_member<R>::is_valid - >::type, - typename enable_if< - start_free<R>::is_valid - >::type> : - start_free<R> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); -}; - -struct impl -{ -#if defined(ASIO_HAS_MOVE) - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R>::overload == call_member, - typename call_traits<R>::result_type - >::type - operator()(R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R>::is_noexcept)) - { - return ASIO_MOVE_CAST(R)(r).start(); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R>::overload == call_free, - typename call_traits<R>::result_type - >::type - operator()(R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R>::is_noexcept)) - { - return start(ASIO_MOVE_CAST(R)(r)); - } -#else // defined(ASIO_HAS_MOVE) - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R&>::overload == call_member, - typename call_traits<R&>::result_type - >::type - operator()(R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R&>::is_noexcept)) - { - return r.start(); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const R&>::overload == call_member, - typename call_traits<const R&>::result_type - >::type - operator()(const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const R&>::is_noexcept)) - { - return r.start(); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<R&>::overload == call_free, - typename call_traits<R&>::result_type - >::type - operator()(R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<R&>::is_noexcept)) - { - return start(r); - } - - template <typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const R&>::overload == call_free, - typename call_traits<const R&>::result_type - >::type - operator()(const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const R&>::is_noexcept)) - { - return start(r); - } -#endif // defined(ASIO_HAS_MOVE) -}; - -template <typename T = impl> -struct static_instance -{ - static const T instance; -}; - -template <typename T> -const T static_instance<T>::instance = {}; - -} // namespace asio_execution_start_fn -namespace asio { -namespace execution { -namespace { - -static ASIO_CONSTEXPR const asio_execution_start_fn::impl& - start = asio_execution_start_fn::static_instance<>::instance; - -} // namespace - -template <typename R> -struct can_start : - integral_constant<bool, - asio_execution_start_fn::call_traits<R>::overload != - asio_execution_start_fn::ill_formed> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R> -constexpr bool can_start_v = can_start<R>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R> -struct is_nothrow_start : - integral_constant<bool, - asio_execution_start_fn::call_traits<R>::is_noexcept> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename R> -constexpr bool is_nothrow_start_v - = is_nothrow_start<R>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -} // namespace execution -} // namespace asio - -#endif // defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_START_HPP diff --git a/3rdparty/asio/include/asio/execution/submit.hpp b/3rdparty/asio/include/asio/execution/submit.hpp deleted file mode 100644 index 7a0bddf83be..00000000000 --- a/3rdparty/asio/include/asio/execution/submit.hpp +++ /dev/null @@ -1,450 +0,0 @@ -// -// execution/submit.hpp -// ~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXECUTION_SUBMIT_HPP -#define ASIO_EXECUTION_SUBMIT_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/execution/detail/submit_receiver.hpp" -#include "asio/execution/executor.hpp" -#include "asio/execution/receiver.hpp" -#include "asio/execution/sender.hpp" -#include "asio/execution/start.hpp" -#include "asio/traits/submit_member.hpp" -#include "asio/traits/submit_free.hpp" - -#include "asio/detail/push_options.hpp" - -#if defined(GENERATING_DOCUMENTATION) - -namespace asio { -namespace execution { - -/// A customisation point that submits a sender to a receiver. -/** - * The name <tt>execution::submit</tt> denotes a customisation point object. For - * some subexpressions <tt>s</tt> and <tt>r</tt>, let <tt>S</tt> be a type such - * that <tt>decltype((s))</tt> is <tt>S</tt> and let <tt>R</tt> be a type such - * that <tt>decltype((r))</tt> is <tt>R</tt>. The expression - * <tt>execution::submit(s, r)</tt> is ill-formed if <tt>sender_to<S, R></tt> is - * not <tt>true</tt>. Otherwise, it is expression-equivalent to: - * - * @li <tt>s.submit(r)</tt>, if that expression is valid and <tt>S</tt> models - * <tt>sender</tt>. If the function selected does not submit the receiver - * object <tt>r</tt> via the sender <tt>s</tt>, the program is ill-formed with - * no diagnostic required. - * - * @li Otherwise, <tt>submit(s, r)</tt>, if that expression is valid and - * <tt>S</tt> models <tt>sender</tt>, with overload resolution performed in a - * context that includes the declaration <tt>void submit();</tt> and that does - * not include a declaration of <tt>execution::submit</tt>. If the function - * selected by overload resolution does not submit the receiver object - * <tt>r</tt> via the sender <tt>s</tt>, the program is ill-formed with no - * diagnostic required. - * - * @li Otherwise, <tt>execution::start((new submit_receiver<S, - * R>{s,r})->state_)</tt>, where <tt>submit_receiver</tt> is an - * implementation-defined class template equivalent to: - * @code template<class S, class R> - * struct submit_receiver { - * struct wrap { - * submit_receiver * p_; - * template<class...As> - * requires receiver_of<R, As...> - * void set_value(As&&... as) && - * noexcept(is_nothrow_receiver_of_v<R, As...>) { - * execution::set_value(std::move(p_->r_), (As&&) as...); - * delete p_; - * } - * template<class E> - * requires receiver<R, E> - * void set_error(E&& e) && noexcept { - * execution::set_error(std::move(p_->r_), (E&&) e); - * delete p_; - * } - * void set_done() && noexcept { - * execution::set_done(std::move(p_->r_)); - * delete p_; - * } - * }; - * remove_cvref_t<R> r_; - * connect_result_t<S, wrap> state_; - * submit_receiver(S&& s, R&& r) - * : r_((R&&) r) - * , state_(execution::connect((S&&) s, wrap{this})) {} - * }; - * @endcode - */ -inline constexpr unspecified submit = unspecified; - -/// A type trait that determines whether a @c submit expression is -/// well-formed. -/** - * Class template @c can_submit is a trait that is derived from - * @c true_type if the expression <tt>execution::submit(std::declval<R>(), - * std::declval<E>())</tt> is well formed; otherwise @c false_type. - */ -template <typename S, typename R> -struct can_submit : - integral_constant<bool, automatically_determined> -{ -}; - -} // namespace execution -} // namespace asio - -#else // defined(GENERATING_DOCUMENTATION) - -namespace asio_execution_submit_fn { - -using asio::declval; -using asio::enable_if; -using asio::execution::is_sender_to; -using asio::traits::submit_free; -using asio::traits::submit_member; - -void submit(); - -enum overload_type -{ - call_member, - call_free, - adapter, - ill_formed -}; - -template <typename S, typename R, typename = void, - typename = void, typename = void> -struct call_traits -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef void result_type; -}; - -template <typename S, typename R> -struct call_traits<S, void(R), - typename enable_if< - submit_member<S, R>::is_valid - >::type, - typename enable_if< - is_sender_to<S, R>::value - >::type> : - submit_member<S, R> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); -}; - -template <typename S, typename R> -struct call_traits<S, void(R), - typename enable_if< - !submit_member<S, R>::is_valid - >::type, - typename enable_if< - submit_free<S, R>::is_valid - >::type, - typename enable_if< - is_sender_to<S, R>::value - >::type> : - submit_free<S, R> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); -}; - -template <typename S, typename R> -struct call_traits<S, void(R), - typename enable_if< - !submit_member<S, R>::is_valid - >::type, - typename enable_if< - !submit_free<S, R>::is_valid - >::type, - typename enable_if< - is_sender_to<S, R>::value - >::type> -{ - ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef void result_type; -}; - -struct impl -{ -#if defined(ASIO_HAS_MOVE) - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(R)>::overload == call_member, - typename call_traits<S, void(R)>::result_type - >::type - operator()(S&& s, R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(R)>::is_noexcept)) - { - return ASIO_MOVE_CAST(S)(s).submit(ASIO_MOVE_CAST(R)(r)); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(R)>::overload == call_free, - typename call_traits<S, void(R)>::result_type - >::type - operator()(S&& s, R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(R)>::is_noexcept)) - { - return submit(ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(R)(r)); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S, void(R)>::overload == adapter, - typename call_traits<S, void(R)>::result_type - >::type - operator()(S&& s, R&& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S, void(R)>::is_noexcept)) - { - return asio::execution::start( - (new asio::execution::detail::submit_receiver<S, R>( - ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(R)(r)))->state_); - } -#else // defined(ASIO_HAS_MOVE) - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(R&)>::overload == call_member, - typename call_traits<S&, void(R&)>::result_type - >::type - operator()(S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(R&)>::is_noexcept)) - { - return s.submit(r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(R&)>::overload == call_member, - typename call_traits<const S&, void(R&)>::result_type - >::type - operator()(const S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(R&)>::is_noexcept)) - { - return s.submit(r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(R&)>::overload == call_free, - typename call_traits<S&, void(R&)>::result_type - >::type - operator()(S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(R&)>::is_noexcept)) - { - return submit(s, r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(R&)>::overload == call_free, - typename call_traits<const S&, void(R&)>::result_type - >::type - operator()(const S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(R&)>::is_noexcept)) - { - return submit(s, r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(R&)>::overload == adapter, - typename call_traits<S&, void(R&)>::result_type - >::type - operator()(S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(R&)>::is_noexcept)) - { - return asio::execution::start( - (new asio::execution::detail::submit_receiver< - S&, R&>(s, r))->state_); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(R&)>::overload == adapter, - typename call_traits<const S&, void(R&)>::result_type - >::type - operator()(const S& s, R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(R&)>::is_noexcept)) - { - asio::execution::start( - (new asio::execution::detail::submit_receiver< - const S&, R&>(s, r))->state_); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(const R&)>::overload == call_member, - typename call_traits<S&, void(const R&)>::result_type - >::type - operator()(S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(const R&)>::is_noexcept)) - { - return s.submit(r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(const R&)>::overload == call_member, - typename call_traits<const S&, void(const R&)>::result_type - >::type - operator()(const S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(const R&)>::is_noexcept)) - { - return s.submit(r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(const R&)>::overload == call_free, - typename call_traits<S&, void(const R&)>::result_type - >::type - operator()(S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(const R&)>::is_noexcept)) - { - return submit(s, r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(const R&)>::overload == call_free, - typename call_traits<const S&, void(const R&)>::result_type - >::type - operator()(const S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(const R&)>::is_noexcept)) - { - return submit(s, r); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<S&, void(const R&)>::overload == adapter, - typename call_traits<S&, void(const R&)>::result_type - >::type - operator()(S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<S&, void(const R&)>::is_noexcept)) - { - asio::execution::start( - (new asio::execution::detail::submit_receiver< - S&, const R&>(s, r))->state_); - } - - template <typename S, typename R> - ASIO_CONSTEXPR typename enable_if< - call_traits<const S&, void(const R&)>::overload == adapter, - typename call_traits<const S&, void(const R&)>::result_type - >::type - operator()(const S& s, const R& r) const - ASIO_NOEXCEPT_IF(( - call_traits<const S&, void(const R&)>::is_noexcept)) - { - asio::execution::start( - (new asio::execution::detail::submit_receiver< - const S&, const R&>(s, r))->state_); - } -#endif // defined(ASIO_HAS_MOVE) -}; - -template <typename T = impl> -struct static_instance -{ - static const T instance; -}; - -template <typename T> -const T static_instance<T>::instance = {}; - -} // namespace asio_execution_submit_fn -namespace asio { -namespace execution { -namespace { - -static ASIO_CONSTEXPR const asio_execution_submit_fn::impl& - submit = asio_execution_submit_fn::static_instance<>::instance; - -} // namespace - -template <typename S, typename R> -struct can_submit : - integral_constant<bool, - asio_execution_submit_fn::call_traits<S, void(R)>::overload != - asio_execution_submit_fn::ill_formed> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename R> -constexpr bool can_submit_v = can_submit<S, R>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename R> -struct is_nothrow_submit : - integral_constant<bool, - asio_execution_submit_fn::call_traits<S, void(R)>::is_noexcept> -{ -}; - -#if defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename R> -constexpr bool is_nothrow_submit_v - = is_nothrow_submit<S, R>::value; - -#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) - -template <typename S, typename R> -struct submit_result -{ - typedef typename asio_execution_submit_fn::call_traits< - S, void(R)>::result_type type; -}; - -namespace detail { - -template <typename S, typename R> -void submit_helper(ASIO_MOVE_ARG(S) s, ASIO_MOVE_ARG(R) r) -{ - execution::submit(ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(R)(r)); -} - -} // namespace detail -} // namespace execution -} // namespace asio - -#endif // defined(GENERATING_DOCUMENTATION) - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXECUTION_SUBMIT_HPP diff --git a/3rdparty/asio/include/asio/execution_context.hpp b/3rdparty/asio/include/asio/execution_context.hpp index e1ee67a28c7..bce8d431607 100644 --- a/3rdparty/asio/include/asio/execution_context.hpp +++ b/3rdparty/asio/include/asio/execution_context.hpp @@ -2,7 +2,7 @@ // execution_context.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,7 +20,6 @@ #include <stdexcept> #include <typeinfo> #include "asio/detail/noncopyable.hpp" -#include "asio/detail/variadic_templates.hpp" #include "asio/detail/push_options.hpp" @@ -224,8 +223,6 @@ public: 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. @@ -241,27 +238,6 @@ public: template <typename Service, typename... Args> friend Service& make_service(execution_context& e, Args&&... args); -#elif defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Service, typename... Args> - friend Service& make_service(execution_context& e, - ASIO_MOVE_ARG(Args)... args); - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Service> - friend Service& make_service(execution_context& e); - -#define ASIO_PRIVATE_MAKE_SERVICE_DEF(n) \ - template <typename Service, ASIO_VARIADIC_TPARAMS(n)> \ - friend Service& make_service(execution_context& e, \ - ASIO_VARIADIC_MOVE_PARAMS(n)); \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_MAKE_SERVICE_DEF) -#undef ASIO_PRIVATE_MAKE_SERVICE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - /// (Deprecated: Use make_service().) Add a service object to the /// execution_context. /** diff --git a/3rdparty/asio/include/asio/executor.hpp b/3rdparty/asio/include/asio/executor.hpp index 419fdcae653..c056525460a 100644 --- a/3rdparty/asio/include/asio/executor.hpp +++ b/3rdparty/asio/include/asio/executor.hpp @@ -2,7 +2,7 @@ // executor.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,6 +19,7 @@ #if !defined(ASIO_NO_TS_EXECUTORS) +#include <new> #include <typeinfo> #include "asio/detail/cstddef.hpp" #include "asio/detail/executor_function.hpp" @@ -36,11 +37,11 @@ class bad_executor { public: /// Constructor. - ASIO_DECL bad_executor() ASIO_NOEXCEPT; + ASIO_DECL bad_executor() noexcept; /// Obtain message associated with exception. ASIO_DECL virtual const char* what() const - ASIO_NOEXCEPT_OR_NOTHROW; + noexcept; }; /// Polymorphic wrapper for executors. @@ -48,36 +49,53 @@ class executor { public: /// Default constructor. - executor() ASIO_NOEXCEPT + executor() noexcept : impl_(0) { } /// Construct from nullptr. - executor(nullptr_t) ASIO_NOEXCEPT + executor(nullptr_t) noexcept : impl_(0) { } /// Copy constructor. - executor(const executor& other) ASIO_NOEXCEPT + executor(const executor& other) noexcept : impl_(other.clone()) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. - executor(executor&& other) ASIO_NOEXCEPT + executor(executor&& other) noexcept : impl_(other.impl_) { other.impl_ = 0; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Construct a polymorphic wrapper for the specified executor. template <typename Executor> executor(Executor e); + /// Construct a polymorphic executor that points to the same target as + /// another polymorphic executor. + executor(std::nothrow_t, const executor& other) noexcept + : impl_(other.clone()) + { + } + + /// Construct a polymorphic executor that moves the target from another + /// polymorphic executor. + executor(std::nothrow_t, executor&& other) noexcept + : impl_(other.impl_) + { + other.impl_ = 0; + } + + /// Construct a polymorphic wrapper for the specified executor. + template <typename Executor> + executor(std::nothrow_t, Executor e) noexcept; + /// Allocator-aware constructor to create a polymorphic wrapper for the /// specified executor. template <typename Executor, typename Allocator> @@ -90,26 +108,24 @@ public: } /// Assignment operator. - executor& operator=(const executor& other) ASIO_NOEXCEPT + executor& operator=(const executor& other) noexcept { destroy(); impl_ = other.clone(); return *this; } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) // Move assignment operator. - executor& operator=(executor&& other) ASIO_NOEXCEPT + executor& operator=(executor&& other) noexcept { destroy(); impl_ = other.impl_; other.impl_ = 0; return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Assignment operator for nullptr_t. - executor& operator=(nullptr_t) ASIO_NOEXCEPT + executor& operator=(nullptr_t) noexcept { destroy(); impl_ = 0; @@ -119,9 +135,9 @@ public: /// Assignment operator to create a polymorphic wrapper for the specified /// executor. template <typename Executor> - executor& operator=(ASIO_MOVE_ARG(Executor) e) ASIO_NOEXCEPT + executor& operator=(Executor&& e) noexcept { - executor tmp(ASIO_MOVE_CAST(Executor)(e)); + executor tmp(static_cast<Executor&&>(e)); destroy(); impl_ = tmp.impl_; tmp.impl_ = 0; @@ -129,19 +145,19 @@ public: } /// Obtain the underlying execution context. - execution_context& context() const ASIO_NOEXCEPT + execution_context& context() const noexcept { return get_impl()->context(); } /// Inform the executor that it has some outstanding work to do. - void on_work_started() const ASIO_NOEXCEPT + void on_work_started() const noexcept { get_impl()->on_work_started(); } /// Inform the executor that some work is no longer outstanding. - void on_work_finished() const ASIO_NOEXCEPT + void on_work_finished() const noexcept { get_impl()->on_work_finished(); } @@ -160,7 +176,7 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename Allocator> - void dispatch(ASIO_MOVE_ARG(Function) f, const Allocator& a) const; + void dispatch(Function&& f, const Allocator& a) const; /// Request the executor to invoke the given function object. /** @@ -176,7 +192,7 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename Allocator> - void post(ASIO_MOVE_ARG(Function) f, const Allocator& a) const; + void post(Function&& f, const Allocator& a) const; /// Request the executor to invoke the given function object. /** @@ -192,14 +208,14 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename Allocator> - void defer(ASIO_MOVE_ARG(Function) f, const Allocator& a) const; + void defer(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 ASIO_NOEXCEPT + operator unspecified_bool_type() const noexcept { return impl_ ? &executor::unspecified_bool_true : 0; } @@ -210,12 +226,12 @@ public: * otherwise, <tt>typeid(void)</tt>. */ #if !defined(ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION) - const std::type_info& target_type() const ASIO_NOEXCEPT + const std::type_info& target_type() const noexcept { return impl_ ? impl_->target_type() : typeid(void); } #else // !defined(ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION) - const void* target_type() const ASIO_NOEXCEPT + const void* target_type() const noexcept { return impl_ ? impl_->target_type() : 0; } @@ -227,7 +243,7 @@ public: * executor target; otherwise, a null pointer. */ template <typename Executor> - Executor* target() ASIO_NOEXCEPT; + Executor* target() noexcept; /// Obtain a pointer to the target executor object. /** @@ -235,11 +251,11 @@ public: * executor target; otherwise, a null pointer. */ template <typename Executor> - const Executor* target() const ASIO_NOEXCEPT; + const Executor* target() const noexcept; /// Compare two executors for equality. friend bool operator==(const executor& a, - const executor& b) ASIO_NOEXCEPT + const executor& b) noexcept { if (a.impl_ == b.impl_) return true; @@ -250,7 +266,7 @@ public: /// Compare two executors for inequality. friend bool operator!=(const executor& a, - const executor& b) ASIO_NOEXCEPT + const executor& b) noexcept { return !(a == b); } @@ -281,18 +297,18 @@ private: class impl_base { public: - virtual impl_base* clone() const ASIO_NOEXCEPT = 0; - virtual void destroy() ASIO_NOEXCEPT = 0; - virtual execution_context& context() ASIO_NOEXCEPT = 0; - virtual void on_work_started() ASIO_NOEXCEPT = 0; - virtual void on_work_finished() ASIO_NOEXCEPT = 0; - virtual void dispatch(ASIO_MOVE_ARG(function)) = 0; - virtual void post(ASIO_MOVE_ARG(function)) = 0; - virtual void defer(ASIO_MOVE_ARG(function)) = 0; - virtual type_id_result_type target_type() const ASIO_NOEXCEPT = 0; - virtual void* target() ASIO_NOEXCEPT = 0; - virtual const void* target() const ASIO_NOEXCEPT = 0; - virtual bool equals(const impl_base* e) const ASIO_NOEXCEPT = 0; + virtual impl_base* clone() const noexcept = 0; + virtual void destroy() noexcept = 0; + virtual execution_context& context() noexcept = 0; + virtual void on_work_started() noexcept = 0; + virtual void on_work_finished() noexcept = 0; + virtual void dispatch(function&&) = 0; + virtual void post(function&&) = 0; + virtual void defer(function&&) = 0; + virtual type_id_result_type target_type() const noexcept = 0; + virtual void* target() noexcept = 0; + virtual const void* target() const noexcept = 0; + virtual bool equals(const impl_base* e) const noexcept = 0; protected: impl_base(bool fast_dispatch) : fast_dispatch_(fast_dispatch) {} @@ -315,13 +331,13 @@ private: } // Helper function to clone another implementation. - impl_base* clone() const ASIO_NOEXCEPT + impl_base* clone() const noexcept { return impl_ ? impl_->clone() : 0; } // Helper function to destroy an implementation. - void destroy() ASIO_NOEXCEPT + void destroy() noexcept { if (impl_) impl_->destroy(); diff --git a/3rdparty/asio/include/asio/executor_work_guard.hpp b/3rdparty/asio/include/asio/executor_work_guard.hpp index 63837cb7458..72787ccdc83 100644 --- a/3rdparty/asio/include/asio/executor_work_guard.hpp +++ b/3rdparty/asio/include/asio/executor_work_guard.hpp @@ -2,7 +2,7 @@ // executor_work_guard.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,8 +17,6 @@ #include "asio/detail/config.hpp" -#if !defined(ASIO_NO_TS_EXECUTORS) - #include "asio/associated_executor.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution.hpp" @@ -36,13 +34,11 @@ class executor_work_guard; #endif // !defined(ASIO_EXECUTOR_WORK_GUARD_DECL) -/// An object of type @c executor_work_guard controls ownership of executor work -/// within a scope. #if defined(GENERATING_DOCUMENTATION) + +/// An object of type @c executor_work_guard controls ownership of outstanding +/// executor work within a scope. template <typename Executor> -#else // defined(GENERATING_DOCUMENTATION) -template <typename Executor, typename, typename> -#endif // defined(GENERATING_DOCUMENTATION) class executor_work_guard { public: @@ -53,15 +49,58 @@ public: /** * Stores a copy of @c e and calls <tt>on_work_started()</tt> on it. */ - explicit executor_work_guard(const executor_type& e) ASIO_NOEXCEPT + explicit executor_work_guard(const executor_type& e) noexcept; + + /// Copy constructor. + executor_work_guard(const executor_work_guard& other) noexcept; + + /// Move constructor. + executor_work_guard(executor_work_guard&& other) noexcept; + + /// Destructor. + /** + * Unless the object has already been reset, or is in a moved-from state, + * calls <tt>on_work_finished()</tt> on the stored executor. + */ + ~executor_work_guard(); + + /// Obtain the associated executor. + executor_type get_executor() const noexcept; + + /// Whether the executor_work_guard object owns some outstanding work. + bool owns_work() const noexcept; + + /// Indicate that the work is no longer outstanding. + /** + * Unless the object has already been reset, or is in a moved-from state, + * calls <tt>on_work_finished()</tt> on the stored executor. + */ + void reset() noexcept; +}; + +#endif // defined(GENERATING_DOCUMENTATION) + +#if !defined(GENERATING_DOCUMENTATION) + +#if !defined(ASIO_NO_TS_EXECUTORS) + +template <typename Executor> +class executor_work_guard<Executor, + enable_if_t< + is_executor<Executor>::value + >> +{ +public: + typedef Executor executor_type; + + explicit executor_work_guard(const executor_type& e) noexcept : executor_(e), owns_(true) { executor_.on_work_started(); } - /// Copy constructor. - executor_work_guard(const executor_work_guard& other) ASIO_NOEXCEPT + executor_work_guard(const executor_work_guard& other) noexcept : executor_(other.executor_), owns_(other.owns_) { @@ -69,45 +108,30 @@ public: executor_.on_work_started(); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) - /// Move constructor. - executor_work_guard(executor_work_guard&& other) ASIO_NOEXCEPT - : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)), + executor_work_guard(executor_work_guard&& other) noexcept + : executor_(static_cast<Executor&&>(other.executor_)), owns_(other.owns_) { other.owns_ = false; } -#endif // defined(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 ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return executor_; } - /// Whether the executor_work_guard object owns some outstanding work. - bool owns_work() const ASIO_NOEXCEPT + bool owns_work() const noexcept { return owns_; } - /// Indicate that the work is no longer outstanding. - /** - * Unless the object has already been reset, or is in a moved-from state, - * calls <tt>on_work_finished()</tt> on the stored executor. - */ - void reset() ASIO_NOEXCEPT + void reset() noexcept { if (owns_) { @@ -124,21 +148,21 @@ private: bool owns_; }; -#if !defined(GENERATING_DOCUMENTATION) +#endif // !defined(ASIO_NO_TS_EXECUTORS) template <typename Executor> class executor_work_guard<Executor, - typename enable_if< + enable_if_t< !is_executor<Executor>::value - >::type, - typename enable_if< + >, + enable_if_t< execution::is_executor<Executor>::value - >::type> + >> { public: typedef Executor executor_type; - explicit executor_work_guard(const executor_type& e) ASIO_NOEXCEPT + explicit executor_work_guard(const executor_type& e) noexcept : executor_(e), owns_(true) { @@ -146,7 +170,7 @@ public: execution::outstanding_work.tracked)); } - executor_work_guard(const executor_work_guard& other) ASIO_NOEXCEPT + executor_work_guard(const executor_work_guard& other) noexcept : executor_(other.executor_), owns_(other.owns_) { @@ -157,21 +181,19 @@ public: } } -#if defined(ASIO_HAS_MOVE) - executor_work_guard(executor_work_guard&& other) ASIO_NOEXCEPT - : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)), + executor_work_guard(executor_work_guard&& other) noexcept + : executor_(static_cast<Executor&&>(other.executor_)), owns_(other.owns_) { if (owns_) { new (&work_) work_type( - ASIO_MOVE_CAST(work_type)( + static_cast<work_type&&>( *static_cast<work_type*>( static_cast<void*>(&other.work_)))); other.owns_ = false; } } -#endif // defined(ASIO_HAS_MOVE) ~executor_work_guard() { @@ -179,17 +201,17 @@ public: static_cast<work_type*>(static_cast<void*>(&work_))->~work_type(); } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return executor_; } - bool owns_work() const ASIO_NOEXCEPT + bool owns_work() const noexcept { return owns_; } - void reset() ASIO_NOEXCEPT + void reset() noexcept { if (owns_) { @@ -202,93 +224,133 @@ private: // Disallow assignment. executor_work_guard& operator=(const executor_work_guard&); - typedef typename decay< - typename prefer_result< + typedef decay_t< + prefer_result_t< const executor_type&, execution::outstanding_work_t::tracked_t - >::type - >::type work_type; + > + > work_type; executor_type executor_; - typename aligned_storage<sizeof(work_type), - alignment_of<work_type>::value>::type work_; + aligned_storage_t<sizeof(work_type), alignment_of<work_type>::value> work_; bool owns_; }; #endif // !defined(GENERATING_DOCUMENTATION) /// Create an @ref executor_work_guard object. +/** + * @param ex An executor. + * + * @returns A work guard constructed with the specified executor. + */ template <typename Executor> -inline executor_work_guard<Executor> make_work_guard(const Executor& ex, - typename constraint< +ASIO_NODISCARD inline executor_work_guard<Executor> +make_work_guard(const Executor& ex, + constraint_t< is_executor<Executor>::value || execution::is_executor<Executor>::value - >::type = 0) + > = 0) { return executor_work_guard<Executor>(ex); } /// Create an @ref executor_work_guard object. +/** + * @param ctx An execution context, from which an executor will be obtained. + * + * @returns A work guard constructed with the execution context's executor, + * obtained by performing <tt>ctx.get_executor()</tt>. + */ template <typename ExecutionContext> -inline executor_work_guard<typename ExecutionContext::executor_type> +ASIO_NODISCARD inline +executor_work_guard<typename ExecutionContext::executor_type> make_work_guard(ExecutionContext& ctx, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) { return executor_work_guard<typename ExecutionContext::executor_type>( ctx.get_executor()); } /// Create an @ref executor_work_guard object. +/** + * @param t An arbitrary object, such as a completion handler, for which the + * associated executor will be obtained. + * + * @returns A work guard constructed with the associated executor of the object + * @c t, which is obtained as if by calling <tt>get_associated_executor(t)</tt>. + */ template <typename T> -inline executor_work_guard<typename associated_executor<T>::type> -make_work_guard(const T& t, - typename constraint< +ASIO_NODISCARD inline +executor_work_guard< + typename constraint_t< !is_executor<T>::value - >::type = 0, - typename constraint< - !execution::is_executor<T>::value - >::type = 0, - typename constraint< - !is_convertible<T&, execution_context&>::value - >::type = 0) + && !execution::is_executor<T>::value + && !is_convertible<T&, execution_context&>::value, + associated_executor<T> + >::type> +make_work_guard(const T& t) { - return executor_work_guard<typename associated_executor<T>::type>( + return executor_work_guard<associated_executor_t<T>>( associated_executor<T>::get(t)); } /// Create an @ref executor_work_guard object. +/** + * @param t An arbitrary object, such as a completion handler, for which the + * associated executor will be obtained. + * + * @param ex An executor to be used as the candidate object when determining the + * associated executor. + * + * @returns A work guard constructed with the associated executor of the object + * @c t, which is obtained as if by calling <tt>get_associated_executor(t, + * ex)</tt>. + */ template <typename T, typename Executor> -inline executor_work_guard<typename associated_executor<T, Executor>::type> +ASIO_NODISCARD inline +executor_work_guard<associated_executor_t<T, Executor>> make_work_guard(const T& t, const Executor& ex, - typename constraint< + constraint_t< is_executor<Executor>::value || execution::is_executor<Executor>::value - >::type = 0) + > = 0) { - return executor_work_guard<typename associated_executor<T, Executor>::type>( + return executor_work_guard<associated_executor_t<T, Executor>>( associated_executor<T, Executor>::get(t, ex)); } /// Create an @ref executor_work_guard object. +/** + * @param t An arbitrary object, such as a completion handler, for which the + * associated executor will be obtained. + * + * @param ctx An execution context, from which an executor is obtained to use as + * the candidate object for determining the associated executor. + * + * @returns A work guard constructed with the associated executor of the object + * @c t, which is obtained as if by calling <tt>get_associated_executor(t, + * ctx.get_executor())</tt>. + */ template <typename T, typename ExecutionContext> -inline executor_work_guard<typename associated_executor<T, - typename ExecutionContext::executor_type>::type> +ASIO_NODISCARD inline executor_work_guard< + associated_executor_t<T, typename ExecutionContext::executor_type>> make_work_guard(const T& t, ExecutionContext& ctx, - typename constraint< + constraint_t< !is_executor<T>::value - >::type = 0, - typename constraint< + > = 0, + constraint_t< !execution::is_executor<T>::value - >::type = 0, - typename constraint< + > = 0, + constraint_t< !is_convertible<T&, execution_context&>::value - >::type = 0, - typename constraint< + > = 0, + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) { - return executor_work_guard<typename associated_executor<T, - typename ExecutionContext::executor_type>::type>( + return executor_work_guard< + associated_executor_t<T, typename ExecutionContext::executor_type>>( associated_executor<T, typename ExecutionContext::executor_type>::get( t, ctx.get_executor())); } @@ -297,6 +359,4 @@ make_work_guard(const T& t, ExecutionContext& ctx, #include "asio/detail/pop_options.hpp" -#endif // !defined(ASIO_NO_TS_EXECUTORS) - #endif // ASIO_EXECUTOR_WORK_GUARD_HPP diff --git a/3rdparty/asio/include/asio/experimental/append.hpp b/3rdparty/asio/include/asio/experimental/append.hpp index 681d5e34c17..6a1f280cdd9 100644 --- a/3rdparty/asio/include/asio/experimental/append.hpp +++ b/3rdparty/asio/include/asio/experimental/append.hpp @@ -2,7 +2,7 @@ // experimental/append.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,56 +16,21 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" -#include <tuple> -#include "asio/detail/type_traits.hpp" +#include "asio/append.hpp" #include "asio/detail/push_options.hpp" namespace asio { namespace experimental { -/// Completion token type used to specify that the completion handler -/// arguments should be passed additional values after the results of the -/// operation. -template <typename CompletionToken, typename... Values> -class append_t -{ -public: - /// Constructor. - template <typename T, typename... V> - ASIO_CONSTEXPR explicit append_t( - ASIO_MOVE_ARG(T) completion_token, - ASIO_MOVE_ARG(V)... values) - : token_(ASIO_MOVE_CAST(T)(completion_token)), - values_(ASIO_MOVE_CAST(V)(values)...) - { - } - -//private: - CompletionToken token_; - std::tuple<Values...> values_; -}; - -/// Completion token type used to specify that the completion handler -/// arguments should be passed additional values after the results of the -/// operation. -template <typename CompletionToken, typename... Values> -inline ASIO_CONSTEXPR append_t< - typename decay<CompletionToken>::type, typename decay<Values>::type...> -append(ASIO_MOVE_ARG(CompletionToken) completion_token, - ASIO_MOVE_ARG(Values)... values) -{ - return append_t< - typename decay<CompletionToken>::type, typename decay<Values>::type...>( - ASIO_MOVE_CAST(CompletionToken)(completion_token), - ASIO_MOVE_CAST(Values)(values)...); -} +#if !defined(ASIO_NO_DEPRECATED) +using asio::append_t; +using asio::append; +#endif // !defined(ASIO_NO_DEPRECATED) } // namespace experimental } // namespace asio #include "asio/detail/pop_options.hpp" -#include "asio/experimental/impl/append.hpp" - #endif // ASIO_EXPERIMENTAL_APPEND_HPP diff --git a/3rdparty/asio/include/asio/experimental/as_single.hpp b/3rdparty/asio/include/asio/experimental/as_single.hpp index cfd63ad122f..6282c14f142 100644 --- a/3rdparty/asio/include/asio/experimental/as_single.hpp +++ b/3rdparty/asio/include/asio/experimental/as_single.hpp @@ -2,7 +2,7 @@ // experimental/as_single.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,7 +23,7 @@ namespace asio { namespace experimental { -/// Completion token type used to specify that the completion handler +/// A @ref completion_token adapter used to specify that the completion handler /// arguments should be combined into a single argument. /** * The as_single_t class is used to indicate that any arguments to the @@ -47,18 +47,18 @@ public: * token is itself defaulted as an argument to allow it to capture a source * location. */ - ASIO_CONSTEXPR as_single_t( + constexpr as_single_t( default_constructor_tag = default_constructor_tag(), CompletionToken token = CompletionToken()) - : token_(ASIO_MOVE_CAST(CompletionToken)(token)) + : token_(static_cast<CompletionToken&&>(token)) { } /// Constructor. template <typename T> - ASIO_CONSTEXPR explicit as_single_t( - ASIO_MOVE_ARG(T) completion_token) - : token_(ASIO_MOVE_CAST(T)(completion_token)) + constexpr explicit as_single_t( + T&& completion_token) + : token_(static_cast<T&&>(completion_token)) { } @@ -71,7 +71,7 @@ public: typedef as_single_t default_completion_token_type; /// Construct the adapted executor from the inner executor type. - executor_with_default(const InnerExecutor& ex) ASIO_NOEXCEPT + executor_with_default(const InnerExecutor& ex) noexcept : InnerExecutor(ex) { } @@ -80,9 +80,9 @@ public: /// that to construct the adapted executor. template <typename OtherExecutor> executor_with_default(const OtherExecutor& ex, - typename constraint< + constraint_t< is_convertible<OtherExecutor, InnerExecutor>::value - >::type = 0) ASIO_NOEXCEPT + > = 0) noexcept : InnerExecutor(ex) { } @@ -90,39 +90,36 @@ public: /// Type alias to adapt an I/O object to use @c as_single_t as its /// default completion token type. -#if defined(ASIO_HAS_ALIAS_TEMPLATES) \ - || defined(GENERATING_DOCUMENTATION) template <typename T> using as_default_on_t = typename T::template rebind_executor< - executor_with_default<typename T::executor_type> >::other; -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) + executor_with_default<typename T::executor_type>>::other; /// Function helper to adapt an I/O object to use @c as_single_t as its /// default completion token type. template <typename T> - static typename decay<T>::type::template rebind_executor< - executor_with_default<typename decay<T>::type::executor_type> + static typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> >::other - as_default_on(ASIO_MOVE_ARG(T) object) + as_default_on(T&& object) { - return typename decay<T>::type::template rebind_executor< - executor_with_default<typename decay<T>::type::executor_type> - >::other(ASIO_MOVE_CAST(T)(object)); + return typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> + >::other(static_cast<T&&>(object)); } //private: CompletionToken token_; }; -/// Create a completion token to specify that the completion handler arguments -/// should be combined into a single argument. +/// Adapt a @ref completion_token to specify that the completion handler +/// arguments should be combined into a single argument. template <typename CompletionToken> -inline ASIO_CONSTEXPR as_single_t<typename decay<CompletionToken>::type> -as_single(ASIO_MOVE_ARG(CompletionToken) completion_token) +ASIO_NODISCARD inline +constexpr as_single_t<decay_t<CompletionToken>> +as_single(CompletionToken&& completion_token) { - return as_single_t<typename decay<CompletionToken>::type>( - ASIO_MOVE_CAST(CompletionToken)(completion_token)); + return as_single_t<decay_t<CompletionToken>>( + static_cast<CompletionToken&&>(completion_token)); } } // namespace experimental diff --git a/3rdparty/asio/include/asio/experimental/as_tuple.hpp b/3rdparty/asio/include/asio/experimental/as_tuple.hpp index d8ccdafd806..02f23f2909b 100644 --- a/3rdparty/asio/include/asio/experimental/as_tuple.hpp +++ b/3rdparty/asio/include/asio/experimental/as_tuple.hpp @@ -2,7 +2,7 @@ // experimental/as_tuple.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,116 +16,21 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" +#include "asio/as_tuple.hpp" #include "asio/detail/push_options.hpp" namespace asio { namespace experimental { -/// Completion token type used to specify that the completion handler -/// arguments should be combined into a single tuple argument. -/** - * The as_tuple_t class is used to indicate that any arguments to the - * completion handler should be combined and passed as a single tuple argument. - * The arguments are first moved into a @c std::tuple and that tuple is then - * passed to the completion handler. - */ -template <typename CompletionToken> -class as_tuple_t -{ -public: - /// Tag type used to prevent the "default" constructor from being used for - /// conversions. - struct default_constructor_tag {}; - - /// Default constructor. - /** - * This constructor is only valid if the underlying completion token is - * default constructible and move constructible. The underlying completion - * token is itself defaulted as an argument to allow it to capture a source - * location. - */ - ASIO_CONSTEXPR as_tuple_t( - default_constructor_tag = default_constructor_tag(), - CompletionToken token = CompletionToken()) - : token_(ASIO_MOVE_CAST(CompletionToken)(token)) - { - } - - /// Constructor. - template <typename T> - ASIO_CONSTEXPR explicit as_tuple_t( - ASIO_MOVE_ARG(T) completion_token) - : token_(ASIO_MOVE_CAST(T)(completion_token)) - { - } - - /// Adapts an executor to add the @c as_tuple_t completion token as the - /// default. - template <typename InnerExecutor> - struct executor_with_default : InnerExecutor - { - /// Specify @c as_tuple_t as the default completion token type. - typedef as_tuple_t default_completion_token_type; - - /// Construct the adapted executor from the inner executor type. - template <typename InnerExecutor1> - executor_with_default(const InnerExecutor1& ex, - typename constraint< - conditional< - !is_same<InnerExecutor1, executor_with_default>::value, - is_convertible<InnerExecutor1, InnerExecutor>, - false_type - >::type::value - >::type = 0) ASIO_NOEXCEPT - : InnerExecutor(ex) - { - } - }; - - /// Type alias to adapt an I/O object to use @c as_tuple_t as its - /// default completion token type. -#if defined(ASIO_HAS_ALIAS_TEMPLATES) \ - || defined(GENERATING_DOCUMENTATION) - template <typename T> - using as_default_on_t = typename T::template rebind_executor< - executor_with_default<typename T::executor_type> >::other; -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - - /// Function helper to adapt an I/O object to use @c as_tuple_t as its - /// default completion token type. - template <typename T> - static typename decay<T>::type::template rebind_executor< - executor_with_default<typename decay<T>::type::executor_type> - >::other - as_default_on(ASIO_MOVE_ARG(T) object) - { - return typename decay<T>::type::template rebind_executor< - executor_with_default<typename decay<T>::type::executor_type> - >::other(ASIO_MOVE_CAST(T)(object)); - } - -//private: - CompletionToken token_; -}; - -/// Create a completion token to specify that the completion handler arguments -/// should be combined into a single tuple argument. -template <typename CompletionToken> -inline ASIO_CONSTEXPR as_tuple_t<typename decay<CompletionToken>::type> -as_tuple(ASIO_MOVE_ARG(CompletionToken) completion_token) -{ - return as_tuple_t<typename decay<CompletionToken>::type>( - ASIO_MOVE_CAST(CompletionToken)(completion_token)); -} +#if !defined(ASIO_NO_DEPRECATED) +using asio::as_tuple_t; +using asio::as_tuple; +#endif // !defined(ASIO_NO_DEPRECATED) } // namespace experimental } // namespace asio #include "asio/detail/pop_options.hpp" -#include "asio/experimental/impl/as_tuple.hpp" - #endif // ASIO_EXPERIMENTAL_AS_TUPLE_HPP diff --git a/3rdparty/asio/include/asio/experimental/awaitable_operators.hpp b/3rdparty/asio/include/asio/experimental/awaitable_operators.hpp index ddc24c0af82..45799daaa5f 100644 --- a/3rdparty/asio/include/asio/experimental/awaitable_operators.hpp +++ b/3rdparty/asio/include/asio/experimental/awaitable_operators.hpp @@ -2,7 +2,7 @@ // experimental/awaitable_operators.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -21,12 +21,12 @@ #include <tuple> #include <variant> #include "asio/awaitable.hpp" +#include "asio/co_spawn.hpp" #include "asio/detail/type_traits.hpp" #include "asio/experimental/deferred.hpp" #include "asio/experimental/parallel_group.hpp" #include "asio/multiple_exceptions.hpp" #include "asio/this_coro.hpp" -#include "asio/use_awaitable.hpp" #include "asio/detail/push_options.hpp" @@ -37,28 +37,28 @@ namespace detail { template <typename T, typename Executor> awaitable<T, Executor> awaitable_wrap(awaitable<T, Executor> a, - typename constraint<is_constructible<T>::value>::type* = 0) + constraint_t<is_constructible<T>::value>* = 0) { return a; } template <typename T, typename Executor> awaitable<std::optional<T>, Executor> awaitable_wrap(awaitable<T, Executor> a, - typename constraint<!is_constructible<T>::value>::type* = 0) + constraint_t<!is_constructible<T>::value>* = 0) { co_return std::optional<T>(co_await std::move(a)); } template <typename T> -T& awaitable_unwrap(typename conditional<true, T, void>::type& r, - typename constraint<is_constructible<T>::value>::type* = 0) +T& awaitable_unwrap(conditional_t<true, T, void>& r, + constraint_t<is_constructible<T>::value>* = 0) { return r; } template <typename T> -T& awaitable_unwrap(std::optional<typename conditional<true, T, void>::type>& r, - typename constraint<!is_constructible<T>::value>::type* = 0) +T& awaitable_unwrap(std::optional<conditional_t<true, T, void>>& r, + constraint_t<!is_constructible<T>::value>* = 0) { return *r; } @@ -82,7 +82,7 @@ awaitable<void, Executor> operator&&( co_spawn(ex, std::move(u), deferred) ).async_wait( wait_for_one_error(), - use_awaitable_t<Executor>{} + deferred ); if (ex0 && ex1) @@ -111,7 +111,7 @@ awaitable<U, Executor> operator&&( co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred) ).async_wait( wait_for_one_error(), - use_awaitable_t<Executor>{} + deferred ); if (ex0 && ex1) @@ -140,7 +140,7 @@ awaitable<T, Executor> operator&&( co_spawn(ex, std::move(u), deferred) ).async_wait( wait_for_one_error(), - use_awaitable_t<Executor>{} + deferred ); if (ex0 && ex1) @@ -169,7 +169,7 @@ awaitable<std::tuple<T, U>, Executor> operator&&( co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred) ).async_wait( wait_for_one_error(), - use_awaitable_t<Executor>{} + deferred ); if (ex0 && ex1) @@ -200,7 +200,7 @@ awaitable<std::tuple<T..., std::monostate>, Executor> operator&&( co_spawn(ex, std::move(u), deferred) ).async_wait( wait_for_one_error(), - use_awaitable_t<Executor>{} + deferred ); if (ex0 && ex1) @@ -229,7 +229,7 @@ awaitable<std::tuple<T..., U>, Executor> operator&&( co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred) ).async_wait( wait_for_one_error(), - use_awaitable_t<Executor>{} + deferred ); if (ex0 && ex1) @@ -260,7 +260,7 @@ awaitable<std::variant<std::monostate, std::monostate>, Executor> operator||( co_spawn(ex, std::move(u), deferred) ).async_wait( wait_for_one_success(), - use_awaitable_t<Executor>{} + deferred ); if (order[0] == 0) @@ -302,7 +302,7 @@ awaitable<std::variant<std::monostate, U>, Executor> operator||( co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred) ).async_wait( wait_for_one_success(), - use_awaitable_t<Executor>{} + deferred ); if (order[0] == 0) @@ -346,7 +346,7 @@ awaitable<std::variant<T, std::monostate>, Executor> operator||( co_spawn(ex, std::move(u), deferred) ).async_wait( wait_for_one_success(), - use_awaitable_t<Executor>{} + deferred ); if (order[0] == 0) @@ -390,7 +390,7 @@ awaitable<std::variant<T, U>, Executor> operator||( co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred) ).async_wait( wait_for_one_success(), - use_awaitable_t<Executor>{} + deferred ); if (order[0] == 0) @@ -456,7 +456,7 @@ awaitable<std::variant<T..., std::monostate>, Executor> operator||( co_spawn(ex, std::move(u), deferred) ).async_wait( wait_for_one_success(), - use_awaitable_t<Executor>{} + deferred ); using widen = detail::widen_variant<T..., std::monostate>; @@ -499,7 +499,7 @@ awaitable<std::variant<T..., U>, Executor> operator||( co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred) ).async_wait( wait_for_one_success(), - use_awaitable_t<Executor>{} + deferred ); using widen = detail::widen_variant<T..., U>; diff --git a/3rdparty/asio/include/asio/experimental/basic_channel.hpp b/3rdparty/asio/include/asio/experimental/basic_channel.hpp new file mode 100644 index 00000000000..6ca1438a093 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/basic_channel.hpp @@ -0,0 +1,513 @@ +// +// experimental/basic_channel.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_BASIC_CHANNEL_HPP +#define ASIO_EXPERIMENTAL_BASIC_CHANNEL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/non_const_lvalue.hpp" +#include "asio/detail/null_mutex.hpp" +#include "asio/execution/executor.hpp" +#include "asio/execution_context.hpp" +#include "asio/experimental/detail/channel_send_functions.hpp" +#include "asio/experimental/detail/channel_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +} // namespace detail + +/// A channel for messages. +/** + * The basic_channel class template is used for sending messages between + * different parts of the same application. A <em>message</em> is defined as a + * collection of arguments to be passed to a completion handler, and the set of + * messages supported by a channel is specified by its @c Traits and + * <tt>Signatures...</tt> template parameters. Messages may be sent and received + * using asynchronous or non-blocking synchronous operations. + * + * Unless customising the traits, applications will typically use the @c + * experimental::channel alias template. For example: + * @code void send_loop(int i, steady_timer& timer, + * channel<void(error_code, int)>& ch) + * { + * if (i < 10) + * { + * timer.expires_after(chrono::seconds(1)); + * timer.async_wait( + * [i, &timer, &ch](error_code error) + * { + * if (!error) + * { + * ch.async_send(error_code(), i, + * [i, &timer, &ch](error_code error) + * { + * if (!error) + * { + * send_loop(i + 1, timer, ch); + * } + * }); + * } + * }); + * } + * else + * { + * ch.close(); + * } + * } + * + * void receive_loop(channel<void(error_code, int)>& ch) + * { + * ch.async_receive( + * [&ch](error_code error, int i) + * { + * if (!error) + * { + * std::cout << "Received " << i << "\n"; + * receive_loop(ch); + * } + * }); + * } @endcode + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Unsafe. + * + * The basic_channel class template is not thread-safe, and would typically be + * used for passing messages between application code that runs on the same + * thread or in the same strand. Consider using @ref basic_concurrent_channel, + * and its alias template @c experimental::concurrent_channel, to pass messages + * between code running in different threads. + */ +template <typename Executor, typename Traits, typename... Signatures> +class basic_channel +#if !defined(GENERATING_DOCUMENTATION) + : public detail::channel_send_functions< + basic_channel<Executor, Traits, Signatures...>, + Executor, Signatures...> +#endif // !defined(GENERATING_DOCUMENTATION) +{ +private: + class initiate_async_send; + class initiate_async_receive; + typedef detail::channel_service<asio::detail::null_mutex> service_type; + typedef typename service_type::template implementation_type< + Traits, Signatures...>::payload_type payload_type; + + template <typename... PayloadSignatures, + ASIO_COMPLETION_TOKEN_FOR(PayloadSignatures...) CompletionToken> + auto do_async_receive(detail::channel_payload<PayloadSignatures...>*, + CompletionToken&& token) + -> decltype( + async_initiate<CompletionToken, PayloadSignatures...>( + declval<initiate_async_receive>(), token)) + { + return async_initiate<CompletionToken, PayloadSignatures...>( + initiate_async_receive(this), token); + } + +public: + /// The type of the executor associated with the channel. + typedef Executor executor_type; + + /// Rebinds the channel type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The channel type when rebound to the specified executor. + typedef basic_channel<Executor1, Traits, Signatures...> other; + }; + + /// The traits type associated with the channel. + typedef typename Traits::template rebind<Signatures...>::other traits_type; + + /// Construct a basic_channel. + /** + * This constructor creates and channel. + * + * @param ex The I/O executor that the channel will use, by default, to + * dispatch handlers for any asynchronous operations performed on the channel. + * + * @param max_buffer_size The maximum number of messages that may be buffered + * in the channel. + */ + basic_channel(const executor_type& ex, std::size_t max_buffer_size = 0) + : service_(&asio::use_service<service_type>( + basic_channel::get_context(ex))), + impl_(), + executor_(ex) + { + service_->construct(impl_, max_buffer_size); + } + + /// Construct and open a basic_channel. + /** + * This constructor creates and opens a channel. + * + * @param context An execution context which provides the I/O executor that + * the channel will use, by default, to dispatch handlers for any asynchronous + * operations performed on the channel. + * + * @param max_buffer_size The maximum number of messages that may be buffered + * in the channel. + */ + template <typename ExecutionContext> + basic_channel(ExecutionContext& context, std::size_t max_buffer_size = 0, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : service_(&asio::use_service<service_type>(context)), + impl_(), + executor_(context.get_executor()) + { + service_->construct(impl_, max_buffer_size); + } + + /// Move-construct a basic_channel from another. + /** + * This constructor moves a channel from one object to another. + * + * @param other The other basic_channel object from which the move will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_channel(const executor_type&) constructor. + */ + basic_channel(basic_channel&& other) + : service_(other.service_), + executor_(other.executor_) + { + service_->move_construct(impl_, other.impl_); + } + + /// Move-assign a basic_channel from another. + /** + * This assignment operator moves a channel from one object to another. + * Cancels any outstanding asynchronous operations associated with the target + * object. + * + * @param other The other basic_channel object from which the move will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_channel(const executor_type&) + * constructor. + */ + basic_channel& operator=(basic_channel&& other) + { + if (this != &other) + { + service_->move_assign(impl_, *other.service_, other.impl_); + executor_.~executor_type(); + new (&executor_) executor_type(other.executor_); + service_ = other.service_; + } + return *this; + } + + // All channels have access to each other's implementations. + template <typename, typename, typename...> + friend class basic_channel; + + /// Move-construct a basic_channel from another. + /** + * This constructor moves a channel from one object to another. + * + * @param other The other basic_channel object from which the move will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_channel(const executor_type&) + * constructor. + */ + template <typename Executor1> + basic_channel( + basic_channel<Executor1, Traits, Signatures...>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value + > = 0) + : service_(other.service_), + executor_(other.executor_) + { + service_->move_construct(impl_, other.impl_); + } + + /// Move-assign a basic_channel from another. + /** + * This assignment operator moves a channel from one object to another. + * Cancels any outstanding asynchronous operations associated with the target + * object. + * + * @param other The other basic_channel object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_channel(const executor_type&) + * constructor. + */ + template <typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_channel& + > operator=(basic_channel<Executor1, Traits, Signatures...>&& other) + { + if (this != &other) + { + service_->move_assign(impl_, *other.service_, other.impl_); + executor_.~executor_type(); + new (&executor_) executor_type(other.executor_); + service_ = other.service_; + } + return *this; + } + + /// Destructor. + ~basic_channel() + { + service_->destroy(impl_); + } + + /// Get the executor associated with the object. + const executor_type& get_executor() noexcept + { + return executor_; + } + + /// Get the capacity of the channel's buffer. + std::size_t capacity() noexcept + { + return service_->capacity(impl_); + } + + /// Determine whether the channel is open. + bool is_open() const noexcept + { + return service_->is_open(impl_); + } + + /// Reset the channel to its initial state. + void reset() + { + service_->reset(impl_); + } + + /// Close the channel. + void close() + { + service_->close(impl_); + } + + /// Cancel all asynchronous operations waiting on the channel. + /** + * All outstanding send operations will complete with the error + * @c asio::experimental::error::channel_cancelled. Outstanding receive + * operations complete with the result as determined by the channel traits. + */ + void cancel() + { + service_->cancel(impl_); + } + + /// Determine whether a message can be received without blocking. + bool ready() const noexcept + { + return service_->ready(impl_); + } + +#if defined(GENERATING_DOCUMENTATION) + + /// Try to send a message without blocking. + /** + * Fails if the buffer is full and there are no waiting receive operations. + * + * @returns @c true on success, @c false on failure. + */ + template <typename... Args> + bool try_send(Args&&... args); + + /// Try to send a message without blocking, using dispatch semantics to call + /// the receive operation's completion handler. + /** + * Fails if the buffer is full and there are no waiting receive operations. + * + * The receive operation's completion handler may be called from inside this + * function. + * + * @returns @c true on success, @c false on failure. + */ + template <typename... Args> + bool try_send_via_dispatch(Args&&... args); + + /// Try to send a number of messages without blocking. + /** + * @returns The number of messages that were sent. + */ + template <typename... Args> + std::size_t try_send_n(std::size_t count, Args&&... args); + + /// Try to send a number of messages without blocking, using dispatch + /// semantics to call the receive operations' completion handlers. + /** + * The receive operations' completion handlers may be called from inside this + * function. + * + * @returns The number of messages that were sent. + */ + template <typename... Args> + std::size_t try_send_n_via_dispatch(std::size_t count, Args&&... args); + + /// Asynchronously send a message. + /** + * @par Completion Signature + * @code void(asio::error_code) @endcode + */ + template <typename... Args, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) + CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + auto async_send(Args&&... args, + CompletionToken&& token); + +#endif // defined(GENERATING_DOCUMENTATION) + + /// Try to receive a message without blocking. + /** + * Fails if the buffer is full and there are no waiting receive operations. + * + * @returns @c true on success, @c false on failure. + */ + template <typename Handler> + bool try_receive(Handler&& handler) + { + return service_->try_receive(impl_, static_cast<Handler&&>(handler)); + } + + /// Asynchronously receive a message. + /** + * @par Completion Signature + * As determined by the <tt>Signatures...</tt> template parameter and the + * channel traits. + */ + template <typename CompletionToken + ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + auto async_receive( + CompletionToken&& token + ASIO_DEFAULT_COMPLETION_TOKEN(Executor)) +#if !defined(GENERATING_DOCUMENTATION) + -> decltype( + this->do_async_receive(static_cast<payload_type*>(0), + static_cast<CompletionToken&&>(token))) +#endif // !defined(GENERATING_DOCUMENTATION) + { + return this->do_async_receive(static_cast<payload_type*>(0), + static_cast<CompletionToken&&>(token)); + } + +private: + // Disallow copying and assignment. + basic_channel(const basic_channel&) = delete; + basic_channel& operator=(const basic_channel&) = delete; + + template <typename, typename, typename...> + friend class detail::channel_send_functions; + + // Helper function to get an executor's context. + template <typename T> + static execution_context& get_context(const T& t, + enable_if_t<execution::is_executor<T>::value>* = 0) + { + return asio::query(t, execution::context); + } + + // Helper function to get an executor's context. + template <typename T> + static execution_context& get_context(const T& t, + enable_if_t<!execution::is_executor<T>::value>* = 0) + { + return t.context(); + } + + class initiate_async_send + { + public: + typedef Executor executor_type; + + explicit initiate_async_send(basic_channel* self) + : self_(self) + { + } + + const executor_type& get_executor() const noexcept + { + return self_->get_executor(); + } + + template <typename SendHandler> + void operator()(SendHandler&& handler, + payload_type&& payload) const + { + asio::detail::non_const_lvalue<SendHandler> handler2(handler); + self_->service_->async_send(self_->impl_, + static_cast<payload_type&&>(payload), + handler2.value, self_->get_executor()); + } + + private: + basic_channel* self_; + }; + + class initiate_async_receive + { + public: + typedef Executor executor_type; + + explicit initiate_async_receive(basic_channel* self) + : self_(self) + { + } + + const executor_type& get_executor() const noexcept + { + return self_->get_executor(); + } + + template <typename ReceiveHandler> + void operator()(ReceiveHandler&& handler) const + { + asio::detail::non_const_lvalue<ReceiveHandler> handler2(handler); + self_->service_->async_receive(self_->impl_, + handler2.value, self_->get_executor()); + } + + private: + basic_channel* self_; + }; + + // The service associated with the I/O object. + service_type* service_; + + // The underlying implementation of the I/O object. + typename service_type::template implementation_type< + Traits, Signatures...> impl_; + + // The associated executor. + Executor executor_; +}; + +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_BASIC_CHANNEL_HPP diff --git a/3rdparty/asio/include/asio/experimental/basic_concurrent_channel.hpp b/3rdparty/asio/include/asio/experimental/basic_concurrent_channel.hpp new file mode 100644 index 00000000000..9dbfea39527 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/basic_concurrent_channel.hpp @@ -0,0 +1,513 @@ +// +// experimental/basic_concurrent_channel.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_BASIC_CONCURRENT_CHANNEL_HPP +#define ASIO_EXPERIMENTAL_BASIC_CONCURRENT_CHANNEL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/non_const_lvalue.hpp" +#include "asio/detail/mutex.hpp" +#include "asio/execution/executor.hpp" +#include "asio/execution_context.hpp" +#include "asio/experimental/detail/channel_send_functions.hpp" +#include "asio/experimental/detail/channel_service.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +} // namespace detail + +/// A channel for messages. +/** + * The basic_concurrent_channel class template is used for sending messages + * between different parts of the same application. A <em>message</em> is + * defined as a collection of arguments to be passed to a completion handler, + * and the set of messages supported by a channel is specified by its @c Traits + * and <tt>Signatures...</tt> template parameters. Messages may be sent and + * received using asynchronous or non-blocking synchronous operations. + * + * Unless customising the traits, applications will typically use the @c + * experimental::concurrent_channel alias template. For example: + * @code void send_loop(int i, steady_timer& timer, + * concurrent_channel<void(error_code, int)>& ch) + * { + * if (i < 10) + * { + * timer.expires_after(chrono::seconds(1)); + * timer.async_wait( + * [i, &timer, &ch](error_code error) + * { + * if (!error) + * { + * ch.async_send(error_code(), i, + * [i, &timer, &ch](error_code error) + * { + * if (!error) + * { + * send_loop(i + 1, timer, ch); + * } + * }); + * } + * }); + * } + * else + * { + * ch.close(); + * } + * } + * + * void receive_loop(concurent_channel<void(error_code, int)>& ch) + * { + * ch.async_receive( + * [&ch](error_code error, int i) + * { + * if (!error) + * { + * std::cout << "Received " << i << "\n"; + * receive_loop(ch); + * } + * }); + * } @endcode + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * The basic_concurrent_channel class template is thread-safe, and would + * typically be used for passing messages between application code that run on + * different threads. Consider using @ref basic_channel, and its alias template + * @c experimental::channel, to pass messages between code running in a single + * thread or on the same strand. + */ +template <typename Executor, typename Traits, typename... Signatures> +class basic_concurrent_channel +#if !defined(GENERATING_DOCUMENTATION) + : public detail::channel_send_functions< + basic_concurrent_channel<Executor, Traits, Signatures...>, + Executor, Signatures...> +#endif // !defined(GENERATING_DOCUMENTATION) +{ +private: + class initiate_async_send; + class initiate_async_receive; + typedef detail::channel_service<asio::detail::mutex> service_type; + typedef typename service_type::template implementation_type< + Traits, Signatures...>::payload_type payload_type; + + template <typename... PayloadSignatures, + ASIO_COMPLETION_TOKEN_FOR(PayloadSignatures...) CompletionToken> + auto do_async_receive(detail::channel_payload<PayloadSignatures...>*, + CompletionToken&& token) + -> decltype( + async_initiate<CompletionToken, PayloadSignatures...>( + declval<initiate_async_receive>(), token)) + { + return async_initiate<CompletionToken, PayloadSignatures...>( + initiate_async_receive(this), token); + } + +public: + /// The type of the executor associated with the channel. + typedef Executor executor_type; + + /// Rebinds the channel type to another executor. + template <typename Executor1> + struct rebind_executor + { + /// The channel type when rebound to the specified executor. + typedef basic_concurrent_channel<Executor1, Traits, Signatures...> other; + }; + + /// The traits type associated with the channel. + typedef typename Traits::template rebind<Signatures...>::other traits_type; + + /// Construct a basic_concurrent_channel. + /** + * This constructor creates and channel. + * + * @param ex The I/O executor that the channel will use, by default, to + * dispatch handlers for any asynchronous operations performed on the channel. + * + * @param max_buffer_size The maximum number of messages that may be buffered + * in the channel. + */ + basic_concurrent_channel(const executor_type& ex, + std::size_t max_buffer_size = 0) + : service_(&asio::use_service<service_type>( + basic_concurrent_channel::get_context(ex))), + impl_(), + executor_(ex) + { + service_->construct(impl_, max_buffer_size); + } + + /// Construct and open a basic_concurrent_channel. + /** + * This constructor creates and opens a channel. + * + * @param context An execution context which provides the I/O executor that + * the channel will use, by default, to dispatch handlers for any asynchronous + * operations performed on the channel. + * + * @param max_buffer_size The maximum number of messages that may be buffered + * in the channel. + */ + template <typename ExecutionContext> + basic_concurrent_channel(ExecutionContext& context, + std::size_t max_buffer_size = 0, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value, + defaulted_constraint + > = defaulted_constraint()) + : service_(&asio::use_service<service_type>(context)), + impl_(), + executor_(context.get_executor()) + { + service_->construct(impl_, max_buffer_size); + } + + /// Move-construct a basic_concurrent_channel from another. + /** + * This constructor moves a channel from one object to another. + * + * @param other The other basic_concurrent_channel object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_concurrent_channel(const executor_type&) + * constructor. + */ + basic_concurrent_channel(basic_concurrent_channel&& other) + : service_(other.service_), + executor_(other.executor_) + { + service_->move_construct(impl_, other.impl_); + } + + /// Move-assign a basic_concurrent_channel from another. + /** + * This assignment operator moves a channel from one object to another. + * Cancels any outstanding asynchronous operations associated with the target + * object. + * + * @param other The other basic_concurrent_channel object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_concurrent_channel(const executor_type&) + * constructor. + */ + basic_concurrent_channel& operator=(basic_concurrent_channel&& other) + { + if (this != &other) + { + service_->move_assign(impl_, *other.service_, other.impl_); + executor_.~executor_type(); + new (&executor_) executor_type(other.executor_); + service_ = other.service_; + } + return *this; + } + + // All channels have access to each other's implementations. + template <typename, typename, typename...> + friend class basic_concurrent_channel; + + /// Move-construct a basic_concurrent_channel from another. + /** + * This constructor moves a channel from one object to another. + * + * @param other The other basic_concurrent_channel object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_concurrent_channel(const executor_type&) + * constructor. + */ + template <typename Executor1> + basic_concurrent_channel( + basic_concurrent_channel<Executor1, Traits, Signatures...>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value + > = 0) + : service_(other.service_), + executor_(other.executor_) + { + service_->move_construct(impl_, other.impl_); + } + + /// Move-assign a basic_concurrent_channel from another. + /** + * This assignment operator moves a channel from one object to another. + * Cancels any outstanding asynchronous operations associated with the target + * object. + * + * @param other The other basic_concurrent_channel object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_concurrent_channel(const executor_type&) + * constructor. + */ + template <typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_concurrent_channel& + > operator=( + basic_concurrent_channel<Executor1, Traits, Signatures...>&& other) + { + if (this != &other) + { + service_->move_assign(impl_, *other.service_, other.impl_); + executor_.~executor_type(); + new (&executor_) executor_type(other.executor_); + service_ = other.service_; + } + return *this; + } + + /// Destructor. + ~basic_concurrent_channel() + { + service_->destroy(impl_); + } + + /// Get the executor associated with the object. + const executor_type& get_executor() noexcept + { + return executor_; + } + + /// Get the capacity of the channel's buffer. + std::size_t capacity() noexcept + { + return service_->capacity(impl_); + } + + /// Determine whether the channel is open. + bool is_open() const noexcept + { + return service_->is_open(impl_); + } + + /// Reset the channel to its initial state. + void reset() + { + service_->reset(impl_); + } + + /// Close the channel. + void close() + { + service_->close(impl_); + } + + /// Cancel all asynchronous operations waiting on the channel. + /** + * All outstanding send operations will complete with the error + * @c asio::experimental::error::channel_cancelled. Outstanding receive + * operations complete with the result as determined by the channel traits. + */ + void cancel() + { + service_->cancel(impl_); + } + + /// Determine whether a message can be received without blocking. + bool ready() const noexcept + { + return service_->ready(impl_); + } + +#if defined(GENERATING_DOCUMENTATION) + + /// Try to send a message without blocking. + /** + * Fails if the buffer is full and there are no waiting receive operations. + * + * @returns @c true on success, @c false on failure. + */ + template <typename... Args> + bool try_send(Args&&... args); + + /// Try to send a message without blocking, using dispatch semantics to call + /// the receive operation's completion handler. + /** + * Fails if the buffer is full and there are no waiting receive operations. + * + * The receive operation's completion handler may be called from inside this + * function. + * + * @returns @c true on success, @c false on failure. + */ + template <typename... Args> + bool try_send_via_dispatch(Args&&... args); + + /// Try to send a number of messages without blocking. + /** + * @returns The number of messages that were sent. + */ + template <typename... Args> + std::size_t try_send_n(std::size_t count, Args&&... args); + + /// Try to send a number of messages without blocking, using dispatch + /// semantics to call the receive operations' completion handlers. + /** + * The receive operations' completion handlers may be called from inside this + * function. + * + * @returns The number of messages that were sent. + */ + template <typename... Args> + std::size_t try_send_n_via_dispatch(std::size_t count, Args&&... args); + + /// Asynchronously send a message. + template <typename... Args, + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) + CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + auto async_send(Args&&... args, + CompletionToken&& token); + +#endif // defined(GENERATING_DOCUMENTATION) + + /// Try to receive a message without blocking. + /** + * Fails if the buffer is full and there are no waiting receive operations. + * + * @returns @c true on success, @c false on failure. + */ + template <typename Handler> + bool try_receive(Handler&& handler) + { + return service_->try_receive(impl_, static_cast<Handler&&>(handler)); + } + + /// Asynchronously receive a message. + template <typename CompletionToken + ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> + auto async_receive( + CompletionToken&& token + ASIO_DEFAULT_COMPLETION_TOKEN(Executor)) +#if !defined(GENERATING_DOCUMENTATION) + -> decltype( + this->do_async_receive(static_cast<payload_type*>(0), + static_cast<CompletionToken&&>(token))) +#endif // !defined(GENERATING_DOCUMENTATION) + { + return this->do_async_receive(static_cast<payload_type*>(0), + static_cast<CompletionToken&&>(token)); + } + +private: + // Disallow copying and assignment. + basic_concurrent_channel( + const basic_concurrent_channel&) = delete; + basic_concurrent_channel& operator=( + const basic_concurrent_channel&) = delete; + + template <typename, typename, typename...> + friend class detail::channel_send_functions; + + // Helper function to get an executor's context. + template <typename T> + static execution_context& get_context(const T& t, + enable_if_t<execution::is_executor<T>::value>* = 0) + { + return asio::query(t, execution::context); + } + + // Helper function to get an executor's context. + template <typename T> + static execution_context& get_context(const T& t, + enable_if_t<!execution::is_executor<T>::value>* = 0) + { + return t.context(); + } + + class initiate_async_send + { + public: + typedef Executor executor_type; + + explicit initiate_async_send(basic_concurrent_channel* self) + : self_(self) + { + } + + const executor_type& get_executor() const noexcept + { + return self_->get_executor(); + } + + template <typename SendHandler> + void operator()(SendHandler&& handler, + payload_type&& payload) const + { + asio::detail::non_const_lvalue<SendHandler> handler2(handler); + self_->service_->async_send(self_->impl_, + static_cast<payload_type&&>(payload), + handler2.value, self_->get_executor()); + } + + private: + basic_concurrent_channel* self_; + }; + + class initiate_async_receive + { + public: + typedef Executor executor_type; + + explicit initiate_async_receive(basic_concurrent_channel* self) + : self_(self) + { + } + + const executor_type& get_executor() const noexcept + { + return self_->get_executor(); + } + + template <typename ReceiveHandler> + void operator()(ReceiveHandler&& handler) const + { + asio::detail::non_const_lvalue<ReceiveHandler> handler2(handler); + self_->service_->async_receive(self_->impl_, + handler2.value, self_->get_executor()); + } + + private: + basic_concurrent_channel* self_; + }; + + // The service associated with the I/O object. + service_type* service_; + + // The underlying implementation of the I/O object. + typename service_type::template implementation_type< + Traits, Signatures...> impl_; + + // The associated executor. + Executor executor_; +}; + +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_BASIC_CONCURRENT_CHANNEL_HPP diff --git a/3rdparty/asio/include/asio/experimental/cancellation_condition.hpp b/3rdparty/asio/include/asio/experimental/cancellation_condition.hpp index 586e75e2857..6b1b46dd759 100644 --- a/3rdparty/asio/include/asio/experimental/cancellation_condition.hpp +++ b/3rdparty/asio/include/asio/experimental/cancellation_condition.hpp @@ -2,7 +2,7 @@ // experimental/cancellation_condition.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -31,8 +31,7 @@ class wait_for_all { public: template <typename... Args> - ASIO_CONSTEXPR cancellation_type_t operator()( - Args&&...) const ASIO_NOEXCEPT + constexpr cancellation_type_t operator()(Args&&...) const noexcept { return cancellation_type::none; } @@ -42,15 +41,14 @@ public: class wait_for_one { public: - ASIO_CONSTEXPR explicit wait_for_one( + constexpr explicit wait_for_one( cancellation_type_t cancel_type = cancellation_type::all) : cancel_type_(cancel_type) { } template <typename... Args> - ASIO_CONSTEXPR cancellation_type_t operator()( - Args&&...) const ASIO_NOEXCEPT + constexpr cancellation_type_t operator()(Args&&...) const noexcept { return cancel_type_; } @@ -67,34 +65,34 @@ private: class wait_for_one_success { public: - ASIO_CONSTEXPR explicit wait_for_one_success( + constexpr explicit wait_for_one_success( cancellation_type_t cancel_type = cancellation_type::all) : cancel_type_(cancel_type) { } - ASIO_CONSTEXPR cancellation_type_t - operator()() const ASIO_NOEXCEPT + constexpr cancellation_type_t + operator()() const noexcept { return cancel_type_; } template <typename E, typename... Args> - ASIO_CONSTEXPR typename constraint< - !is_same<typename decay<E>::type, asio::error_code>::value - && !is_same<typename decay<E>::type, std::exception_ptr>::value, + constexpr constraint_t< + !is_same<decay_t<E>, asio::error_code>::value + && !is_same<decay_t<E>, std::exception_ptr>::value, cancellation_type_t - >::type operator()(const E&, Args&&...) const ASIO_NOEXCEPT + > operator()(const E&, Args&&...) const noexcept { return cancel_type_; } template <typename E, typename... Args> - ASIO_CONSTEXPR typename constraint< - is_same<typename decay<E>::type, asio::error_code>::value - || is_same<typename decay<E>::type, std::exception_ptr>::value, + constexpr constraint_t< + is_same<decay_t<E>, asio::error_code>::value + || is_same<decay_t<E>, std::exception_ptr>::value, cancellation_type_t - >::type operator()(const E& e, Args&&...) const ASIO_NOEXCEPT + > operator()(const E& e, Args&&...) const noexcept { return !!e ? cancellation_type::none : cancel_type_; } @@ -111,34 +109,33 @@ private: class wait_for_one_error { public: - ASIO_CONSTEXPR explicit wait_for_one_error( + constexpr explicit wait_for_one_error( cancellation_type_t cancel_type = cancellation_type::all) : cancel_type_(cancel_type) { } - ASIO_CONSTEXPR cancellation_type_t - operator()() const ASIO_NOEXCEPT + constexpr cancellation_type_t operator()() const noexcept { return cancellation_type::none; } template <typename E, typename... Args> - ASIO_CONSTEXPR typename constraint< - !is_same<typename decay<E>::type, asio::error_code>::value - && !is_same<typename decay<E>::type, std::exception_ptr>::value, + constexpr constraint_t< + !is_same<decay_t<E>, asio::error_code>::value + && !is_same<decay_t<E>, std::exception_ptr>::value, cancellation_type_t - >::type operator()(const E&, Args&&...) const ASIO_NOEXCEPT + > operator()(const E&, Args&&...) const noexcept { return cancellation_type::none; } template <typename E, typename... Args> - ASIO_CONSTEXPR typename constraint< - is_same<typename decay<E>::type, asio::error_code>::value - || is_same<typename decay<E>::type, std::exception_ptr>::value, + constexpr constraint_t< + is_same<decay_t<E>, asio::error_code>::value + || is_same<decay_t<E>, std::exception_ptr>::value, cancellation_type_t - >::type operator()(const E& e, Args&&...) const ASIO_NOEXCEPT + > operator()(const E& e, Args&&...) const noexcept { return !!e ? cancel_type_ : cancellation_type::none; } diff --git a/3rdparty/asio/include/asio/experimental/channel.hpp b/3rdparty/asio/include/asio/experimental/channel.hpp new file mode 100644 index 00000000000..c808bb4aafd --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/channel.hpp @@ -0,0 +1,70 @@ +// +// experimental/channel.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_CHANNEL_HPP +#define ASIO_EXPERIMENTAL_CHANNEL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/any_io_executor.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/execution/executor.hpp" +#include "asio/is_executor.hpp" +#include "asio/experimental/basic_channel.hpp" +#include "asio/experimental/channel_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename ExecutorOrSignature, typename = void> +struct channel_type +{ + template <typename... Signatures> + struct inner + { + typedef basic_channel<any_io_executor, channel_traits<>, + ExecutorOrSignature, Signatures...> type; + }; +}; + +template <typename ExecutorOrSignature> +struct channel_type<ExecutorOrSignature, + enable_if_t< + is_executor<ExecutorOrSignature>::value + || execution::is_executor<ExecutorOrSignature>::value + >> +{ + template <typename... Signatures> + struct inner + { + typedef basic_channel<ExecutorOrSignature, + channel_traits<>, Signatures...> type; + }; +}; + +} // namespace detail + +/// Template type alias for common use of channel. +template <typename ExecutorOrSignature, typename... Signatures> +using channel = typename detail::channel_type< + ExecutorOrSignature>::template inner<Signatures...>::type; + +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_CHANNEL_HPP diff --git a/3rdparty/asio/include/asio/experimental/channel_error.hpp b/3rdparty/asio/include/asio/experimental/channel_error.hpp new file mode 100644 index 00000000000..dd419757cc3 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/channel_error.hpp @@ -0,0 +1,82 @@ +// +// experimental/channel_error.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_CHANNEL_ERROR_HPP +#define ASIO_EXPERIMENTAL_CHANNEL_ERROR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/error_code.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace error { + +enum channel_errors +{ + /// The channel was closed. + channel_closed = 1, + + /// The channel was cancelled. + channel_cancelled = 2 +}; + +extern ASIO_DECL +const asio::error_category& get_channel_category(); + +static const asio::error_category& + channel_category ASIO_UNUSED_VARIABLE + = asio::experimental::error::get_channel_category(); + +} // namespace error +namespace channel_errc { + // Simulates a scoped enum. + using error::channel_closed; + using error::channel_cancelled; +} // namespace channel_errc +} // namespace experimental +} // namespace asio + +namespace std { + +template<> struct is_error_code_enum< + asio::experimental::error::channel_errors> +{ + static const bool value = true; +}; + +} // namespace std + +namespace asio { +namespace experimental { +namespace error { + +inline asio::error_code make_error_code(channel_errors e) +{ + return asio::error_code( + static_cast<int>(e), get_channel_category()); +} + +} // namespace error +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#if defined(ASIO_HEADER_ONLY) +# include "asio/experimental/impl/channel_error.ipp" +#endif // defined(ASIO_HEADER_ONLY) + +#endif // ASIO_EXPERIMENTAL_CHANNEL_ERROR_HPP diff --git a/3rdparty/asio/include/asio/experimental/channel_traits.hpp b/3rdparty/asio/include/asio/experimental/channel_traits.hpp new file mode 100644 index 00000000000..bccff9876e4 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/channel_traits.hpp @@ -0,0 +1,301 @@ +// +// experimental/channel_traits.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_CHANNEL_TRAITS_HPP +#define ASIO_EXPERIMENTAL_CHANNEL_TRAITS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <deque> +#include "asio/detail/type_traits.hpp" +#include "asio/error.hpp" +#include "asio/experimental/channel_error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { + +#if defined(GENERATING_DOCUMENTATION) + +template <typename... Signatures> +struct channel_traits +{ + /// Rebind the traits to a new set of signatures. + /** + * This nested structure must have a single nested type @c other that + * aliases a traits type with the specified set of signatures. + */ + template <typename... NewSignatures> + struct rebind + { + typedef user_defined other; + }; + + /// Determine the container for the specified elements. + /** + * This nested structure must have a single nested type @c other that + * aliases a container type for the specified element type. + */ + template <typename Element> + struct container + { + typedef user_defined type; + }; + + /// The signature of a channel cancellation notification. + typedef void receive_cancelled_signature(...); + + /// Invoke the specified handler with a cancellation notification. + template <typename F> + static void invoke_receive_cancelled(F f); + + /// The signature of a channel closed notification. + typedef void receive_closed_signature(...); + + /// Invoke the specified handler with a closed notification. + template <typename F> + static void invoke_receive_closed(F f); +}; + +#else // defined(GENERATING_DOCUMENTATION) + +/// Traits used for customising channel behaviour. +template <typename... Signatures> +struct channel_traits +{ + template <typename... NewSignatures> + struct rebind + { + typedef channel_traits<NewSignatures...> other; + }; +}; + +template <typename R> +struct channel_traits<R(asio::error_code)> +{ + template <typename... NewSignatures> + struct rebind + { + typedef channel_traits<NewSignatures...> other; + }; + + template <typename Element> + struct container + { + typedef std::deque<Element> type; + }; + + typedef R receive_cancelled_signature(asio::error_code); + + template <typename F> + static void invoke_receive_cancelled(F f) + { + const asio::error_code e = error::channel_cancelled; + static_cast<F&&>(f)(e); + } + + typedef R receive_closed_signature(asio::error_code); + + template <typename F> + static void invoke_receive_closed(F f) + { + const asio::error_code e = error::channel_closed; + static_cast<F&&>(f)(e); + } +}; + +template <typename R, typename... Args, typename... Signatures> +struct channel_traits<R(asio::error_code, Args...), Signatures...> +{ + template <typename... NewSignatures> + struct rebind + { + typedef channel_traits<NewSignatures...> other; + }; + + template <typename Element> + struct container + { + typedef std::deque<Element> type; + }; + + typedef R receive_cancelled_signature(asio::error_code, Args...); + + template <typename F> + static void invoke_receive_cancelled(F f) + { + const asio::error_code e = error::channel_cancelled; + static_cast<F&&>(f)(e, decay_t<Args>()...); + } + + typedef R receive_closed_signature(asio::error_code, Args...); + + template <typename F> + static void invoke_receive_closed(F f) + { + const asio::error_code e = error::channel_closed; + static_cast<F&&>(f)(e, decay_t<Args>()...); + } +}; + +template <typename R> +struct channel_traits<R(std::exception_ptr)> +{ + template <typename... NewSignatures> + struct rebind + { + typedef channel_traits<NewSignatures...> other; + }; + + template <typename Element> + struct container + { + typedef std::deque<Element> type; + }; + + typedef R receive_cancelled_signature(std::exception_ptr); + + template <typename F> + static void invoke_receive_cancelled(F f) + { + const asio::error_code e = error::channel_cancelled; + static_cast<F&&>(f)( + std::make_exception_ptr(asio::system_error(e))); + } + + typedef R receive_closed_signature(std::exception_ptr); + + template <typename F> + static void invoke_receive_closed(F f) + { + const asio::error_code e = error::channel_closed; + static_cast<F&&>(f)( + std::make_exception_ptr(asio::system_error(e))); + } +}; + +template <typename R, typename... Args, typename... Signatures> +struct channel_traits<R(std::exception_ptr, Args...), Signatures...> +{ + template <typename... NewSignatures> + struct rebind + { + typedef channel_traits<NewSignatures...> other; + }; + + template <typename Element> + struct container + { + typedef std::deque<Element> type; + }; + + typedef R receive_cancelled_signature(std::exception_ptr, Args...); + + template <typename F> + static void invoke_receive_cancelled(F f) + { + const asio::error_code e = error::channel_cancelled; + static_cast<F&&>(f)( + std::make_exception_ptr(asio::system_error(e)), + decay_t<Args>()...); + } + + typedef R receive_closed_signature(std::exception_ptr, Args...); + + template <typename F> + static void invoke_receive_closed(F f) + { + const asio::error_code e = error::channel_closed; + static_cast<F&&>(f)( + std::make_exception_ptr(asio::system_error(e)), + decay_t<Args>()...); + } +}; + +template <typename R> +struct channel_traits<R()> +{ + template <typename... NewSignatures> + struct rebind + { + typedef channel_traits<NewSignatures...> other; + }; + + template <typename Element> + struct container + { + typedef std::deque<Element> type; + }; + + typedef R receive_cancelled_signature(asio::error_code); + + template <typename F> + static void invoke_receive_cancelled(F f) + { + const asio::error_code e = error::channel_cancelled; + static_cast<F&&>(f)(e); + } + + typedef R receive_closed_signature(asio::error_code); + + template <typename F> + static void invoke_receive_closed(F f) + { + const asio::error_code e = error::channel_closed; + static_cast<F&&>(f)(e); + } +}; + +template <typename R, typename T> +struct channel_traits<R(T)> +{ + template <typename... NewSignatures> + struct rebind + { + typedef channel_traits<NewSignatures...> other; + }; + + template <typename Element> + struct container + { + typedef std::deque<Element> type; + }; + + typedef R receive_cancelled_signature(asio::error_code); + + template <typename F> + static void invoke_receive_cancelled(F f) + { + const asio::error_code e = error::channel_cancelled; + static_cast<F&&>(f)(e); + } + + typedef R receive_closed_signature(asio::error_code); + + template <typename F> + static void invoke_receive_closed(F f) + { + const asio::error_code e = error::channel_closed; + static_cast<F&&>(f)(e); + } +}; + +#endif // defined(GENERATING_DOCUMENTATION) + +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_CHANNEL_TRAITS_HPP diff --git a/3rdparty/asio/include/asio/experimental/co_composed.hpp b/3rdparty/asio/include/asio/experimental/co_composed.hpp new file mode 100644 index 00000000000..dd1b82939cd --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/co_composed.hpp @@ -0,0 +1,145 @@ +// +// experimental/co_composed.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_CO_COMPOSED_HPP +#define ASIO_EXPERIMENTAL_CO_COMPOSED_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/async_result.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { + +/// Creates an initiation function object that may be used to launch a +/// coroutine-based composed asynchronous operation. +/** + * The experimental::co_composed utility simplifies the implementation of + * composed asynchronous operations by automatically adapting a coroutine to be + * an initiation function object for use with @c async_initiate. When awaiting + * asynchronous operations, the coroutine automatically uses a conforming + * intermediate completion handler. + * + * @param implementation A function object that contains the coroutine-based + * implementation of the composed asynchronous operation. The first argument to + * the function object represents the state of the operation, and may be used + * to test for cancellation. The remaining arguments are those passed to @c + * async_initiate after the completion token. + * + * @param io_objects_or_executors Zero or more I/O objects or I/O executors for + * which outstanding work must be maintained while the operation is incomplete. + * + * @par Per-Operation Cancellation + * By default, terminal per-operation cancellation is enabled for composed + * operations that use experimental::co_composed. To disable cancellation for + * the composed operation, or to alter its supported cancellation types, call + * the state's @c reset_cancellation_state function. + * + * @par Examples + * The following example illustrates manual error handling and explicit checks + * for cancellation. The completion handler is invoked via a @c co_yield to the + * state's @c complete function, which never returns. + * + * @code template <typename CompletionToken> + * auto async_echo(tcp::socket& socket, + * CompletionToken&& token) + * { + * return asio::async_initiate< + * CompletionToken, void(std::error_code)>( + * asio::experimental::co_composed( + * [](auto state, tcp::socket& socket) -> void + * { + * state.reset_cancellation_state( + * asio::enable_terminal_cancellation()); + * + * while (!state.cancelled()) + * { + * char data[1024]; + * auto [e1, n1] = + * co_await socket.async_read_some( + * asio::buffer(data), + * asio::as_tuple(asio::deferred)); + * + * if (e1) + * co_yield state.complete(e1); + * + * if (!!state.cancelled()) + * co_yield state.complete( + * make_error_code(asio::error::operation_aborted)); + * + * auto [e2, n2] = + * co_await asio::async_write(socket, + * asio::buffer(data, n1), + * asio::as_tuple(asio::deferred)); + * + * if (e2) + * co_yield state.complete(e2); + * } + * }, socket), + * token, std::ref(socket)); + * } @endcode + * + * This next example shows exception-based error handling and implicit checks + * for cancellation. The completion handler is invoked after returning from the + * coroutine via @c co_return. Valid @c co_return values are specified using + * completion signatures passed to the @c co_composed function. + * + * @code template <typename CompletionToken> + * auto async_echo(tcp::socket& socket, + * CompletionToken&& token) + * { + * return asio::async_initiate< + * CompletionToken, void(std::error_code)>( + * asio::experimental::co_composed< + * void(std::error_code)>( + * [](auto state, tcp::socket& socket) -> void + * { + * try + * { + * state.throw_if_cancelled(true); + * state.reset_cancellation_state( + * asio::enable_terminal_cancellation()); + * + * for (;;) + * { + * char data[1024]; + * std::size_t n = co_await socket.async_read_some( + * asio::buffer(data), asio::deferred); + * + * co_await asio::async_write(socket, + * asio::buffer(data, n), asio::deferred); + * } + * } + * catch (const std::system_error& e) + * { + * co_return {e.code()}; + * } + * }, socket), + * token, std::ref(socket)); + * } @endcode + */ +template <completion_signature... Signatures, + typename Implementation, typename... IoObjectsOrExecutors> +auto co_composed(Implementation&& implementation, + IoObjectsOrExecutors&&... io_objects_or_executors); + +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/experimental/impl/co_composed.hpp" + +#endif // ASIO_EXPERIMENTAL_CO_COMPOSED_HPP diff --git a/3rdparty/asio/include/asio/experimental/co_spawn.hpp b/3rdparty/asio/include/asio/experimental/co_spawn.hpp new file mode 100644 index 00000000000..8ef59283178 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/co_spawn.hpp @@ -0,0 +1,187 @@ +// +// experimental/co_spawn.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +#ifndef ASIO_EXPERIMENTAL_CO_SPAWN_HPP +#define ASIO_EXPERIMENTAL_CO_SPAWN_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <utility> +#include "asio/compose.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/experimental/coro.hpp" +#include "asio/experimental/deferred.hpp" +#include "asio/experimental/prepend.hpp" +#include "asio/redirect_error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename T, typename U, typename Executor> +struct coro_spawn_op +{ + coro<T, U, Executor> c; + + void operator()(auto& self) + { + auto op = c.async_resume(deferred); + std::move(op)((prepend)(std::move(self), 0)); + } + + void operator()(auto& self, int, auto... res) + { + self.complete(std::move(res)...); + } +}; + +} // namespace detail + +/// Spawn a resumable coroutine. +/** + * This function spawns the coroutine for execution on its executor. It binds + * the lifetime of the coroutine to the executor. + * + * @param c The coroutine + * + * @param token The completion token + * + * @returns Implementation defined + */ +template <typename T, typename Executor, typename CompletionToken> +ASIO_INITFN_AUTO_RESULT_TYPE( + CompletionToken, void(std::exception_ptr, T)) +co_spawn(coro<void, T, Executor> c, CompletionToken&& token) +{ + auto exec = c.get_executor(); + return async_compose<CompletionToken, void(std::exception_ptr, T)>( + detail::coro_spawn_op<void, T, Executor>{std::move(c)}, + token, exec); +} + +/// Spawn a resumable coroutine. +/** + * This function spawns the coroutine for execution on its executor. It binds + * the lifetime of the coroutine to the executor. + * + * @param c The coroutine + * + * @param token The completion token + * + * @returns Implementation defined + */ +template <typename T, typename Executor, typename CompletionToken> +ASIO_INITFN_AUTO_RESULT_TYPE( + CompletionToken, void(std::exception_ptr, T)) +co_spawn(coro<void(), T, Executor> c, CompletionToken&& token) +{ + auto exec = c.get_executor(); + return async_compose<CompletionToken, void(std::exception_ptr, T)>( + detail::coro_spawn_op<void(), T, Executor>{std::move(c)}, + token, exec); +} + +/// Spawn a resumable coroutine. +/** + * This function spawns the coroutine for execution on its executor. It binds + * the lifetime of the coroutine to the executor. + * + * @param c The coroutine + * + * @param token The completion token + * + * @returns Implementation defined + */ +template <typename T, typename Executor, typename CompletionToken> +ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(T)) +co_spawn(coro<void() noexcept, T, Executor> c, CompletionToken&& token) +{ + auto exec = c.get_executor(); + return async_compose<CompletionToken, void(T)>( + detail::coro_spawn_op<void() noexcept, T, Executor>{std::move(c)}, + token, exec); +} + +/// Spawn a resumable coroutine. +/** + * This function spawns the coroutine for execution on its executor. It binds + * the lifetime of the coroutine to the executor. + * + * @param c The coroutine + * + * @param token The completion token + * + * @returns Implementation defined + */ +template <typename Executor, typename CompletionToken> +ASIO_INITFN_AUTO_RESULT_TYPE( + CompletionToken, void(std::exception_ptr)) +co_spawn(coro<void, void, Executor> c, CompletionToken&& token) +{ + auto exec = c.get_executor(); + return async_compose<CompletionToken, void(std::exception_ptr)>( + detail::coro_spawn_op<void, void, Executor>{std::move(c)}, + token, exec); +} + +/// Spawn a resumable coroutine. +/** + * This function spawns the coroutine for execution on its executor. It binds + * the lifetime of the coroutine to the executor. + * + * @param c The coroutine + * + * @param token The completion token + * + * @returns Implementation defined + */ +template <typename Executor, typename CompletionToken> +ASIO_INITFN_AUTO_RESULT_TYPE( + CompletionToken, void(std::exception_ptr)) +co_spawn(coro<void(), void, Executor> c, CompletionToken&& token) +{ + auto exec = c.get_executor(); + return async_compose<CompletionToken, void(std::exception_ptr)>( + detail::coro_spawn_op<void(), void, Executor>{std::move(c)}, + token, exec); +} + +/// Spawn a resumable coroutine. +/** + * This function spawns the coroutine for execution on its executor. It binds + * the lifetime of the coroutine to the executor. + * + * @param c The coroutine + * + * @param token The completion token + * + * @returns Implementation defined + */ +template <typename Executor, typename CompletionToken> +ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) +co_spawn(coro<void() noexcept, void, Executor> c, CompletionToken&& token) +{ + auto exec = c.get_executor(); + return async_compose<CompletionToken, void()>( + detail::coro_spawn_op<void() noexcept, void, Executor>{std::move(c)}, + token, exec); +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif //ASIO_EXPERIMENTAL_CO_SPAWN_HPP diff --git a/3rdparty/asio/include/asio/experimental/concurrent_channel.hpp b/3rdparty/asio/include/asio/experimental/concurrent_channel.hpp new file mode 100644 index 00000000000..b326be96d31 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/concurrent_channel.hpp @@ -0,0 +1,70 @@ +// +// experimental/concurrent_channel.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_CONCURRENT_CHANNEL_HPP +#define ASIO_EXPERIMENTAL_CONCURRENT_CHANNEL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/any_io_executor.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/execution/executor.hpp" +#include "asio/is_executor.hpp" +#include "asio/experimental/basic_concurrent_channel.hpp" +#include "asio/experimental/channel_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename ExecutorOrSignature, typename = void> +struct concurrent_channel_type +{ + template <typename... Signatures> + struct inner + { + typedef basic_concurrent_channel<any_io_executor, channel_traits<>, + ExecutorOrSignature, Signatures...> type; + }; +}; + +template <typename ExecutorOrSignature> +struct concurrent_channel_type<ExecutorOrSignature, + enable_if_t< + is_executor<ExecutorOrSignature>::value + || execution::is_executor<ExecutorOrSignature>::value + >> +{ + template <typename... Signatures> + struct inner + { + typedef basic_concurrent_channel<ExecutorOrSignature, + channel_traits<>, Signatures...> type; + }; +}; + +} // namespace detail + +/// Template type alias for common use of channel. +template <typename ExecutorOrSignature, typename... Signatures> +using concurrent_channel = typename detail::concurrent_channel_type< + ExecutorOrSignature>::template inner<Signatures...>::type; + +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_CONCURRENT_CHANNEL_HPP diff --git a/3rdparty/asio/include/asio/experimental/coro.hpp b/3rdparty/asio/include/asio/experimental/coro.hpp index fb2ad013a52..de909d29a6b 100644 --- a/3rdparty/asio/include/asio/experimental/coro.hpp +++ b/3rdparty/asio/include/asio/experimental/coro.hpp @@ -2,8 +2,8 @@ // experimental/coro.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2021 Klemens D. Morgenstern -// (klemens dot morgenstern at gmx dot net) +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -12,236 +12,105 @@ #ifndef ASIO_EXPERIMENTAL_CORO_HPP #define ASIO_EXPERIMENTAL_CORO_HPP +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + #include "asio/detail/config.hpp" #include "asio/dispatch.hpp" -#include "asio/experimental/detail/coro_promise_allocator.hpp" -#include "asio/experimental/detail/partial_promise.hpp" -#include "asio/experimental/detail/coro_traits.hpp" #include "asio/error.hpp" #include "asio/error_code.hpp" -#include "asio/experimental/use_coro.hpp" +#include "asio/experimental/coro_traits.hpp" +#include "asio/experimental/detail/coro_promise_allocator.hpp" +#include "asio/experimental/detail/partial_promise.hpp" #include "asio/post.hpp" #include "asio/detail/push_options.hpp" namespace asio { namespace experimental { - -template <typename Yield, typename Return, typename Executor> -struct coro; - namespace detail { -template <typename Signature, typename Return, typename Executor> +template <typename Signature, typename Return, + typename Executor, typename Allocator> struct coro_promise; -template <typename T> -struct is_noexcept : std::false_type -{ -}; - -template <typename Return, typename... Args> -struct is_noexcept<Return(Args...)> : std::false_type -{ -}; - -template <typename Return, typename... Args> -struct is_noexcept<Return(Args...) noexcept> : std::true_type -{ -}; - -template <typename T> -constexpr bool is_noexcept_v = is_noexcept<T>::value; - -template <typename T> -struct coro_error; - -template <> -struct coro_error<asio::error_code> -{ - static asio::error_code invalid() - { - return error::fault; - } - - static asio::error_code cancelled() - { - return error::operation_aborted; - } - - static asio::error_code interrupted() - { - return error::interrupted; - } - - static asio::error_code done() - { - return error::broken_pipe; - } -}; - -template <> -struct coro_error<std::exception_ptr> -{ - static std::exception_ptr invalid() - { - return std::make_exception_ptr( - asio::system_error( - coro_error<asio::error_code>::invalid())); - } - - static std::exception_ptr cancelled() - { - return std::make_exception_ptr( - asio::system_error( - coro_error<asio::error_code>::cancelled())); - } - - static std::exception_ptr interrupted() - { - return std::make_exception_ptr( - asio::system_error( - coro_error<asio::error_code>::interrupted())); - } - - static std::exception_ptr done() - { - return std::make_exception_ptr( - asio::system_error( - coro_error<asio::error_code>::done())); - } -}; - -template <typename T, typename Coroutine, typename = void> -struct coro_with_arg -{ - using coro_t = Coroutine; - T value; - coro_t& coro; - - struct awaitable_t - { - T value; - coro_t& coro; - - constexpr static bool await_ready() { return false; } - - template <typename Y, typename R, typename E> - auto await_suspend(coroutine_handle<coro_promise<Y, R, E>> h) - -> coroutine_handle<> - { - auto& hp = h.promise(); - if (hp.get_executor() == coro.get_executor()) - { - coro.coro_->awaited_from = h; - coro.coro_->reset_error(); - coro.coro_->input_ = std::move(value); - struct cancel_handler - { - cancel_handler(coro_t& coro) : coro(coro.coro_) {} - - typename coro_t::promise_type* coro; - - void operator()(cancellation_type ct) - { - coro->cancel.signal.emit(ct); - } - }; - - hp.cancel.state.slot().template emplace<cancel_handler>(coro); - return coro.coro_->get_handle(); - } else - { - coro.coro_->awaited_from = - dispatch_coroutine(hp.get_executor(), [h]() mutable - { h.resume(); }); - coro.coro_->reset_error(); - coro.coro_->input_ = std::move(value); - - struct cancel_handler - { - cancel_handler(E e, coro_t& coro) : e(e), coro(coro.coro_) {} - - E e; - typename coro_t::promise_type* coro; - - void operator()(cancellation_type ct) - { - asio::dispatch(e, - [ct, p = coro]() mutable - { - p->cancel.signal.emit(ct); - }); - } - }; - - hp.cancel.state.slot().template emplace<cancel_handler>( - coro.get_executor(), coro); - - return dispatch_coroutine( - hp.get_executor(), [h]() mutable { h.resume(); }); - } - - } - - auto await_resume() -> typename coro_t::result_type - { - coro.coro_->cancel.state.slot().clear(); - coro.coro_->rethrow_if(); - return std::move(coro.coro_->result_); - } - }; - - template <typename CompletionToken> - auto async_resume(CompletionToken&& token) && - { - return coro.async_resume(std::move(value), - std::forward<CompletionToken>(token)); - } - - auto operator co_await() && - { - return awaitable_t{std::move(value), coro}; - } -}; +template <typename T, typename Coroutine> +struct coro_with_arg; } // namespace detail +/// The main type of a resumable coroutine. +/** + * Template parameter @c Yield specifies type or signature used by co_yield, + * @c Return specifies the type used for co_return, and @c Executor specifies + * the underlying executor type. + */ template <typename Yield = void, typename Return = void, - typename Executor = any_io_executor> + typename Executor = any_io_executor, + typename Allocator = std::allocator<void>> struct coro { - using traits = detail::coro_traits<Yield, Return, Executor>; + /// The traits of the coroutine. See asio::experimental::coro_traits + /// for details. + using traits = coro_traits<Yield, Return, Executor>; + /// The value that can be passed into a symmetrical cororoutine. @c void if + /// asymmetrical. using input_type = typename traits::input_type; + + /// The type that can be passed out through a co_yield. using yield_type = typename traits::yield_type; + + /// The type that can be passed out through a co_return. using return_type = typename traits::return_type; - using error_type = typename traits::error_type; + + /// The type received by a co_await or async_resume. Its a combination of + /// yield and return. using result_type = typename traits::result_type; + + /// The signature used by the async_resume. + using signature_type = typename traits::signature_type; + + /// Whether or not the coroutine is noexcept. constexpr static bool is_noexcept = traits::is_noexcept; - using promise_type = detail::coro_promise<Yield, Return, Executor>; + /// The error type of the coroutine. Void for noexcept + using error_type = typename traits::error_type; + + /// Completion handler type used by async_resume. + using completion_handler = typename traits::completion_handler; + + /// The internal promise-type of the coroutine. + using promise_type = detail::coro_promise<Yield, Return, Executor, Allocator>; #if !defined(GENERATING_DOCUMENTATION) - template <typename T, typename Coroutine, typename> + template <typename T, typename Coroutine> friend struct detail::coro_with_arg; #endif // !defined(GENERATING_DOCUMENTATION) + /// The executor type. using executor_type = Executor; + /// The allocator type. + using allocator_type = Allocator; + #if !defined(GENERATING_DOCUMENTATION) - friend struct detail::coro_promise<Yield, Return, Executor>; + friend struct detail::coro_promise<Yield, Return, Executor, Allocator>; #endif // !defined(GENERATING_DOCUMENTATION) + /// The default constructor, gives an invalid coroutine. coro() = default; + /// Move constructor. coro(coro&& lhs) noexcept : coro_(std::exchange(lhs.coro_, nullptr)) { } - coro(const coro &) = delete; + coro(const coro&) = delete; + /// Move assignment. coro& operator=(coro&& lhs) noexcept { std::swap(coro_, lhs.coro_); @@ -250,6 +119,12 @@ struct coro coro& operator=(const coro&) = delete; + /// Destructor. Destroys the coroutine, if it holds a valid one. + /** + * @note This does not cancel an active coroutine. Destructing a resumable + * coroutine, i.e. one with a call to async_resume that has not completed, is + * undefined behaviour. + */ ~coro() { if (coro_ != nullptr) @@ -260,8 +135,7 @@ struct coro destroyer(const detail::coroutine_handle<promise_type>& handle) : handle(handle) - { - } + { } destroyer(destroyer&& lhs) : handle(std::exchange(lhs.handle, nullptr)) @@ -286,6 +160,7 @@ struct coro } } + /// Get the used executor. executor_type get_executor() const { if (coro_) @@ -297,29 +172,74 @@ struct coro throw std::logic_error("Coroutine has no executor"); } + /// Get the used allocator. + allocator_type get_allocator() const + { + if (coro_) + return coro_->get_allocator(); + + if constexpr (std::is_default_constructible_v<Allocator>) + return Allocator{}; + else + throw std::logic_error( + "Coroutine has no available allocator without a constructed promise"); + } + + /// Resume the coroutine. + /** + * @param token The completion token of the async resume. + * + * @attention Calling an invalid coroutine with a noexcept signature is + * undefined behaviour. + * + * @note This overload is only available for coroutines without an input + * value. + */ template <typename CompletionToken> requires std::is_void_v<input_type> - auto async_resume(CompletionToken&& token) + auto async_resume(CompletionToken&& token) & { return async_initiate<CompletionToken, typename traits::completion_handler>( initiate_async_resume(this), token); } - + /// Resume the coroutine. + /** + * @param token The completion token of the async resume. + * + * @attention Calling an invalid coroutine with a noexcept signature is + * undefined behaviour. + * + * @note This overload is only available for coroutines with an input value. + */ template <typename CompletionToken, detail::convertible_to<input_type> T> - auto async_resume(T&& ip, CompletionToken&& token) + auto async_resume(T&& ip, CompletionToken&& token) & { return async_initiate<CompletionToken, typename traits::completion_handler>( initiate_async_resume(this), token, std::forward<T>(ip)); } + /// Operator used for coroutines without input value. auto operator co_await() requires (std::is_void_v<input_type>) { return awaitable_t{*this}; } + /// Operator used for coroutines with input value. + /** + * @param ip The input value + * + * @returns An awaitable handle. + * + * @code + * coro<void> push_values(coro<double(int)> c) + * { + * std::optional<double> res = co_await c(42); + * } + * @endcode + */ template <detail::convertible_to<input_type> T> auto operator()(T&& ip) { @@ -327,6 +247,7 @@ struct coro std::forward<T>(ip), *this}; } + /// Check whether the coroutine is open, i.e. can be resumed. bool is_open() const { if (coro_) @@ -339,717 +260,34 @@ struct coro return false; } + /// Check whether the coroutine is open, i.e. can be resumed. explicit operator bool() const { return is_open(); } - void cancel(cancellation_type ct = cancellation_type::all) - { - if (is_open() && !coro_->cancel.state.cancelled()) - asio::dispatch(get_executor(), - [ct, coro = coro_] { coro->cancel.signal.emit(ct); }); - } - private: - struct awaitable_t - { - coro& coro_; - - constexpr static bool await_ready() { return false; } - - template <typename Y, typename R, typename E> - auto await_suspend( - detail::coroutine_handle<detail::coro_promise<Y, R, E>> h) - -> detail::coroutine_handle<> - { - auto& hp = h.promise(); - if (hp.get_executor() == coro_.get_executor()) - { - coro_.coro_->awaited_from = h; - coro_.coro_->reset_error(); - - struct cancel_handler - { - cancel_handler(coro& coro_) : coro_(coro_.coro_) {} - - typename coro::promise_type* coro_; + struct awaitable_t; - void operator()(cancellation_type ct) - { - coro_->cancel.signal.emit(ct); - } - }; - - hp.cancel.state.slot().template emplace<cancel_handler>(coro_); - return coro_.coro_->get_handle(); - } - else - { - coro_.coro_->awaited_from = detail::dispatch_coroutine( - hp.get_executor(), [h]() mutable { h.resume(); }); - coro_.coro_->reset_error(); - - struct cancel_handler - { - cancel_handler(E e, coro& coro) : e(e), coro_(coro.coro_) {} - - E e; - typename coro::promise_type* coro_; - - void operator()(cancellation_type ct) - { - asio::dispatch(e, - [ct, p = coro_]() mutable - { - p->cancel.signal.emit(ct); - }); - } - }; - - hp.cancel.state.slot().template emplace<cancel_handler>( - coro_.get_executor(), coro_); - - return detail::dispatch_coroutine( - hp.get_executor(), [h]() mutable { h.resume(); }); - } - } - - auto await_resume() -> result_type - { - coro_.coro_->cancel.state.slot().clear(); - coro_.coro_->rethrow_if(); - if constexpr (!std::is_void_v<result_type>) - return std::move(coro_.coro_->result_); - } - }; - - class initiate_async_resume - { - public: - typedef Executor executor_type; - - explicit initiate_async_resume(coro* self) - : self_(self) - { - } - - executor_type get_executor() const noexcept - { - return self_->get_executor(); - } - - template <typename E, typename WaitHandler> - auto handle(E exec, WaitHandler&& handler, - std::true_type /* error is noexcept */, - std::true_type /* result is void */) const //noexcept - { - return [self = self_, - h = std::forward<WaitHandler>(handler), - exec = std::move(exec)]() mutable - { - assert(self); - auto ch = - detail::coroutine_handle<promise_type>::from_promise(*self->coro_); - assert(ch && !ch.done()); - assert(self->coro_->awaited_from == detail::noop_coroutine()); - - self->coro_->awaited_from = - post_coroutine(std::move(exec), std::move(h)); - self->coro_->reset_error(); - ch.resume(); - }; - } - - template <typename E, typename WaitHandler> - requires (!std::is_void_v<result_type>) - auto handle(E exec, WaitHandler&& handler, - std::true_type /* error is noexcept */, - std::false_type /* result is void */) const //noexcept - { - return [self = self_, - h = std::forward<WaitHandler>(handler), - exec = std::move(exec)]() mutable - { - assert(self); - - auto ch = - detail::coroutine_handle<promise_type>::from_promise(*self->coro_); - assert(ch && !ch.done()); - assert(self->coro_->awaited_from == detail::noop_coroutine()); - - self->coro_->awaited_from = - detail::post_coroutine(exec, - [self, h = std::move(h)]() mutable - { - std::move(h)(std::move(self->coro_->result_)); - }); - self->coro_->reset_error(); - ch.resume(); - }; - } - - template <typename E, typename WaitHandler> - auto handle(E exec, WaitHandler&& handler, - std::false_type /* error is noexcept */, - std::true_type /* result is void */) const - { - return [self = self_, - h = std::forward<WaitHandler>(handler), - exec = std::move(exec)]() mutable - { - if (!self) - { - asio::post(exec, - [h = std::move(h)]() mutable - { - h(detail::coro_error<error_type>::invalid()); - }); - return; - } - - auto ch = - detail::coroutine_handle<promise_type>::from_promise(*self->coro_); - if (!ch) - { - asio::post(exec, - [h = std::move(h)]() mutable - { - h(detail::coro_error<error_type>::invalid()); - }); - } - else if (ch.done()) - { - asio::post(exec, - [h = std::move(h)]() mutable - { - h(detail::coro_error<error_type>::done()); - }); - } - else - { - assert(self->coro_->awaited_from == detail::noop_coroutine()); - self->coro_->awaited_from = - detail::post_coroutine(exec, - [self, h = std::move(h)]() mutable - { - std::move(h)(std::move(self->coro_->error_)); - }); - self->coro_->reset_error(); - ch.resume(); - } - }; - } - - template <typename E, typename WaitHandler> - auto handle(E exec, WaitHandler&& handler, - std::false_type /* error is noexcept */, - std::false_type /* result is void */) const - { - return [self = self_, h = std::forward<WaitHandler>(handler), - exec = std::move(exec)]() mutable - { - if (!self) - { - asio::post(exec, - [h = std::move(h)]() mutable - { - h(detail::coro_error<error_type>::invalid(), result_type{}); - }); - return; - } - - auto ch = - detail::coroutine_handle<promise_type>::from_promise(*self->coro_); - if (!ch) - { - asio::post(exec, - [h = std::move(h)]() mutable - { - h(detail::coro_error<error_type>::invalid(), result_type{}); - }); - } - else if (ch.done()) - { - asio::post(exec, - [h = std::move(h)]() mutable - { - h(detail::coro_error<error_type>::done(), result_type{}); - }); - } - else - { - assert(self->coro_->awaited_from == detail::noop_coroutine()); - self->coro_->awaited_from = - detail::post_coroutine(exec, - [h = std::move(h), self]() mutable - { - std::move(h)(std::move(self->coro_->error_), - std::move(self->coro_->result_)); - }); - self->coro_->reset_error(); - ch.resume(); - } - }; - } - - struct cancel_handler - { - promise_type* coro; - - cancel_handler(promise_type* coro) : coro(coro) {} - - void operator()(cancellation_type ct) - { - asio::dispatch(coro->get_executor(), - [ct, k = coro] { k->cancel.signal.emit(ct); }); - } - }; - - template <typename WaitHandler> - void operator()(WaitHandler&& handler) const - { - const auto exec = - asio::prefer( - get_associated_executor(handler, get_executor()), - execution::outstanding_work.tracked); - - using cancel_t = decltype(self_->coro_->cancel); - self_->coro_->cancel.~cancel_t(); - new(&self_->coro_->cancel) cancel_t(); - - auto cancel = get_associated_cancellation_slot(handler); - if (cancel.is_connected()) - cancel.template emplace<cancel_handler>(self_->coro_); - - asio::dispatch(get_executor(), - handle(exec, std::forward<WaitHandler>(handler), - std::integral_constant<bool, is_noexcept>{}, - std::is_void<result_type>{})); - } - - template <typename WaitHandler, typename Input> - void operator()(WaitHandler&& handler, Input&& input) const - { - const auto exec = - asio::prefer( - get_associated_executor(handler, get_executor()), - execution::outstanding_work.tracked); - auto cancel = get_associated_cancellation_slot(handler); - - using cancel_t = decltype(self_->coro_->cancel); - self_->coro_->cancel.~cancel_t(); - new(&self_->coro_->cancel) cancel_t(); - - if (cancel.is_connected()) - cancel.template emplace<cancel_handler>(self_->coro_); - - asio::dispatch(get_executor(), - [h = handle(exec, std::forward<WaitHandler>(handler), - std::integral_constant<bool, is_noexcept>{}, - std::is_void<result_type>{}), - in = std::forward<Input>(input), self = self_]() mutable - { - self->coro_->input_ = std::move(in); - std::move(h)(); - }); - } - - private: - coro* self_; - }; + struct initiate_async_resume; explicit coro(promise_type* const cr) : coro_(cr) {} promise_type* coro_{nullptr}; }; -namespace detail { +/// A generator is a coro that returns void and yields value. +template<typename T, typename Executor = asio::any_io_executor, + typename Allocator = std::allocator<void>> +using generator = coro<T, void, Executor, Allocator>; -template <bool IsNoexcept> -struct coro_promise_error; +/// A task is a coro that does not yield values +template<typename T, typename Executor = asio::any_io_executor, + typename Allocator = std::allocator<void>> +using task = coro<void(), T, Executor, Allocator>; -template <> -struct coro_promise_error<false> -{ - std::exception_ptr error_; - - void reset_error() { error_ = std::exception_ptr{}; } - - void unhandled_exception() { error_ = std::current_exception(); } - - void rethrow_if() - { - if (error_) - std::rethrow_exception(error_); - } -}; - -template <> -struct coro_promise_error<true> -{ - void reset_error() {} - - void unhandled_exception() noexcept { throw; } - - void rethrow_if() {} -}; - -template <typename T = void> -struct yield_input -{ - T& value; - coroutine_handle<> awaited_from{noop_coroutine()}; - - bool await_ready() const noexcept - { - return false; - } - - auto await_suspend(coroutine_handle<>) noexcept - { - return std::exchange(awaited_from, noop_coroutine()); - } - - T await_resume() const noexcept { return std::move(value); } -}; - -template <> -struct yield_input<void> -{ - coroutine_handle<> awaited_from{noop_coroutine()}; - - bool await_ready() const noexcept - { - return false; - } - - auto await_suspend(coroutine_handle<>) noexcept - { - return std::exchange(awaited_from, noop_coroutine()); - } - - constexpr void await_resume() const noexcept {} -}; - -struct coro_awaited_from -{ - coroutine_handle<> awaited_from{noop_coroutine()}; - - auto final_suspend() noexcept - { - struct suspendor - { - coroutine_handle<> awaited_from; - - constexpr static bool await_ready() noexcept { return false; } - - auto await_suspend(coroutine_handle<>) noexcept - { - return std::exchange(awaited_from, noop_coroutine()); - } - - constexpr static void await_resume() noexcept {} - }; - - return suspendor{std::exchange(awaited_from, noop_coroutine())}; - } - - ~coro_awaited_from() - { - awaited_from.resume(); - }//must be on the right executor -}; - -template <typename Yield, typename Input, typename Return> -struct coro_promise_exchange : coro_awaited_from -{ - using result_type = coro_result_t<Yield, Return>; - - result_type result_; - Input input_; - - auto yield_value(Yield&& y) - { - result_ = std::move(y); - return yield_input<Input>{std::move(input_), - std::exchange(awaited_from, noop_coroutine())}; - } - - auto yield_value(const Yield& y) - { - result_ = y; - return yield_input<Input>{std::move(input_), - std::exchange(awaited_from, noop_coroutine())}; - } - - void return_value(const Return& r) { result_ = r; } - - void return_value(Return&& r) { result_ = std::move(r); } -}; - -template <typename YieldReturn> -struct coro_promise_exchange<YieldReturn, void, YieldReturn> : coro_awaited_from -{ - using result_type = coro_result_t<YieldReturn, YieldReturn>; - - result_type result_; - - auto yield_value(const YieldReturn& y) - { - result_ = y; - return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; - } - - auto yield_value(YieldReturn&& y) - { - result_ = std::move(y); - return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; - } - - void return_value(const YieldReturn& r) { result_ = r; } - - void return_value(YieldReturn&& r) { result_ = std::move(r); } -}; - -template <typename Yield, typename Return> -struct coro_promise_exchange<Yield, void, Return> : coro_awaited_from -{ - using result_type = coro_result_t<Yield, Return>; - - result_type result_; - - auto yield_value(const Yield& y) - { - result_.template emplace<0>(y); - return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; - } - - auto yield_value(Yield&& y) - { - result_.template emplace<0>(std::move(y)); - return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; - } - - void return_value(const Return& r) - { result_.template emplace<1>(r); } - - void return_value(Return&& r) - { result_.template emplace<1>(std::move(r)); } -}; - -template <typename Yield, typename Input> -struct coro_promise_exchange<Yield, Input, void> : coro_awaited_from -{ - using result_type = coro_result_t<Yield, void>; - - result_type result_; - Input input_; - - auto yield_value(Yield&& y) - { - result_ = std::move(y); - return yield_input<Input>{input_, - std::exchange(awaited_from, noop_coroutine())}; - } - - auto yield_value(const Yield& y) - { - result_ = y; - return yield_input<Input>{input_, - std::exchange(awaited_from, noop_coroutine())}; - } - - void return_void() { result_.reset(); } -}; - -template <typename Return> -struct coro_promise_exchange<void, void, Return> : coro_awaited_from -{ - using result_type = coro_result_t<void, Return>; - - result_type result_; - - void yield_value(); - - void return_value(const Return& r) { result_ = r; } - - void return_value(Return&& r) { result_ = std::move(r); } -}; - - -template <> -struct coro_promise_exchange<void, void, void> : coro_awaited_from -{ - void return_void() {} - - void yield_value(); -}; - -template <typename Yield> -struct coro_promise_exchange<Yield, void, void> : coro_awaited_from -{ - using result_type = coro_result_t<Yield, void>; - - result_type result_; - - auto yield_value(const Yield& y) - { - result_ = y; - return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; - } - - auto yield_value(Yield&& y) - { - result_ = std::move(y); - return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; - } - - void return_void() { result_.reset(); } -}; - -template <typename Yield, typename Return, typename Executor> -struct coro_promise final : - coro_promise_allocator<coro<Yield, Return, Executor>>, - coro_promise_error<coro_traits<Yield, Return, Executor>::is_noexcept>, - coro_promise_exchange< - typename coro_traits<Yield, Return, Executor>::yield_type, - typename coro_traits<Yield, Return, Executor>::input_type, - typename coro_traits<Yield, Return, Executor>::return_type> -{ - using coro_type = coro<Yield, Return, Executor>; - - auto handle() - { return coroutine_handle<coro_promise>::from_promise(this); } - - using executor_type = Executor; - - executor_type executor_; - struct cancel_pair - { - cancellation_signal signal; - asio::cancellation_state state{signal.slot()}; - - }; - cancel_pair cancel; - - using allocator_type = - typename std::allocator_traits<associated_allocator_t < Executor>>:: - template rebind_alloc<std::byte>; - using traits = coro_traits<Yield, Return, Executor>; - - using input_type = typename traits::input_type; - using yield_type = typename traits::yield_type; - using return_type = typename traits::return_type; - using error_type = typename traits::error_type; - using result_type = typename traits::result_type; - constexpr static bool is_noexcept = traits::is_noexcept; - - auto get_executor() const -> Executor { return executor_; } - - auto get_handle() - { - return coroutine_handle<coro_promise>::from_promise(*this); - } - - template <typename... Args> - coro_promise(Executor executor, Args &&...) noexcept - : executor_(std::move(executor)) - { - } - - template <execution_context Context, typename... Args> - coro_promise(Context&& ctx, Args&&...) noexcept - : executor_(ctx.get_executor()) - { - } - - auto get_return_object() - { - return coro<Yield, Return, Executor>{this}; - } - - auto initial_suspend() noexcept - { - return suspend_always{}; - } - - using coro_promise_exchange< - typename coro_traits<Yield, Return, Executor>::yield_type, - typename coro_traits<Yield, Return, Executor>::input_type, - typename coro_traits<Yield, Return, Executor>::return_type>::yield_value; - - auto await_transform(this_coro::executor_t) const - { - struct exec_helper - { - const executor_type& value; - - constexpr static bool await_ready() noexcept { return true; } - - constexpr static void await_suspend(coroutine_handle<>) noexcept {} - - executor_type await_resume() const noexcept { return value; } - }; - - return exec_helper{executor_}; - } - - auto await_transform(this_coro::cancellation_state_t) const - { - struct exec_helper - { - const asio::cancellation_state& value; - - constexpr static bool await_ready() noexcept { return true; } - - constexpr static void await_suspend(coroutine_handle<>) noexcept {} - - const asio::cancellation_state& await_resume() const noexcept - { - return value; - } - }; - - return exec_helper{cancel.state}; - } - - template <typename Yield_, typename Return_, typename Executor_> - auto await_transform(coro<Yield_, Return_, Executor_>& kr) -> decltype(auto) - { - return kr; - } - - template <typename Yield_, typename Return_, typename Executor_> - auto await_transform(coro<Yield_, Return_, Executor_>&& kr) - { - return std::move(kr); - } - - template <typename T_, typename Coroutine> - auto await_transform(coro_with_arg<T_, Coroutine>&& kr) -> decltype(auto) - { - return std::move(kr); - } - - template <typename T_> - requires requires(T_ t) {{ t.async_wait(use_coro) }; } - auto await_transform(T_ &t) -> decltype(auto) - { - return await_transform(t.async_wait(use_coro)); - } - - template <typename... Ts> - auto await_transform(coro_init_handler<Executor, Ts...>&& kr) const - { - if constexpr (is_noexcept) - return std::move(kr).as_noexcept(cancel.state.slot()); - else - return std::move(kr).as_throwing(cancel.state.slot()); - } -}; - -} // namespace detail } // namespace experimental } // namespace asio #include "asio/detail/pop_options.hpp" +#include "asio/experimental/impl/coro.hpp" + #endif // ASIO_EXPERIMENTAL_CORO_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/coro_traits.hpp b/3rdparty/asio/include/asio/experimental/coro_traits.hpp index a2b31cb952e..7da904b1273 100644 --- a/3rdparty/asio/include/asio/experimental/detail/coro_traits.hpp +++ b/3rdparty/asio/include/asio/experimental/coro_traits.hpp @@ -2,8 +2,8 @@ // experimental/detail/coro_traits.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2021 Klemens D. Morgenstern -// (klemens dot morgenstern at gmx dot net) +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -12,6 +12,10 @@ #ifndef ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP #define ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + #include "asio/detail/config.hpp" #include <optional> #include <variant> @@ -22,16 +26,15 @@ namespace experimental { namespace detail { template <class From, class To> -concept convertible_to = std::is_convertible_v<From, To> && - requires(std::add_rvalue_reference_t<From> (&f)()) {static_cast<To>(f()); }; +concept convertible_to = std::is_convertible_v<From, To>; template <typename T> concept decays_to_executor = execution::executor<std::decay_t<T>>; -template <typename T> +template <typename T, typename Executor = any_io_executor> concept execution_context = requires (T& t) { - {t.get_executor()} -> decays_to_executor; + {t.get_executor()} -> convertible_to<Executor>; }; template <typename Yield, typename Return> @@ -97,17 +100,59 @@ struct coro_handler<T, true> template <typename Result, bool IsNoexcept> using coro_handler_t = typename coro_handler<Result, IsNoexcept>::type; +} // namespace detail + +#if defined(GENERATING_DOCUMENTATION) + +/// The traits describing the resumable coroutine behaviour. +/** + * Template parameter @c Yield specifies type or signature used by co_yield, + * @c Return specifies the type used for co_return, and @c Executor specifies + * the underlying executor type. + */ +template <typename Yield, typename Return, typename Executor> +struct coro_traits +{ + /// The value that can be passed into a symmetrical cororoutine. @c void if + /// asymmetrical. + using input_type = argument_dependent; + + /// The type that can be passed out through a co_yield. + using yield_type = argument_dependent; + + /// The type that can be passed out through a co_return. + using return_type = argument_dependent; + + /// The type received by a co_await or async_resume. It's a combination of + /// yield and return. + using result_type = argument_dependent; + + /// The signature used by the async_resume. + using signature_type = argument_dependent; + + /// Whether or not the coroutine is noexcept. + constexpr static bool is_noexcept = argument_dependent; + + /// The error type of the coroutine. @c void for noexcept. + using error_type = argument_dependent; + + /// Completion handler type used by async_resume. + using completion_handler = argument_dependent; +}; + +#else // defined(GENERATING_DOCUMENTATION) + template <typename Yield, typename Return, typename Executor> struct coro_traits { using input_type = void; using yield_type = Yield; using return_type = Return; - using result_type = coro_result_t<yield_type, return_type>; + using result_type = detail::coro_result_t<yield_type, return_type>; using signature_type = result_type(); constexpr static bool is_noexcept = false; using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>; - using completion_handler = coro_handler_t<result_type, is_noexcept>; + using completion_handler = detail::coro_handler_t<result_type, is_noexcept>; }; template <typename T, typename Return, typename Executor> @@ -116,11 +161,11 @@ struct coro_traits<T(), Return, Executor> using input_type = void; using yield_type = T; using return_type = Return; - using result_type = coro_result_t<yield_type, return_type>; + using result_type = detail::coro_result_t<yield_type, return_type>; using signature_type = result_type(); constexpr static bool is_noexcept = false; using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>; - using completion_handler = coro_handler_t<result_type, is_noexcept>; + using completion_handler = detail::coro_handler_t<result_type, is_noexcept>; }; template <typename T, typename Return, typename Executor> @@ -129,11 +174,11 @@ struct coro_traits<T() noexcept, Return, Executor> using input_type = void; using yield_type = T; using return_type = Return; - using result_type = coro_result_t<yield_type, return_type>; + using result_type = detail::coro_result_t<yield_type, return_type>; using signature_type = result_type(); constexpr static bool is_noexcept = true; using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>; - using completion_handler = coro_handler_t<result_type, is_noexcept>; + using completion_handler = detail::coro_handler_t<result_type, is_noexcept>; }; template <typename T, typename U, typename Return, typename Executor> @@ -142,11 +187,11 @@ struct coro_traits<T(U), Return, Executor> using input_type = U; using yield_type = T; using return_type = Return; - using result_type = coro_result_t<yield_type, return_type>; + using result_type = detail::coro_result_t<yield_type, return_type>; using signature_type = result_type(input_type); constexpr static bool is_noexcept = false; using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>; - using completion_handler = coro_handler_t<result_type, is_noexcept>; + using completion_handler = detail::coro_handler_t<result_type, is_noexcept>; }; template <typename T, typename U, typename Return, typename Executor> @@ -155,28 +200,28 @@ struct coro_traits<T(U) noexcept, Return, Executor> using input_type = U; using yield_type = T; using return_type = Return; - using result_type = coro_result_t<yield_type, return_type>; + using result_type = detail::coro_result_t<yield_type, return_type>; using signature_type = result_type(input_type); constexpr static bool is_noexcept = true; using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>; - using completion_handler = coro_handler_t<result_type, is_noexcept>; + using completion_handler = detail::coro_handler_t<result_type, is_noexcept>; }; - template <typename Executor> struct coro_traits<void() noexcept, void, Executor> { using input_type = void; using yield_type = void; using return_type = void; - using result_type = coro_result_t<yield_type, return_type>; + using result_type = detail::coro_result_t<yield_type, return_type>; using signature_type = result_type(input_type); constexpr static bool is_noexcept = true; using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>; - using completion_handler = coro_handler_t<result_type, is_noexcept>; + using completion_handler = detail::coro_handler_t<result_type, is_noexcept>; }; -} // namespace detail +#endif // defined(GENERATING_DOCUMENTATION) + } // namespace experimental } // namespace asio diff --git a/3rdparty/asio/include/asio/experimental/deferred.hpp b/3rdparty/asio/include/asio/experimental/deferred.hpp index f09be1582a3..c722ad1a2de 100644 --- a/3rdparty/asio/include/asio/experimental/deferred.hpp +++ b/3rdparty/asio/include/asio/experimental/deferred.hpp @@ -2,7 +2,7 @@ // experimental/deferred.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,590 +16,21 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" -#include <tuple> -#include "asio/associator.hpp" -#include "asio/async_result.hpp" -#include "asio/detail/type_traits.hpp" +#include "asio/deferred.hpp" #include "asio/detail/push_options.hpp" namespace asio { namespace experimental { -/// Trait for detecting objects that are usable as deferred operations. -template <typename T> -struct is_deferred : false_type -{ -}; - -namespace detail { - -// Helper trait for getting the completion signature from an async operation. - -struct deferred_signature_probe {}; - -template <typename T> -struct deferred_signature_probe_result -{ - typedef T type; -}; - -template <typename T> -struct deferred_signature -{ - typedef typename decltype( - declval<T>()(declval<deferred_signature_probe>()))::type type; -}; - -// Helper trait for getting the completion signature of the tail in a sequence -// when invoked with the specified arguments. - -template <typename HeadSignature, typename Tail> -struct deferred_sequence_signature; - -template <typename R, typename... Args, typename Tail> -struct deferred_sequence_signature<R(Args...), Tail> -{ - static_assert( - !is_same<decltype(declval<Tail>()(declval<Args>()...)), void>::value, - "deferred functions must produce a deferred return type"); - - typedef typename decltype( - declval<Tail>()(declval<Args>()...)( - declval<deferred_signature_probe>()))::type type; -}; - -// Completion handler for the head component of a deferred sequence. -template <typename Handler, typename Tail> -class deferred_sequence_handler -{ -public: - template <typename H, typename T> - explicit deferred_sequence_handler( - ASIO_MOVE_ARG(H) handler, ASIO_MOVE_ARG(T) tail) - : handler_(ASIO_MOVE_CAST(H)(handler)), - tail_(ASIO_MOVE_CAST(T)(tail)) - { - } - - template <typename... Args> - void operator()(ASIO_MOVE_ARG(Args)... args) - { - ASIO_MOVE_OR_LVALUE(Tail)(tail_)( - ASIO_MOVE_CAST(Args)(args)...)( - ASIO_MOVE_OR_LVALUE(Handler)(handler_)); - } - -//private: - Handler handler_; - Tail tail_; -}; - -} // namespace detail - -/// Used to represent an empty deferred action. -struct deferred_noop -{ - /// No effect. - template <typename... Args> - void operator()(ASIO_MOVE_ARG(Args)...) ASIO_RVALUE_REF_QUAL - { - } - -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - /// No effect. - template <typename... Args> - decltype(auto) operator()(ASIO_MOVE_ARG(Args)...) const & - { - } -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) -}; - -#if !defined(GENERATING_DOCUMENTATION) -template <> -struct is_deferred<deferred_noop> : true_type -{ -}; -#endif // !defined(GENERATING_DOCUMENTATION) - -/// Tag type to disambiguate deferred constructors. -struct deferred_init_tag {}; - -/// Wraps a function object so that it may be used as an element in a deferred -/// composition. -template <typename Function> -class deferred_function -{ -public: - /// Constructor. - template <typename F> - ASIO_CONSTEXPR explicit deferred_function( - deferred_init_tag, ASIO_MOVE_ARG(F) function) - : function_(ASIO_MOVE_CAST(F)(function)) - { - } - - template <typename... Args> - decltype(auto) operator()( - ASIO_MOVE_ARG(Args)... args) ASIO_RVALUE_REF_QUAL - { - return ASIO_MOVE_CAST(Function)(function_)( - ASIO_MOVE_CAST(Args)(args)...); - } - -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - template <typename... Args> - decltype(auto) operator()( - ASIO_MOVE_ARG(Args)... args) const & - { - return deferred_function(*this)( - ASIO_MOVE_CAST(Args)(args)...); - } -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -//private: - Function function_; -}; - -#if !defined(GENERATING_DOCUMENTATION) -template <typename Function> -struct is_deferred<deferred_function<Function> > : true_type -{ -}; -#endif // !defined(GENERATING_DOCUMENTATION) - -/// Encapsulates deferred values. -template <typename... Values> -class ASIO_NODISCARD deferred_values -{ -private: - std::tuple<Values...> values_; - - struct initiate - { - template <typename Handler, typename... V> - void operator()(Handler handler, ASIO_MOVE_ARG(V)... values) - { - ASIO_MOVE_OR_LVALUE(Handler)(handler)( - ASIO_MOVE_CAST(V)(values)...); - } - }; - - template <typename CompletionToken, std::size_t... I> - decltype(auto) invoke_helper( - ASIO_MOVE_ARG(CompletionToken) token, - std::index_sequence<I...>) - { - return asio::async_initiate<CompletionToken, void(Values...)>( - initiate(), token, - std::get<I>(ASIO_MOVE_CAST(std::tuple<Values...>)(values_))...); - } - -public: - /// Construct a deferred asynchronous operation from the arguments to an - /// initiation function object. - template <typename... V> - ASIO_CONSTEXPR explicit deferred_values( - deferred_init_tag, ASIO_MOVE_ARG(V)... values) - : values_(ASIO_MOVE_CAST(V)(values)...) - { - } - - /// Initiate the deferred operation using the supplied completion token. - template <ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken> - decltype(auto) operator()( - ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL - { - return this->invoke_helper( - ASIO_MOVE_CAST(CompletionToken)(token), - std::index_sequence_for<Values...>()); - } - -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - template <ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken> - decltype(auto) operator()( - ASIO_MOVE_ARG(CompletionToken) token) const & - { - return deferred_values(*this)( - ASIO_MOVE_CAST(CompletionToken)(token)); - } -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) -}; - -#if !defined(GENERATING_DOCUMENTATION) -template <typename... Values> -struct is_deferred<deferred_values<Values...> > : true_type -{ -}; -#endif // !defined(GENERATING_DOCUMENTATION) - -/// Encapsulates a deferred asynchronous operation. -template <typename Signature, typename Initiation, typename... InitArgs> -class ASIO_NODISCARD deferred_async_operation -{ -private: - typename decay<Initiation>::type initiation_; - typedef std::tuple<typename decay<InitArgs>::type...> init_args_t; - init_args_t init_args_; - - template <typename CompletionToken, std::size_t... I> - decltype(auto) invoke_helper( - ASIO_MOVE_ARG(CompletionToken) token, - std::index_sequence<I...>) - { - return asio::async_initiate<CompletionToken, Signature>( - ASIO_MOVE_CAST(typename decay<Initiation>::type)(initiation_), - token, std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...); - } - -public: - /// Construct a deferred asynchronous operation from the arguments to an - /// initiation function object. - template <typename I, typename... A> - ASIO_CONSTEXPR explicit deferred_async_operation( - deferred_init_tag, ASIO_MOVE_ARG(I) initiation, - ASIO_MOVE_ARG(A)... init_args) - : initiation_(ASIO_MOVE_CAST(I)(initiation)), - init_args_(ASIO_MOVE_CAST(A)(init_args)...) - { - } - - /// Initiate the asynchronous operation using the supplied completion token. - template <ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken> - decltype(auto) operator()( - ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL - { - return this->invoke_helper( - ASIO_MOVE_CAST(CompletionToken)(token), - std::index_sequence_for<InitArgs...>()); - } - -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - template <ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken> - decltype(auto) operator()( - ASIO_MOVE_ARG(CompletionToken) token) const & - { - return deferred_async_operation(*this)( - ASIO_MOVE_CAST(CompletionToken)(token)); - } -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) -}; - -#if !defined(GENERATING_DOCUMENTATION) -template <typename Signature, typename Initiation, typename... InitArgs> -struct is_deferred< - deferred_async_operation<Signature, Initiation, InitArgs...> > : true_type -{ -}; -#endif // !defined(GENERATING_DOCUMENTATION) - -/// Defines a link between two consecutive operations in a sequence. -template <typename Head, typename Tail> -class ASIO_NODISCARD deferred_sequence -{ -private: - typedef typename detail::deferred_sequence_signature< - typename detail::deferred_signature<Head>::type, Tail>::type - signature; - -public: - template <typename H, typename T> - ASIO_CONSTEXPR explicit deferred_sequence(deferred_init_tag, - ASIO_MOVE_ARG(H) head, ASIO_MOVE_ARG(T) tail) - : head_(ASIO_MOVE_CAST(H)(head)), - tail_(ASIO_MOVE_CAST(T)(tail)) - { - } - - template <ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken> - decltype(auto) operator()( - ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL - { - return asio::async_initiate<CompletionToken, signature>( - initiate(), token, ASIO_MOVE_OR_LVALUE(Head)(head_), - ASIO_MOVE_OR_LVALUE(Tail)(tail_)); - } - -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - template <ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken> - decltype(auto) operator()( - ASIO_MOVE_ARG(CompletionToken) token) const & - { - return deferred_sequence(*this)( - ASIO_MOVE_CAST(CompletionToken)(token)); - } -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -private: - struct initiate - { - template <typename Handler> - void operator()(ASIO_MOVE_ARG(Handler) handler, - Head head, ASIO_MOVE_ARG(Tail) tail) - { - ASIO_MOVE_OR_LVALUE(Head)(head)( - detail::deferred_sequence_handler< - typename decay<Handler>::type, - typename decay<Tail>::type>( - ASIO_MOVE_CAST(Handler)(handler), - ASIO_MOVE_CAST(Tail)(tail))); - } - }; - - Head head_; - Tail tail_; -}; - -#if !defined(GENERATING_DOCUMENTATION) -template <typename Head, typename Tail> -struct is_deferred<deferred_sequence<Head, Tail> > : true_type -{ -}; -#endif // !defined(GENERATING_DOCUMENTATION) - -/// Used to represent a deferred conditional branch. -template <typename OnTrue = deferred_noop, - typename OnFalse = deferred_noop> -class ASIO_NODISCARD deferred_conditional -{ -public: - /// Construct a deferred conditional with the value to determine which branch - /// will be executed. - ASIO_CONSTEXPR explicit deferred_conditional(bool b) - : on_true_(), - on_false_(), - bool_(b) - { - } - - /// Invoke the conditional branch bsaed on the stored alue. - template <typename... Args> - auto operator()(ASIO_MOVE_ARG(Args)... args) ASIO_RVALUE_REF_QUAL - { - if (bool_) - { - return ASIO_MOVE_OR_LVALUE(OnTrue)(on_true_)( - ASIO_MOVE_CAST(Args)(args)...); - } - else - { - return ASIO_MOVE_OR_LVALUE(OnFalse)(on_false_)( - ASIO_MOVE_CAST(Args)(args)...); - } - } - -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - template <typename... Args> - auto operator()(ASIO_MOVE_ARG(Args)... args) const & - { - return deferred_conditional(*this)( - ASIO_MOVE_CAST(Args)(args)...); - } -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - - /// Set the true branch of the conditional. - template <typename T> - deferred_conditional<T, OnFalse> then(T on_true, - typename constraint< - is_deferred<T>::value - >::type* = 0, - typename constraint< - is_same< - typename conditional<true, OnTrue, T>::type, - deferred_noop - >::value - >::type* = 0) ASIO_RVALUE_REF_QUAL - { - return deferred_conditional<T, OnFalse>( - bool_, ASIO_MOVE_CAST(T)(on_true), - ASIO_MOVE_CAST(OnFalse)(on_false_)); - } - - /// Set the false branch of the conditional. - template <typename T> - deferred_conditional<OnTrue, T> otherwise(T on_false, - typename constraint< - is_deferred<T>::value - >::type* = 0, - typename constraint< - !is_same< - typename conditional<true, OnTrue, T>::type, - deferred_noop - >::value - >::type* = 0, - typename constraint< - is_same< - typename conditional<true, OnFalse, T>::type, - deferred_noop - >::value - >::type* = 0) ASIO_RVALUE_REF_QUAL - { - return deferred_conditional<OnTrue, T>( - bool_, ASIO_MOVE_CAST(OnTrue)(on_true_), - ASIO_MOVE_CAST(T)(on_false)); - } - -private: - template <typename T, typename F> friend class deferred_conditional; - - // Helper constructor. - template <typename T, typename F> - explicit deferred_conditional(bool b, ASIO_MOVE_ARG(T) on_true, - ASIO_MOVE_ARG(F) on_false) - : on_true_(ASIO_MOVE_CAST(T)(on_true)), - on_false_(ASIO_MOVE_CAST(F)(on_false)), - bool_(b) - { - } - - OnTrue on_true_; - OnFalse on_false_; - bool bool_; -}; - -#if !defined(GENERATING_DOCUMENTATION) -template <typename OnTrue, typename OnFalse> -struct is_deferred<deferred_conditional<OnTrue, OnFalse> > : true_type -{ -}; -#endif // !defined(GENERATING_DOCUMENTATION) - -/// Class used to specify that an asynchronous operation should return a -/// function object to lazily launch the operation. -/** - * The deferred_t class is used to indicate that an asynchronous operation - * should return a function object which is itself an initiation function. A - * deferred_t object may be passed as a completion token to an asynchronous - * operation, typically using the special value @c asio::deferred. For - * example: - * - * @code auto my_sender - * = my_socket.async_read_some(my_buffer, - * asio::experimental::deferred); @endcode - * - * The initiating function (async_read_some in the above example) returns a - * function object that will lazily initiate the operation. - */ -class deferred_t -{ -public: - /// Default constructor. - ASIO_CONSTEXPR deferred_t() - { - } - - /// Adapts an executor to add the @c deferred_t completion token as the - /// default. - template <typename InnerExecutor> - struct executor_with_default : InnerExecutor - { - /// Specify @c deferred_t as the default completion token type. - typedef deferred_t default_completion_token_type; - - /// Construct the adapted executor from the inner executor type. - template <typename InnerExecutor1> - executor_with_default(const InnerExecutor1& ex, - typename constraint< - conditional< - !is_same<InnerExecutor1, executor_with_default>::value, - is_convertible<InnerExecutor1, InnerExecutor>, - false_type - >::type::value - >::type = 0) ASIO_NOEXCEPT - : InnerExecutor(ex) - { - } - }; - - /// Type alias to adapt an I/O object to use @c deferred_t as its - /// default completion token type. -#if defined(ASIO_HAS_ALIAS_TEMPLATES) \ - || defined(GENERATING_DOCUMENTATION) - template <typename T> - using as_default_on_t = typename T::template rebind_executor< - executor_with_default<typename T::executor_type> >::other; -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - - /// Function helper to adapt an I/O object to use @c deferred_t as its - /// default completion token type. - template <typename T> - static typename decay<T>::type::template rebind_executor< - executor_with_default<typename decay<T>::type::executor_type> - >::other - as_default_on(ASIO_MOVE_ARG(T) object) - { - return typename decay<T>::type::template rebind_executor< - executor_with_default<typename decay<T>::type::executor_type> - >::other(ASIO_MOVE_CAST(T)(object)); - } - - /// Creates a new deferred from a function. - template <typename Function> - typename constraint< - !is_deferred<typename decay<Function>::type>::value, - deferred_function<typename decay<Function>::type> - >::type operator()(ASIO_MOVE_ARG(Function) function) const - { - return deferred_function<typename decay<Function>::type>( - deferred_init_tag{}, ASIO_MOVE_CAST(Function)(function)); - } - - /// Passes through anything that is already deferred. - template <typename T> - typename constraint< - is_deferred<typename decay<T>::type>::value, - typename decay<T>::type - >::type operator()(ASIO_MOVE_ARG(T) t) const - { - return ASIO_MOVE_CAST(T)(t); - } - - /// Returns a deferred operation that returns the provided values. - template <typename... Args> - static ASIO_CONSTEXPR deferred_values<typename decay<Args>::type...> - values(ASIO_MOVE_ARG(Args)... args) - { - return deferred_values<typename decay<Args>::type...>( - deferred_init_tag{}, ASIO_MOVE_CAST(Args)(args)...); - } - - /// Creates a conditional object for branching deferred operations. - static ASIO_CONSTEXPR deferred_conditional<> when(bool b) - { - return deferred_conditional<>(b); - } -}; - -/// Pipe operator used to chain deferred operations. -template <typename Head, typename Tail> -inline auto operator|(Head head, ASIO_MOVE_ARG(Tail) tail) - -> typename constraint< - is_deferred<Head>::value, - decltype(ASIO_MOVE_OR_LVALUE(Head)(head)( - ASIO_MOVE_CAST(Tail)(tail))) - >::type -{ - return ASIO_MOVE_OR_LVALUE(Head)(head)( - ASIO_MOVE_CAST(Tail)(tail)); -} - -/// A special value, similar to std::nothrow. -/** - * See the documentation for asio::experimental::deferred_t for a usage - * example. - */ -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) -constexpr deferred_t deferred; -#elif defined(ASIO_MSVC) -__declspec(selectany) deferred_t deferred; -#endif +#if !defined(ASIO_NO_DEPRECATED) +using asio::deferred_t; +using asio::deferred; +#endif // !defined(ASIO_NO_DEPRECATED) } // namespace experimental } // namespace asio #include "asio/detail/pop_options.hpp" -#include "asio/experimental/impl/deferred.hpp" - #endif // ASIO_EXPERIMENTAL_DEFERRED_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/channel_handler.hpp b/3rdparty/asio/include/asio/experimental/detail/channel_handler.hpp new file mode 100644 index 00000000000..0152c2e76ff --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/detail/channel_handler.hpp @@ -0,0 +1,77 @@ +// +// experimental/detail/channel_handler.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_HANDLER_HPP +#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_HANDLER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/associator.hpp" +#include "asio/experimental/detail/channel_payload.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename Payload, typename Handler> +class channel_handler +{ +public: + channel_handler(Payload&& p, Handler& h) + : payload_(static_cast<Payload&&>(p)), + handler_(static_cast<Handler&&>(h)) + { + } + + void operator()() + { + payload_.receive(handler_); + } + +//private: + Payload payload_; + Handler handler_; +}; + +} // namespace detail +} // namespace experimental + +template <template <typename, typename> class Associator, + typename Payload, typename Handler, typename DefaultCandidate> +struct associator<Associator, + experimental::detail::channel_handler<Payload, Handler>, + DefaultCandidate> + : Associator<Handler, DefaultCandidate> +{ + static typename Associator<Handler, DefaultCandidate>::type get( + const experimental::detail::channel_handler<Payload, Handler>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const experimental::detail::channel_handler<Payload, Handler>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) + { + return Associator<Handler, DefaultCandidate>::get(h.handler_, c); + } +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_HANDLER_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/channel_message.hpp b/3rdparty/asio/include/asio/experimental/detail/channel_message.hpp new file mode 100644 index 00000000000..16446f0c1bb --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/detail/channel_message.hpp @@ -0,0 +1,129 @@ +// +// experimental/detail/channel_message.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_MESSAGE_HPP +#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_MESSAGE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <tuple> +#include "asio/detail/type_traits.hpp" +#include "asio/detail/utility.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename Signature> +class channel_message; + +template <typename R> +class channel_message<R()> +{ +public: + channel_message(int) + { + } + + template <typename Handler> + void receive(Handler& handler) + { + static_cast<Handler&&>(handler)(); + } +}; + +template <typename R, typename Arg0> +class channel_message<R(Arg0)> +{ +public: + template <typename T0> + channel_message(int, T0&& t0) + : arg0_(static_cast<T0&&>(t0)) + { + } + + template <typename Handler> + void receive(Handler& handler) + { + static_cast<Handler&&>(handler)( + static_cast<arg0_type&&>(arg0_)); + } + +private: + typedef decay_t<Arg0> arg0_type; + arg0_type arg0_; +}; + +template <typename R, typename Arg0, typename Arg1> +class channel_message<R(Arg0, Arg1)> +{ +public: + template <typename T0, typename T1> + channel_message(int, T0&& t0, T1&& t1) + : arg0_(static_cast<T0&&>(t0)), + arg1_(static_cast<T1&&>(t1)) + { + } + + template <typename Handler> + void receive(Handler& handler) + { + static_cast<Handler&&>(handler)( + static_cast<arg0_type&&>(arg0_), + static_cast<arg1_type&&>(arg1_)); + } + +private: + typedef decay_t<Arg0> arg0_type; + arg0_type arg0_; + typedef decay_t<Arg1> arg1_type; + arg1_type arg1_; +}; + +template <typename R, typename... Args> +class channel_message<R(Args...)> +{ +public: + template <typename... T> + channel_message(int, T&&... t) + : args_(static_cast<T&&>(t)...) + { + } + + template <typename Handler> + void receive(Handler& h) + { + this->do_receive(h, asio::detail::index_sequence_for<Args...>()); + } + +private: + template <typename Handler, std::size_t... I> + void do_receive(Handler& h, asio::detail::index_sequence<I...>) + { + static_cast<Handler&&>(h)( + std::get<I>(static_cast<args_type&&>(args_))...); + } + + typedef std::tuple<decay_t<Args>...> args_type; + args_type args_; +}; + +} // namespace detail +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_MESSAGE_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/channel_operation.hpp b/3rdparty/asio/include/asio/experimental/detail/channel_operation.hpp new file mode 100644 index 00000000000..1231f1f87c1 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/detail/channel_operation.hpp @@ -0,0 +1,361 @@ +// +// experimental/detail/channel_operation.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP +#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/associated_allocator.hpp" +#include "asio/associated_executor.hpp" +#include "asio/associated_immediate_executor.hpp" +#include "asio/detail/initiate_post.hpp" +#include "asio/detail/initiate_dispatch.hpp" +#include "asio/detail/op_queue.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/execution/executor.hpp" +#include "asio/execution/outstanding_work.hpp" +#include "asio/executor_work_guard.hpp" +#include "asio/prefer.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +// Base class for all channel operations. A function pointer is used instead of +// virtual functions to avoid the associated overhead. +class channel_operation ASIO_INHERIT_TRACKED_HANDLER +{ +public: + template <typename Executor, typename = void, typename = void> + class handler_work_base; + + template <typename Handler, typename IoExecutor, typename = void> + class handler_work; + + void destroy() + { + func_(this, destroy_op, 0); + } + +protected: + enum action + { + destroy_op = 0, + immediate_op = 1, + post_op = 2, + dispatch_op = 3, + cancel_op = 4, + close_op = 5 + }; + + typedef void (*func_type)(channel_operation*, action, void*); + + channel_operation(func_type func) + : next_(0), + func_(func), + cancellation_key_(0) + { + } + + // Prevents deletion through this type. + ~channel_operation() + { + } + + friend class asio::detail::op_queue_access; + channel_operation* next_; + func_type func_; + +public: + // The operation key used for targeted cancellation. + void* cancellation_key_; +}; + +template <typename Executor, typename, typename> +class channel_operation::handler_work_base +{ +public: + typedef decay_t< + prefer_result_t<Executor, + execution::outstanding_work_t::tracked_t + > + > executor_type; + + handler_work_base(int, const Executor& ex) + : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) + { + } + + const executor_type& get_executor() const noexcept + { + return executor_; + } + + template <typename IoExecutor, typename Function, typename Handler> + void post(const IoExecutor& io_exec, Function& function, Handler&) + { + (asio::detail::initiate_post_with_executor<IoExecutor>(io_exec))( + static_cast<Function&&>(function)); + } + + template <typename Function, typename Handler> + void dispatch(Function& function, Handler& handler) + { + associated_allocator_t<Handler> allocator = + (get_associated_allocator)(handler); + + asio::prefer(executor_, + execution::allocator(allocator) + ).execute(static_cast<Function&&>(function)); + } + +private: + executor_type executor_; +}; + +template <typename Executor> +class channel_operation::handler_work_base<Executor, + enable_if_t< + execution::is_executor<Executor>::value + >, + enable_if_t< + can_require<Executor, execution::blocking_t::never_t>::value + > + > +{ +public: + typedef decay_t< + prefer_result_t<Executor, + execution::outstanding_work_t::tracked_t + > + > executor_type; + + handler_work_base(int, const Executor& ex) + : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) + { + } + + const executor_type& get_executor() const noexcept + { + return executor_; + } + + template <typename IoExecutor, typename Function, typename Handler> + void post(const IoExecutor&, Function& function, Handler& handler) + { + associated_allocator_t<Handler> allocator = + (get_associated_allocator)(handler); + + asio::prefer( + asio::require(executor_, execution::blocking.never), + execution::allocator(allocator) + ).execute(static_cast<Function&&>(function)); + } + + template <typename Function, typename Handler> + void dispatch(Function& function, Handler& handler) + { + associated_allocator_t<Handler> allocator = + (get_associated_allocator)(handler); + + asio::prefer(executor_, + execution::allocator(allocator) + ).execute(static_cast<Function&&>(function)); + } + +private: + executor_type executor_; +}; + +#if !defined(ASIO_NO_TS_EXECUTORS) + +template <typename Executor> +class channel_operation::handler_work_base<Executor, + enable_if_t< + !execution::is_executor<Executor>::value + > + > +{ +public: + typedef Executor executor_type; + + handler_work_base(int, const Executor& ex) + : work_(ex) + { + } + + executor_type get_executor() const noexcept + { + return work_.get_executor(); + } + + template <typename IoExecutor, typename Function, typename Handler> + void post(const IoExecutor&, Function& function, Handler& handler) + { + associated_allocator_t<Handler> allocator = + (get_associated_allocator)(handler); + + work_.get_executor().post( + static_cast<Function&&>(function), allocator); + } + + template <typename Function, typename Handler> + void dispatch(Function& function, Handler& handler) + { + associated_allocator_t<Handler> allocator = + (get_associated_allocator)(handler); + + work_.get_executor().dispatch( + static_cast<Function&&>(function), allocator); + } + +private: + executor_work_guard<Executor> work_; +}; + +#endif // !defined(ASIO_NO_TS_EXECUTORS) + +template <typename Handler, typename IoExecutor, typename> +class channel_operation::handler_work : + channel_operation::handler_work_base<IoExecutor>, + channel_operation::handler_work_base< + associated_executor_t<Handler, IoExecutor>, IoExecutor> +{ +public: + typedef channel_operation::handler_work_base<IoExecutor> base1_type; + + typedef channel_operation::handler_work_base< + associated_executor_t<Handler, IoExecutor>, IoExecutor> + base2_type; + + handler_work(Handler& handler, const IoExecutor& io_ex) noexcept + : base1_type(0, io_ex), + base2_type(0, (get_associated_executor)(handler, io_ex)) + { + } + + template <typename Function> + void post(Function& function, Handler& handler) + { + base2_type::post(base1_type::get_executor(), function, handler); + } + + template <typename Function> + void dispatch(Function& function, Handler& handler) + { + base2_type::dispatch(function, handler); + } + + template <typename Function> + void immediate(Function& function, Handler& handler, ...) + { + typedef associated_immediate_executor_t<Handler, + typename base1_type::executor_type> immediate_ex_type; + + immediate_ex_type immediate_ex = (get_associated_immediate_executor)( + handler, base1_type::get_executor()); + + (asio::detail::initiate_dispatch_with_executor<immediate_ex_type>( + immediate_ex))(static_cast<Function&&>(function)); + } + + template <typename Function> + void immediate(Function& function, Handler&, + enable_if_t< + is_same< + typename associated_immediate_executor< + conditional_t<false, Function, Handler>, + typename base1_type::executor_type>:: + asio_associated_immediate_executor_is_unspecialised, + void + >::value + >*) + { + (asio::detail::initiate_post_with_executor< + typename base1_type::executor_type>( + base1_type::get_executor()))( + static_cast<Function&&>(function)); + } +}; + +template <typename Handler, typename IoExecutor> +class channel_operation::handler_work< + Handler, IoExecutor, + enable_if_t< + is_same< + typename associated_executor<Handler, + IoExecutor>::asio_associated_executor_is_unspecialised, + void + >::value + > + > : handler_work_base<IoExecutor> +{ +public: + typedef channel_operation::handler_work_base<IoExecutor> base1_type; + + handler_work(Handler&, const IoExecutor& io_ex) noexcept + : base1_type(0, io_ex) + { + } + + template <typename Function> + void post(Function& function, Handler& handler) + { + base1_type::post(base1_type::get_executor(), function, handler); + } + + template <typename Function> + void dispatch(Function& function, Handler& handler) + { + base1_type::dispatch(function, handler); + } + + template <typename Function> + void immediate(Function& function, Handler& handler, ...) + { + typedef associated_immediate_executor_t<Handler, + typename base1_type::executor_type> immediate_ex_type; + + immediate_ex_type immediate_ex = (get_associated_immediate_executor)( + handler, base1_type::get_executor()); + + (asio::detail::initiate_dispatch_with_executor<immediate_ex_type>( + immediate_ex))(static_cast<Function&&>(function)); + } + + template <typename Function> + void immediate(Function& function, Handler& handler, + enable_if_t< + is_same< + typename associated_immediate_executor< + conditional_t<false, Function, Handler>, + typename base1_type::executor_type>:: + asio_associated_immediate_executor_is_unspecialised, + void + >::value + >*) + { + base1_type::post(base1_type::get_executor(), function, handler); + } +}; + +} // namespace detail +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/channel_payload.hpp b/3rdparty/asio/include/asio/experimental/detail/channel_payload.hpp new file mode 100644 index 00000000000..31614cd5dbc --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/detail/channel_payload.hpp @@ -0,0 +1,222 @@ +// +// experimental/detail/channel_payload.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_HPP +#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/error_code.hpp" +#include "asio/experimental/detail/channel_message.hpp" + +#if defined(ASIO_HAS_STD_VARIANT) +# include <variant> +#else // defined(ASIO_HAS_STD_VARIANT) +# include <new> +#endif // defined(ASIO_HAS_STD_VARIANT) + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename... Signatures> +class channel_payload; + +template <typename R> +class channel_payload<R()> +{ +public: + explicit channel_payload(channel_message<R()>) + { + } + + template <typename Handler> + void receive(Handler& handler) + { + static_cast<Handler&&>(handler)(); + } +}; + +template <typename Signature> +class channel_payload<Signature> +{ +public: + channel_payload(channel_message<Signature>&& m) + : message_(static_cast<channel_message<Signature>&&>(m)) + { + } + + template <typename Handler> + void receive(Handler& handler) + { + message_.receive(handler); + } + +private: + channel_message<Signature> message_; +}; + +#if defined(ASIO_HAS_STD_VARIANT) + +template <typename... Signatures> +class channel_payload +{ +public: + template <typename Signature> + channel_payload(channel_message<Signature>&& m) + : message_(static_cast<channel_message<Signature>&&>(m)) + { + } + + template <typename Handler> + void receive(Handler& handler) + { + std::visit( + [&](auto& message) + { + message.receive(handler); + }, message_); + } + +private: + std::variant<channel_message<Signatures>...> message_; +}; + +#else // defined(ASIO_HAS_STD_VARIANT) + +template <typename R1, typename R2> +class channel_payload<R1(), R2(asio::error_code)> +{ +public: + typedef channel_message<R1()> void_message_type; + typedef channel_message<R2(asio::error_code)> error_message_type; + + channel_payload(void_message_type&&) + : message_(0, asio::error_code()), + empty_(true) + { + } + + channel_payload(error_message_type&& m) + : message_(static_cast<error_message_type&&>(m)), + empty_(false) + { + } + + template <typename Handler> + void receive(Handler& handler) + { + if (empty_) + channel_message<R1()>(0).receive(handler); + else + message_.receive(handler); + } + +private: + error_message_type message_; + bool empty_; +}; + +template <typename Sig1, typename Sig2> +class channel_payload<Sig1, Sig2> +{ +public: + typedef channel_message<Sig1> message_1_type; + typedef channel_message<Sig2> message_2_type; + + channel_payload(message_1_type&& m) + : index_(1) + { + new (&storage_.message_1_) message_1_type(static_cast<message_1_type&&>(m)); + } + + channel_payload(message_2_type&& m) + : index_(2) + { + new (&storage_.message_2_) message_2_type(static_cast<message_2_type&&>(m)); + } + + channel_payload(channel_payload&& other) + : index_(other.index_) + { + switch (index_) + { + case 1: + new (&storage_.message_1_) message_1_type( + static_cast<message_1_type&&>(other.storage_.message_1_)); + break; + case 2: + new (&storage_.message_2_) message_2_type( + static_cast<message_2_type&&>(other.storage_.message_2_)); + break; + default: + break; + } + } + + ~channel_payload() + { + switch (index_) + { + case 1: + storage_.message_1_.~message_1_type(); + break; + case 2: + storage_.message_2_.~message_2_type(); + break; + default: + break; + } + } + + template <typename Handler> + void receive(Handler& handler) + { + switch (index_) + { + case 1: + storage_.message_1_.receive(handler); + break; + case 2: + storage_.message_2_.receive(handler); + break; + default: + break; + } + } + +private: + union storage + { + storage() {} + ~storage() {} + + char dummy_; + message_1_type message_1_; + message_2_type message_2_; + } storage_; + unsigned char index_; +}; + +#endif // defined(ASIO_HAS_STD_VARIANT) + +} // namespace detail +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/channel_receive_op.hpp b/3rdparty/asio/include/asio/experimental/detail/channel_receive_op.hpp new file mode 100644 index 00000000000..89d8ac2a5ab --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/detail/channel_receive_op.hpp @@ -0,0 +1,127 @@ +// +// experimental/detail/channel_receive_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_RECEIVE_OP_HPP +#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_RECEIVE_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/error.hpp" +#include "asio/experimental/detail/channel_handler.hpp" +#include "asio/experimental/detail/channel_operation.hpp" +#include "asio/experimental/detail/channel_payload.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename Payload> +class channel_receive : public channel_operation +{ +public: + void immediate(Payload payload) + { + func_(this, immediate_op, &payload); + } + + void post(Payload payload) + { + func_(this, post_op, &payload); + } + + void dispatch(Payload payload) + { + func_(this, dispatch_op, &payload); + } + +protected: + channel_receive(func_type func) + : channel_operation(func) + { + } +}; + +template <typename Payload, typename Handler, typename IoExecutor> +class channel_receive_op : public channel_receive<Payload> +{ +public: + ASIO_DEFINE_HANDLER_PTR(channel_receive_op); + + template <typename... Args> + channel_receive_op(Handler& handler, const IoExecutor& io_ex) + : channel_receive<Payload>(&channel_receive_op::do_action), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_action(channel_operation* base, + channel_operation::action a, void* v) + { + // Take ownership of the operation object. + channel_receive_op* o(static_cast<channel_receive_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + channel_operation::handler_work<Handler, IoExecutor> w( + static_cast<channel_operation::handler_work<Handler, IoExecutor>&&>( + o->work_)); + + // Make a copy of the handler so that the memory can be deallocated before + // the handler is posted. Even if we're not about to post the handler, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + if (a != channel_operation::destroy_op) + { + Payload* payload = static_cast<Payload*>(v); + channel_handler<Payload, Handler> handler( + static_cast<Payload&&>(*payload), o->handler_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + ASIO_HANDLER_INVOCATION_BEGIN(()); + if (a == channel_operation::immediate_op) + w.immediate(handler, handler.handler_, 0); + else if (a == channel_operation::dispatch_op) + w.dispatch(handler, handler.handler_); + else + w.post(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + else + { + asio::detail::binder0<Handler> handler(o->handler_); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + } + } + +private: + Handler handler_; + channel_operation::handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_RECEIVE_OP_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/channel_send_functions.hpp b/3rdparty/asio/include/asio/experimental/detail/channel_send_functions.hpp new file mode 100644 index 00000000000..108dffec934 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/detail/channel_send_functions.hpp @@ -0,0 +1,192 @@ +// +// experimental/detail/channel_send_functions.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_FUNCTIONS_HPP +#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_FUNCTIONS_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/async_result.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/error_code.hpp" +#include "asio/experimental/detail/channel_message.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename Derived, typename Executor, typename... Signatures> +class channel_send_functions; + +template <typename Derived, typename Executor, typename R, typename... Args> +class channel_send_functions<Derived, Executor, R(Args...)> +{ +public: + template <typename... Args2> + enable_if_t< + is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value, + bool + > try_send(Args2&&... args) + { + typedef typename detail::channel_message<R(Args...)> message_type; + Derived* self = static_cast<Derived*>(this); + return self->service_->template try_send<message_type>( + self->impl_, false, static_cast<Args2&&>(args)...); + } + + template <typename... Args2> + enable_if_t< + is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value, + bool + > try_send_via_dispatch(Args2&&... args) + { + typedef typename detail::channel_message<R(Args...)> message_type; + Derived* self = static_cast<Derived*>(this); + return self->service_->template try_send<message_type>( + self->impl_, true, static_cast<Args2&&>(args)...); + } + + template <typename... Args2> + enable_if_t< + is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value, + std::size_t + > try_send_n(std::size_t count, Args2&&... args) + { + typedef typename detail::channel_message<R(Args...)> message_type; + Derived* self = static_cast<Derived*>(this); + return self->service_->template try_send_n<message_type>( + self->impl_, count, false, static_cast<Args2&&>(args)...); + } + + template <typename... Args2> + enable_if_t< + is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value, + std::size_t + > try_send_n_via_dispatch(std::size_t count, Args2&&... args) + { + typedef typename detail::channel_message<R(Args...)> message_type; + Derived* self = static_cast<Derived*>(this); + return self->service_->template try_send_n<message_type>( + self->impl_, count, true, static_cast<Args2&&>(args)...); + } + + template < + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) + CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> + auto async_send(Args... args, + CompletionToken&& token + ASIO_DEFAULT_COMPLETION_TOKEN(Executor)) + -> decltype( + async_initiate<CompletionToken, void (asio::error_code)>( + declval<typename conditional_t<false, CompletionToken, + Derived>::initiate_async_send>(), token, + declval<typename conditional_t<false, CompletionToken, + Derived>::payload_type>())) + { + typedef typename Derived::payload_type payload_type; + typedef typename detail::channel_message<R(Args...)> message_type; + Derived* self = static_cast<Derived*>(this); + return async_initiate<CompletionToken, void (asio::error_code)>( + typename Derived::initiate_async_send(self), token, + payload_type(message_type(0, static_cast<Args&&>(args)...))); + } +}; + +template <typename Derived, typename Executor, + typename R, typename... Args, typename... Signatures> +class channel_send_functions<Derived, Executor, R(Args...), Signatures...> : + public channel_send_functions<Derived, Executor, Signatures...> +{ +public: + using channel_send_functions<Derived, Executor, Signatures...>::try_send; + using channel_send_functions<Derived, Executor, Signatures...>::async_send; + + template <typename... Args2> + enable_if_t< + is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value, + bool + > try_send(Args2&&... args) + { + typedef typename detail::channel_message<R(Args...)> message_type; + Derived* self = static_cast<Derived*>(this); + return self->service_->template try_send<message_type>( + self->impl_, false, static_cast<Args2&&>(args)...); + } + + template <typename... Args2> + enable_if_t< + is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value, + bool + > try_send_via_dispatch(Args2&&... args) + { + typedef typename detail::channel_message<R(Args...)> message_type; + Derived* self = static_cast<Derived*>(this); + return self->service_->template try_send<message_type>( + self->impl_, true, static_cast<Args2&&>(args)...); + } + + template <typename... Args2> + enable_if_t< + is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value, + std::size_t + > try_send_n(std::size_t count, Args2&&... args) + { + typedef typename detail::channel_message<R(Args...)> message_type; + Derived* self = static_cast<Derived*>(this); + return self->service_->template try_send_n<message_type>( + self->impl_, count, false, static_cast<Args2&&>(args)...); + } + + template <typename... Args2> + enable_if_t< + is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value, + std::size_t + > try_send_n_via_dispatch(std::size_t count, Args2&&... args) + { + typedef typename detail::channel_message<R(Args...)> message_type; + Derived* self = static_cast<Derived*>(this); + return self->service_->template try_send_n<message_type>( + self->impl_, count, true, static_cast<Args2&&>(args)...); + } + + template < + ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) + CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> + auto async_send(Args... args, + CompletionToken&& token + ASIO_DEFAULT_COMPLETION_TOKEN(Executor)) + -> decltype( + async_initiate<CompletionToken, void (asio::error_code)>( + declval<typename conditional_t<false, CompletionToken, + Derived>::initiate_async_send>(), token, + declval<typename conditional_t<false, CompletionToken, + Derived>::payload_type>())) + { + typedef typename Derived::payload_type payload_type; + typedef typename detail::channel_message<R(Args...)> message_type; + Derived* self = static_cast<Derived*>(this); + return async_initiate<CompletionToken, void (asio::error_code)>( + typename Derived::initiate_async_send(self), token, + payload_type(message_type(0, static_cast<Args&&>(args)...))); + } +}; + +} // namespace detail +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_FUNCTIONS_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/channel_send_op.hpp b/3rdparty/asio/include/asio/experimental/detail/channel_send_op.hpp new file mode 100644 index 00000000000..4326c23253e --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/detail/channel_send_op.hpp @@ -0,0 +1,148 @@ +// +// experimental/detail/channel_send_op.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_OP_HPP +#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_OP_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/bind_handler.hpp" +#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/error.hpp" +#include "asio/experimental/channel_error.hpp" +#include "asio/experimental/detail/channel_operation.hpp" +#include "asio/experimental/detail/channel_payload.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename Payload> +class channel_send : public channel_operation +{ +public: + Payload get_payload() + { + return static_cast<Payload&&>(payload_); + } + + void immediate() + { + func_(this, immediate_op, 0); + } + + void post() + { + func_(this, post_op, 0); + } + + void cancel() + { + func_(this, cancel_op, 0); + } + + void close() + { + func_(this, close_op, 0); + } + +protected: + channel_send(func_type func, Payload&& payload) + : channel_operation(func), + payload_(static_cast<Payload&&>(payload)) + { + } + +private: + Payload payload_; +}; + +template <typename Payload, typename Handler, typename IoExecutor> +class channel_send_op : public channel_send<Payload> +{ +public: + ASIO_DEFINE_HANDLER_PTR(channel_send_op); + + channel_send_op(Payload&& payload, + Handler& handler, const IoExecutor& io_ex) + : channel_send<Payload>(&channel_send_op::do_action, + static_cast<Payload&&>(payload)), + handler_(static_cast<Handler&&>(handler)), + work_(handler_, io_ex) + { + } + + static void do_action(channel_operation* base, + channel_operation::action a, void*) + { + // Take ownership of the operation object. + channel_send_op* o(static_cast<channel_send_op*>(base)); + ptr p = { asio::detail::addressof(o->handler_), o, o }; + + ASIO_HANDLER_COMPLETION((*o)); + + // Take ownership of the operation's outstanding work. + channel_operation::handler_work<Handler, IoExecutor> w( + static_cast<channel_operation::handler_work<Handler, IoExecutor>&&>( + o->work_)); + + asio::error_code ec; + switch (a) + { + case channel_operation::cancel_op: + ec = error::channel_cancelled; + break; + case channel_operation::close_op: + ec = error::channel_closed; + break; + default: + break; + } + + // Make a copy of the handler so that the memory can be deallocated before + // the handler is posted. Even if we're not about to post the handler, a + // sub-object of the handler may be the true owner of the memory associated + // with the handler. Consequently, a local copy of the handler is required + // to ensure that any owning sub-object remains valid until after we have + // deallocated the memory here. + asio::detail::binder1<Handler, asio::error_code> + handler(o->handler_, ec); + p.h = asio::detail::addressof(handler.handler_); + p.reset(); + + // Post the completion if required. + if (a != channel_operation::destroy_op) + { + ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_)); + if (a == channel_operation::immediate_op) + w.immediate(handler, handler.handler_, 0); + else + w.post(handler, handler.handler_); + ASIO_HANDLER_INVOCATION_END; + } + } + +private: + Handler handler_; + channel_operation::handler_work<Handler, IoExecutor> work_; +}; + +} // namespace detail +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_OP_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/channel_service.hpp b/3rdparty/asio/include/asio/experimental/detail/channel_service.hpp new file mode 100644 index 00000000000..12324414613 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/detail/channel_service.hpp @@ -0,0 +1,677 @@ +// +// experimental/detail/channel_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SERVICE_HPP +#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/associated_cancellation_slot.hpp" +#include "asio/cancellation_type.hpp" +#include "asio/detail/mutex.hpp" +#include "asio/detail/op_queue.hpp" +#include "asio/execution_context.hpp" +#include "asio/experimental/detail/channel_message.hpp" +#include "asio/experimental/detail/channel_receive_op.hpp" +#include "asio/experimental/detail/channel_send_op.hpp" +#include "asio/experimental/detail/has_signature.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename Mutex> +class channel_service + : public asio::detail::execution_context_service_base< + channel_service<Mutex>> +{ +public: + // Possible states for a channel end. + enum state + { + buffer = 0, + waiter = 1, + block = 2, + closed = 3 + }; + + // The base implementation type of all channels. + struct base_implementation_type + { + // Default constructor. + base_implementation_type() + : receive_state_(block), + send_state_(block), + max_buffer_size_(0), + next_(0), + prev_(0) + { + } + + // The current state of the channel. + state receive_state_ : 16; + state send_state_ : 16; + + // The maximum number of elements that may be buffered in the channel. + std::size_t max_buffer_size_; + + // The operations that are waiting on the channel. + asio::detail::op_queue<channel_operation> waiters_; + + // Pointers to adjacent channel implementations in linked list. + base_implementation_type* next_; + base_implementation_type* prev_; + + // The mutex type to protect the internal implementation. + mutable Mutex mutex_; + }; + + // The implementation for a specific value type. + template <typename Traits, typename... Signatures> + struct implementation_type; + + // Constructor. + channel_service(asio::execution_context& ctx); + + // Destroy all user-defined handler objects owned by the service. + void shutdown(); + + // Construct a new channel implementation. + void construct(base_implementation_type& impl, std::size_t max_buffer_size); + + // Destroy a channel implementation. + template <typename Traits, typename... Signatures> + void destroy(implementation_type<Traits, Signatures...>& impl); + + // Move-construct a new channel implementation. + template <typename Traits, typename... Signatures> + void move_construct(implementation_type<Traits, Signatures...>& impl, + implementation_type<Traits, Signatures...>& other_impl); + + // Move-assign from another channel implementation. + template <typename Traits, typename... Signatures> + void move_assign(implementation_type<Traits, Signatures...>& impl, + channel_service& other_service, + implementation_type<Traits, Signatures...>& other_impl); + + // Get the capacity of the channel. + std::size_t capacity( + const base_implementation_type& impl) const noexcept; + + // Determine whether the channel is open. + bool is_open(const base_implementation_type& impl) const noexcept; + + // Reset the channel to its initial state. + template <typename Traits, typename... Signatures> + void reset(implementation_type<Traits, Signatures...>& impl); + + // Close the channel. + template <typename Traits, typename... Signatures> + void close(implementation_type<Traits, Signatures...>& impl); + + // Cancel all operations associated with the channel. + template <typename Traits, typename... Signatures> + void cancel(implementation_type<Traits, Signatures...>& impl); + + // Cancel the operation associated with the channel that has the given key. + template <typename Traits, typename... Signatures> + void cancel_by_key(implementation_type<Traits, Signatures...>& impl, + void* cancellation_key); + + // Determine whether a value can be read from the channel without blocking. + bool ready(const base_implementation_type& impl) const noexcept; + + // Synchronously send a new value into the channel. + template <typename Message, typename Traits, + typename... Signatures, typename... Args> + bool try_send(implementation_type<Traits, Signatures...>& impl, + bool via_dispatch, Args&&... args); + + // Synchronously send a number of new values into the channel. + template <typename Message, typename Traits, + typename... Signatures, typename... Args> + std::size_t try_send_n(implementation_type<Traits, Signatures...>& impl, + std::size_t count, bool via_dispatch, Args&&... args); + + // Asynchronously send a new value into the channel. + template <typename Traits, typename... Signatures, + typename Handler, typename IoExecutor> + void async_send(implementation_type<Traits, Signatures...>& impl, + typename implementation_type<Traits, + Signatures...>::payload_type&& payload, + Handler& handler, const IoExecutor& io_ex) + { + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef channel_send_op< + typename implementation_type<Traits, Signatures...>::payload_type, + Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(static_cast<typename implementation_type< + Traits, Signatures...>::payload_type&&>(payload), handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<op_cancellation<Traits, Signatures...>>( + this, &impl); + } + + ASIO_HANDLER_CREATION((this->context(), *p.p, + "channel", &impl, 0, "async_send")); + + start_send_op(impl, p.p); + p.v = p.p = 0; + } + + // Synchronously receive a value from the channel. + template <typename Traits, typename... Signatures, typename Handler> + bool try_receive(implementation_type<Traits, Signatures...>& impl, + Handler&& handler); + + // Asynchronously receive a value from the channel. + template <typename Traits, typename... Signatures, + typename Handler, typename IoExecutor> + void async_receive(implementation_type<Traits, Signatures...>& impl, + Handler& handler, const IoExecutor& io_ex) + { + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // Allocate and construct an operation to wrap the handler. + typedef channel_receive_op< + typename implementation_type<Traits, Signatures...>::payload_type, + Handler, IoExecutor> op; + typename op::ptr p = { asio::detail::addressof(handler), + op::ptr::allocate(handler), 0 }; + p.p = new (p.v) op(handler, io_ex); + + // Optionally register for per-operation cancellation. + if (slot.is_connected()) + { + p.p->cancellation_key_ = + &slot.template emplace<op_cancellation<Traits, Signatures...>>( + this, &impl); + } + + ASIO_HANDLER_CREATION((this->context(), *p.p, + "channel", &impl, 0, "async_receive")); + + start_receive_op(impl, p.p); + p.v = p.p = 0; + } + +private: + // Helper function object to handle a closed notification. + template <typename Payload, typename Signature> + struct post_receive + { + explicit post_receive(channel_receive<Payload>* op) + : op_(op) + { + } + + template <typename... Args> + void operator()(Args&&... args) + { + op_->post( + channel_message<Signature>(0, + static_cast<Args&&>(args)...)); + } + + channel_receive<Payload>* op_; + }; + + // Destroy a base channel implementation. + void base_destroy(base_implementation_type& impl); + + // Helper function to start an asynchronous put operation. + template <typename Traits, typename... Signatures> + void start_send_op(implementation_type<Traits, Signatures...>& impl, + channel_send<typename implementation_type< + Traits, Signatures...>::payload_type>* send_op); + + // Helper function to start an asynchronous get operation. + template <typename Traits, typename... Signatures> + void start_receive_op(implementation_type<Traits, Signatures...>& impl, + channel_receive<typename implementation_type< + Traits, Signatures...>::payload_type>* receive_op); + + // Helper class used to implement per-operation cancellation. + template <typename Traits, typename... Signatures> + class op_cancellation + { + public: + op_cancellation(channel_service* s, + implementation_type<Traits, Signatures...>* impl) + : service_(s), + impl_(impl) + { + } + + void operator()(cancellation_type_t type) + { + if (!!(type & + (cancellation_type::terminal + | cancellation_type::partial + | cancellation_type::total))) + { + service_->cancel_by_key(*impl_, this); + } + } + + private: + channel_service* service_; + implementation_type<Traits, Signatures...>* impl_; + }; + + // Mutex to protect access to the linked list of implementations. + asio::detail::mutex mutex_; + + // The head of a linked list of all implementations. + base_implementation_type* impl_list_; +}; + +// The implementation for a specific value type. +template <typename Mutex> +template <typename Traits, typename... Signatures> +struct channel_service<Mutex>::implementation_type : base_implementation_type +{ + // The traits type associated with the channel. + typedef typename Traits::template rebind<Signatures...>::other traits_type; + + // Type of an element stored in the buffer. + typedef conditional_t< + has_signature< + typename traits_type::receive_cancelled_signature, + Signatures... + >::value, + conditional_t< + has_signature< + typename traits_type::receive_closed_signature, + Signatures... + >::value, + channel_payload<Signatures...>, + channel_payload< + Signatures..., + typename traits_type::receive_closed_signature + > + >, + conditional_t< + has_signature< + typename traits_type::receive_closed_signature, + Signatures..., + typename traits_type::receive_cancelled_signature + >::value, + channel_payload< + Signatures..., + typename traits_type::receive_cancelled_signature + >, + channel_payload< + Signatures..., + typename traits_type::receive_cancelled_signature, + typename traits_type::receive_closed_signature + > + > + > payload_type; + + // Move from another buffer. + void buffer_move_from(implementation_type& other) + { + buffer_ = static_cast< + typename traits_type::template container<payload_type>::type&&>( + other.buffer_); + other.buffer_clear(); + } + + // Get number of buffered elements. + std::size_t buffer_size() const + { + return buffer_.size(); + } + + // Push a new value to the back of the buffer. + void buffer_push(payload_type payload) + { + buffer_.push_back(static_cast<payload_type&&>(payload)); + } + + // Push new values to the back of the buffer. + std::size_t buffer_push_n(std::size_t count, payload_type payload) + { + std::size_t i = 0; + for (; i < count && buffer_.size() < this->max_buffer_size_; ++i) + buffer_.push_back(payload); + return i; + } + + // Get the element at the front of the buffer. + payload_type buffer_front() + { + return static_cast<payload_type&&>(buffer_.front()); + } + + // Pop a value from the front of the buffer. + void buffer_pop() + { + buffer_.pop_front(); + } + + // Clear all buffered values. + void buffer_clear() + { + buffer_.clear(); + } + +private: + // Buffered values. + typename traits_type::template container<payload_type>::type buffer_; +}; + +// The implementation for a void value type. +template <typename Mutex> +template <typename Traits, typename R> +struct channel_service<Mutex>::implementation_type<Traits, R()> + : channel_service::base_implementation_type +{ + // The traits type associated with the channel. + typedef typename Traits::template rebind<R()>::other traits_type; + + // Type of an element stored in the buffer. + typedef conditional_t< + has_signature< + typename traits_type::receive_cancelled_signature, + R() + >::value, + conditional_t< + has_signature< + typename traits_type::receive_closed_signature, + R() + >::value, + channel_payload<R()>, + channel_payload< + R(), + typename traits_type::receive_closed_signature + > + >, + conditional_t< + has_signature< + typename traits_type::receive_closed_signature, + R(), + typename traits_type::receive_cancelled_signature + >::value, + channel_payload< + R(), + typename traits_type::receive_cancelled_signature + >, + channel_payload< + R(), + typename traits_type::receive_cancelled_signature, + typename traits_type::receive_closed_signature + > + > + > payload_type; + + // Construct with empty buffer. + implementation_type() + : buffer_(0) + { + } + + // Move from another buffer. + void buffer_move_from(implementation_type& other) + { + buffer_ = other.buffer_; + other.buffer_ = 0; + } + + // Get number of buffered elements. + std::size_t buffer_size() const + { + return buffer_; + } + + // Push a new value to the back of the buffer. + void buffer_push(payload_type) + { + ++buffer_; + } + + // Push new values to the back of the buffer. + std::size_t buffer_push_n(std::size_t count, payload_type) + { + std::size_t available = this->max_buffer_size_ - buffer_; + count = (count < available) ? count : available; + buffer_ += count; + return count; + } + + // Get the element at the front of the buffer. + payload_type buffer_front() + { + return payload_type(channel_message<R()>(0)); + } + + // Pop a value from the front of the buffer. + void buffer_pop() + { + --buffer_; + } + + // Clear all values from the buffer. + void buffer_clear() + { + buffer_ = 0; + } + +private: + // Number of buffered "values". + std::size_t buffer_; +}; + +// The implementation for an error_code signature. +template <typename Mutex> +template <typename Traits, typename R> +struct channel_service<Mutex>::implementation_type< + Traits, R(asio::error_code)> + : channel_service::base_implementation_type +{ + // The traits type associated with the channel. + typedef typename Traits::template rebind<R(asio::error_code)>::other + traits_type; + + // Type of an element stored in the buffer. + typedef conditional_t< + has_signature< + typename traits_type::receive_cancelled_signature, + R(asio::error_code) + >::value, + conditional_t< + has_signature< + typename traits_type::receive_closed_signature, + R(asio::error_code) + >::value, + channel_payload<R(asio::error_code)>, + channel_payload< + R(asio::error_code), + typename traits_type::receive_closed_signature + > + >, + conditional_t< + has_signature< + typename traits_type::receive_closed_signature, + R(asio::error_code), + typename traits_type::receive_cancelled_signature + >::value, + channel_payload< + R(asio::error_code), + typename traits_type::receive_cancelled_signature + >, + channel_payload< + R(asio::error_code), + typename traits_type::receive_cancelled_signature, + typename traits_type::receive_closed_signature + > + > + > payload_type; + + // Construct with empty buffer. + implementation_type() + : size_(0) + { + first_.count_ = 0; + } + + // Move from another buffer. + void buffer_move_from(implementation_type& other) + { + size_ = other.buffer_; + other.size_ = 0; + first_ = other.first_; + other.first.count_ = 0; + rest_ = static_cast< + typename traits_type::template container<buffered_value>::type&&>( + other.rest_); + other.buffer_clear(); + } + + // Get number of buffered elements. + std::size_t buffer_size() const + { + return size_; + } + + // Push a new value to the back of the buffer. + void buffer_push(payload_type payload) + { + buffered_value& last = rest_.empty() ? first_ : rest_.back(); + if (last.count_ == 0) + { + value_handler handler{last.value_}; + payload.receive(handler); + last.count_ = 1; + } + else + { + asio::error_code value{last.value_}; + value_handler handler{value}; + payload.receive(handler); + if (last.value_ == value) + ++last.count_; + else + rest_.push_back({value, 1}); + } + ++size_; + } + + // Push new values to the back of the buffer. + std::size_t buffer_push_n(std::size_t count, payload_type payload) + { + std::size_t available = this->max_buffer_size_ - size_; + count = (count < available) ? count : available; + if (count > 0) + { + buffered_value& last = rest_.empty() ? first_ : rest_.back(); + if (last.count_ == 0) + { + payload.receive(value_handler{last.value_}); + last.count_ = count; + } + else + { + asio::error_code value{last.value_}; + payload.receive(value_handler{value}); + if (last.value_ == value) + last.count_ += count; + else + rest_.push_back({value, count}); + } + size_ += count; + } + return count; + } + + // Get the element at the front of the buffer. + payload_type buffer_front() + { + return payload_type({0, first_.value_}); + } + + // Pop a value from the front of the buffer. + void buffer_pop() + { + --size_; + if (--first_.count_ == 0 && !rest_.empty()) + { + first_ = rest_.front(); + rest_.pop_front(); + } + } + + // Clear all values from the buffer. + void buffer_clear() + { + size_ = 0; + first_.count_ == 0; + rest_.clear(); + } + +private: + struct buffered_value + { + asio::error_code value_; + std::size_t count_; + }; + + struct value_handler + { + asio::error_code& target_; + + template <typename... Args> + void operator()(const asio::error_code& value, Args&&...) + { + target_ = value; + } + }; + + buffered_value& last_value() + { + return rest_.empty() ? first_ : rest_.back(); + } + + // Total number of buffered values. + std::size_t size_; + + // The first buffered value is maintained as a separate data member to avoid + // allocating space in the container in the common case. + buffered_value first_; + + // The rest of the buffered values. + typename traits_type::template container<buffered_value>::type rest_; +}; + +} // namespace detail +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/experimental/detail/impl/channel_service.hpp" + +#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SERVICE_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/completion_handler_erasure.hpp b/3rdparty/asio/include/asio/experimental/detail/completion_handler_erasure.hpp deleted file mode 100644 index aca02496957..00000000000 --- a/3rdparty/asio/include/asio/experimental/detail/completion_handler_erasure.hpp +++ /dev/null @@ -1,158 +0,0 @@ -// -// experimental/detail/completion_handler_erasure.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2021 Klemens D. Morgenstern -// (klemens dot morgenstern at gmx dot net) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXPERIMENTAL_DETAIL_COMPLETION_HANDLER_ERASURE_HPP -#define ASIO_EXPERIMENTAL_DETAIL_COMPLETION_HANDLER_ERASURE_HPP - -#include "asio/associated_allocator.hpp" -#include "asio/dispatch.hpp" - -namespace asio { - -class any_io_executor; - -namespace experimental { -namespace detail { - -template<typename Signature, typename Executor> -struct completion_handler_erasure_base; - -template<typename Func, typename Signature, typename Executor> -struct completion_handler_erasure_impl; - -template<typename Return, typename ... Args, typename Executor> -struct completion_handler_erasure_base<Return(Args...), Executor> -{ - Executor executor; - - completion_handler_erasure_base(Executor&& executor) - : executor(std::move(executor)) - { - } - - virtual Return call(Args ...args) = 0; - virtual ~completion_handler_erasure_base() = default; -}; - -template<typename Func, typename Return, typename ... Args, typename Executor> -struct completion_handler_erasure_impl<Func, Return(Args...), Executor> final - : completion_handler_erasure_base<Return(Args...), Executor> -{ - completion_handler_erasure_impl(Executor&& exec, Func&& func) - : completion_handler_erasure_base<Return(Args...), Executor>( - std::move(exec)), func(std::move(func)) - { - } - - virtual Return call(Args ...args) override - { - std::move(func)(std::move(args)...); - } - - Func func; -}; - -template<typename Signature, typename Executor = any_io_executor> -struct completion_handler_erasure; - -template<typename Return, typename ... Args, typename Executor> -struct completion_handler_erasure<Return(Args...), Executor> -{ - struct deleter_t - { - using allocator_base = typename associated_allocator<Executor>::type; - using allocator_type = - typename std::allocator_traits<allocator_base>::template rebind_alloc< - completion_handler_erasure_base<Return(Args...), Executor>>; - - allocator_type allocator; - std::size_t size; - - template<typename Func> - static std::unique_ptr< - completion_handler_erasure_base<Return(Args...), Executor>, deleter_t> - make(Executor exec, Func&& func) - { - using type = completion_handler_erasure_impl< - std::remove_reference_t<Func>, Return(Args...), Executor>; - using alloc_type = typename std::allocator_traits< - allocator_base>::template rebind_alloc<type>; - auto alloc = alloc_type(get_associated_allocator(exec)); - auto size = sizeof(type); - auto p = std::allocator_traits<alloc_type>::allocate(alloc, size); - auto res = std::unique_ptr<type, deleter_t>( - p, deleter_t{allocator_type(alloc), size}); - std::allocator_traits<alloc_type>::construct(alloc, - p, std::move(exec), std::forward<Func>(func)); - return res; - } - - void operator()( - completion_handler_erasure_base<Return(Args...), Executor> * p) - { - std::allocator_traits<allocator_type>::destroy(allocator, p); - std::allocator_traits<allocator_type>::deallocate(allocator, p, size); - } - }; - - completion_handler_erasure(const completion_handler_erasure&) = delete; - completion_handler_erasure(completion_handler_erasure&&) = default; - completion_handler_erasure& operator=( - const completion_handler_erasure&) = delete; - completion_handler_erasure& operator=( - completion_handler_erasure&&) = default; - - constexpr completion_handler_erasure() = default; - - constexpr completion_handler_erasure(nullptr_t) - : completion_handler_erasure() - { - } - - template<typename Func> - completion_handler_erasure(Executor exec, Func&& func) - : impl_(deleter_t::make(std::move(exec), std::forward<Func>(func))) - { - } - - ~completion_handler_erasure() - { - if (auto f = std::exchange(impl_, nullptr); f != nullptr) - { - asio::dispatch(f->executor, - [f = std::move(f)]() mutable - { - std::move(f)->call(Args{}...); - }); - } - } - - Return operator()(Args ... args) - { - if (auto f = std::exchange(impl_, nullptr); f != nullptr) - f->call(std::move(args)...); - } - - constexpr bool operator==(nullptr_t) const noexcept {return impl_ == nullptr;} - constexpr bool operator!=(nullptr_t) const noexcept {return impl_ != nullptr;} - constexpr bool operator!() const noexcept {return impl_ == nullptr;} - -private: - std::unique_ptr< - completion_handler_erasure_base<Return(Args...), Executor>, deleter_t> - impl_; -}; - -} // namespace detail -} // namespace experimental -} // namespace asio - -#endif // ASIO_EXPERIMENTAL_DETAIL_COMPLETION_HANDLER_ERASURE_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/coro_completion_handler.hpp b/3rdparty/asio/include/asio/experimental/detail/coro_completion_handler.hpp new file mode 100644 index 00000000000..52809134cb0 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/detail/coro_completion_handler.hpp @@ -0,0 +1,169 @@ +// +// experimental/detail/coro_completion_handler.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_DETAIL_CORO_COMPLETION_HANDLER_HPP +#define ASIO_EXPERIMENTAL_DETAIL_CORO_COMPLETION_HANDLER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/deferred.hpp" +#include "asio/experimental/coro.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename Promise, typename... Args> +struct coro_completion_handler +{ + coro_completion_handler(coroutine_handle<Promise> h, + std::optional<std::tuple<Args...>>& result) + : self(h), + result(result) + { + } + + coro_completion_handler(coro_completion_handler&&) = default; + + coroutine_handle<Promise> self; + + std::optional<std::tuple<Args...>>& result; + + using promise_type = Promise; + + void operator()(Args... args) + { + result.emplace(std::move(args)...); + self.resume(); + } + + using allocator_type = typename promise_type::allocator_type; + allocator_type get_allocator() const noexcept + { + return self.promise().get_allocator(); + } + + using executor_type = typename promise_type::executor_type; + executor_type get_executor() const noexcept + { + return self.promise().get_executor(); + } + + using cancellation_slot_type = typename promise_type::cancellation_slot_type; + cancellation_slot_type get_cancellation_slot() const noexcept + { + return self.promise().get_cancellation_slot(); + } +}; + +template <typename Signature> +struct coro_completion_handler_type; + +template <typename... Args> +struct coro_completion_handler_type<void(Args...)> +{ + using type = std::tuple<Args...>; + + template <typename Promise> + using completion_handler = coro_completion_handler<Promise, Args...>; +}; + +template <typename Signature> +using coro_completion_handler_type_t = + typename coro_completion_handler_type<Signature>::type; + +inline void coro_interpret_result(std::tuple<>&&) +{ +} + +template <typename... Args> +inline auto coro_interpret_result(std::tuple<Args...>&& args) +{ + return std::move(args); +} + +template <typename... Args> +auto coro_interpret_result(std::tuple<std::exception_ptr, Args...>&& args) +{ + if (std::get<0>(args)) + std::rethrow_exception(std::get<0>(args)); + + return std::apply( + [](auto, auto&&... rest) + { + return std::make_tuple(std::move(rest)...); + }, std::move(args)); +} + +template <typename... Args> +auto coro_interpret_result( + std::tuple<asio::error_code, Args...>&& args) +{ + if (std::get<0>(args)) + asio::detail::throw_exception( + asio::system_error(std::get<0>(args))); + + return std::apply( + [](auto, auto&&... rest) + { + return std::make_tuple(std::move(rest)...); + }, std::move(args)); +} + +template <typename Arg> +inline auto coro_interpret_result(std::tuple<Arg>&& args) +{ + return std::get<0>(std::move(args)); +} + +template <typename Arg> +auto coro_interpret_result(std::tuple<std::exception_ptr, Arg>&& args) +{ + if (std::get<0>(args)) + std::rethrow_exception(std::get<0>(args)); + return std::get<1>(std::move(args)); +} + +inline auto coro_interpret_result( + std::tuple<asio::error_code>&& args) +{ + if (std::get<0>(args)) + asio::detail::throw_exception( + asio::system_error(std::get<0>(args))); +} + +inline auto coro_interpret_result(std::tuple<std::exception_ptr>&& args) +{ + if (std::get<0>(args)) + std::rethrow_exception(std::get<0>(args)); +} + +template <typename Arg> +auto coro_interpret_result(std::tuple<asio::error_code, Arg>&& args) +{ + if (std::get<0>(args)) + asio::detail::throw_exception( + asio::system_error(std::get<0>(args))); + return std::get<1>(std::move(args)); +} + +} // namespace detail +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_DETAIL_CORO_COMPLETION_HANDLER_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/coro_promise_allocator.hpp b/3rdparty/asio/include/asio/experimental/detail/coro_promise_allocator.hpp index bb78677f115..328646968f3 100644 --- a/3rdparty/asio/include/asio/experimental/detail/coro_promise_allocator.hpp +++ b/3rdparty/asio/include/asio/experimental/detail/coro_promise_allocator.hpp @@ -2,8 +2,8 @@ // experimental/detail/coro_promise_allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2021 Klemens D. Morgenstern -// (klemens dot morgenstern at gmx dot net) +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -13,101 +13,124 @@ #define ASIO_EXPERIMENTAL_DETAIL_CORO_PROMISE_ALLOCATOR_HPP #include "asio/detail/config.hpp" -#include "asio/experimental/detail/coro_traits.hpp" +#include "asio/experimental/coro_traits.hpp" namespace asio { namespace experimental { namespace detail { -template <typename Coroutine, - typename Executor = typename Coroutine::executor_type, - typename Allocator = typename std::allocator_traits< - associated_allocator_t<Executor>>:: template rebind_alloc<std::byte>, - bool Noexcept = noexcept(std::declval<Allocator>().allocate(0u))> -struct coro_promise_allocator +/// Allocate the memory and put the allocator behind the coro memory +template <typename AllocatorType> +void* allocate_coroutine(const std::size_t size, AllocatorType alloc_) { - using allocator_type = Allocator; + using alloc_type = typename std::allocator_traits<AllocatorType>::template + rebind_alloc<unsigned char>; + alloc_type alloc{alloc_}; + + const auto align_needed = size % alignof(alloc_type); + const auto align_offset = align_needed != 0 + ? alignof(alloc_type) - align_needed : 0ull; + const auto alloc_size = size + sizeof(alloc_type) + align_offset; + const auto raw = + std::allocator_traits<alloc_type>::allocate(alloc, alloc_size); + new(raw + size + align_offset) alloc_type(std::move(alloc)); + + return raw; +} + +/// Deallocate the memory and destroy the allocator in the coro memory. +template <typename AllocatorType> +void deallocate_coroutine(void* raw_, const std::size_t size) +{ + using alloc_type = typename std::allocator_traits<AllocatorType>::template + rebind_alloc<unsigned char>; - template <typename... Args> - void* operator new(const std::size_t size, Executor executor, Args&&...) - { - static_assert(std::is_nothrow_move_constructible_v<allocator_type>); - allocator_type alloc{get_associated_allocator(executor)}; - - const auto csize = size + sizeof(alloc); - const auto raw = - std::allocator_traits<allocator_type>::allocate(alloc, csize); - new (raw) allocator_type(std::move(alloc)); - return static_cast<std::byte*>(raw) + sizeof(alloc); - } + const auto raw = static_cast<unsigned char *>(raw_); - template <execution_context Context, typename... Args> - void* operator new(const std::size_t size, Context&& ctx, Args&&... args) - { - return coro_promise_allocator::operator new(size, - ctx.get_executor(), std::forward<Args>(args)...); - } + const auto align_needed = size % alignof(alloc_type); + const auto align_offset = align_needed != 0 + ? alignof(alloc_type) - align_needed : 0ull; + const auto alloc_size = size + sizeof(alloc_type) + align_offset; - void operator delete(void* raw, std::size_t size ) - { - auto * alloc_p = static_cast<allocator_type*>(raw); + auto alloc_p = reinterpret_cast<alloc_type *>(raw + size + align_offset); + auto alloc = std::move(*alloc_p); + alloc_p->~alloc_type(); + std::allocator_traits<alloc_type>::deallocate(alloc, raw, alloc_size); +} + +template <typename T> +constexpr std::size_t variadic_first(std::size_t = 0u) +{ + return std::numeric_limits<std::size_t>::max(); +} - auto alloc = std::move(*alloc_p); - alloc_p->~allocator_type(); - std::allocator_traits<allocator_type>::deallocate(alloc, - static_cast<std::byte*>(raw), size + sizeof(allocator_type)); - } -}; -template <typename Coroutine, typename Executor> -struct coro_promise_allocator<Coroutine, - Executor, std::allocator<std::byte>, false> +template <typename T, typename First, typename... Args> +constexpr std::size_t variadic_first(std::size_t pos = 0u) { + if constexpr (std::is_same_v<std::decay_t<First>, T>) + return pos; + else + return variadic_first<T, Args...>(pos+1); +} + +template <std::size_t Idx, typename First, typename... Args> + requires (Idx <= sizeof...(Args)) +constexpr decltype(auto) get_variadic(First&& first, Args&&... args) +{ + if constexpr (Idx == 0u) + return static_cast<First>(first); + else + return get_variadic<Idx-1u>(static_cast<Args>(args)...); +} -}; +template <std::size_t Idx> +constexpr decltype(auto) get_variadic(); -template <typename Coroutine, typename Executor, typename Allocator> -struct coro_promise_allocator<Coroutine, Executor, Allocator, true> +template <typename Allocator> +struct coro_promise_allocator { using allocator_type = Allocator; + allocator_type get_allocator() const {return alloc_;} template <typename... Args> - void* operator new(const std::size_t size, - Executor executor, Args&&...) noexcept + void* operator new(const std::size_t size, Args & ... args) + { + return allocate_coroutine(size, + get_variadic<variadic_first<std::allocator_arg_t, + std::decay_t<Args>...>() + 1u>(args...)); + } + + void operator delete(void* raw, const std::size_t size) { - static_assert(std::is_nothrow_move_constructible_v<allocator_type>); - allocator_type alloc{get_associated_allocator(executor)}; - - const auto csize = size + sizeof(alloc); - const auto raw = - std::allocator_traits<allocator_type>::allocate(alloc, csize); - if (raw == nullptr) - return nullptr; - new (raw) allocator_type(std::move(alloc)); - return static_cast<std::byte*>(raw) + sizeof(alloc); + deallocate_coroutine<allocator_type>(raw, size); } - template <execution_context Context, typename... Args> - void* operator new(const std::size_t size, - Context&& ctx, Args&&... args) noexcept + template <typename... Args> + coro_promise_allocator(Args&& ... args) + : alloc_( + get_variadic<variadic_first<std::allocator_arg_t, + std::decay_t<Args>...>() + 1u>(args...)) { - return coro_promise_allocator::operator new(size, - ctx.get_executor(), std::forward<Args>(args)...); } - void operator delete(void* raw, std::size_t size) noexcept +private: + allocator_type alloc_; +}; + +template <> +struct coro_promise_allocator<std::allocator<void>> +{ + using allocator_type = std::allocator<void>; + + template <typename... Args> + coro_promise_allocator(Args&&...) { - auto * alloc_p = static_cast<allocator_type*>(raw); - auto alloc = std::move(*alloc_p); - alloc_p->~allocator_type(); - const auto csize = size + sizeof(allocator_type); - std::allocator_traits<allocator_type>::deallocate(alloc, - static_cast<std::byte*>(raw) - sizeof(allocator_type), csize); } - static auto get_return_object_on_allocation_failure() noexcept -> Coroutine + allocator_type get_allocator() const { - return Coroutine{}; + return {}; } }; diff --git a/3rdparty/asio/include/asio/experimental/detail/has_signature.hpp b/3rdparty/asio/include/asio/experimental/detail/has_signature.hpp new file mode 100644 index 00000000000..ea5dac8c69b --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/detail/has_signature.hpp @@ -0,0 +1,54 @@ +// +// experimental/detail/has_signature.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_DETAIL_HAS_SIGNATURE_HPP +#define ASIO_EXPERIMENTAL_DETAIL_HAS_SIGNATURE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/type_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename S, typename... Signatures> +struct has_signature; + +template <typename S, typename... Signatures> +struct has_signature; + +template <typename S> +struct has_signature<S> : false_type +{ +}; + +template <typename S, typename... Signatures> +struct has_signature<S, S, Signatures...> : true_type +{ +}; + +template <typename S, typename Head, typename... Tail> +struct has_signature<S, Head, Tail...> : has_signature<S, Tail...> +{ +}; + +} // namespace detail +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_DETAIL_HAS_SIGNATURE_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/impl/channel_service.hpp b/3rdparty/asio/include/asio/experimental/detail/impl/channel_service.hpp new file mode 100644 index 00000000000..797c9f433c7 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/detail/impl/channel_service.hpp @@ -0,0 +1,621 @@ +// +// experimental/detail/impl/channel_service.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_DETAIL_IMPL_CHANNEL_SERVICE_HPP +#define ASIO_EXPERIMENTAL_DETAIL_IMPL_CHANNEL_SERVICE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +template <typename Mutex> +inline channel_service<Mutex>::channel_service( + asio::execution_context& ctx) + : asio::detail::execution_context_service_base<channel_service>(ctx), + mutex_(), + impl_list_(0) +{ +} + +template <typename Mutex> +inline void channel_service<Mutex>::shutdown() +{ + // Abandon all pending operations. + asio::detail::op_queue<channel_operation> ops; + asio::detail::mutex::scoped_lock lock(mutex_); + base_implementation_type* impl = impl_list_; + while (impl) + { + ops.push(impl->waiters_); + impl = impl->next_; + } +} + +template <typename Mutex> +inline void channel_service<Mutex>::construct( + channel_service<Mutex>::base_implementation_type& impl, + std::size_t max_buffer_size) +{ + impl.max_buffer_size_ = max_buffer_size; + impl.receive_state_ = block; + impl.send_state_ = max_buffer_size ? buffer : block; + + // Insert implementation into linked list of all implementations. + asio::detail::mutex::scoped_lock lock(mutex_); + impl.next_ = impl_list_; + impl.prev_ = 0; + if (impl_list_) + impl_list_->prev_ = &impl; + impl_list_ = &impl; +} + +template <typename Mutex> +template <typename Traits, typename... Signatures> +void channel_service<Mutex>::destroy( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl) +{ + cancel(impl); + base_destroy(impl); +} + +template <typename Mutex> +template <typename Traits, typename... Signatures> +void channel_service<Mutex>::move_construct( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl, + channel_service<Mutex>::implementation_type< + Traits, Signatures...>& other_impl) +{ + impl.max_buffer_size_ = other_impl.max_buffer_size_; + impl.receive_state_ = other_impl.receive_state_; + other_impl.receive_state_ = block; + impl.send_state_ = other_impl.send_state_; + other_impl.send_state_ = other_impl.max_buffer_size_ ? buffer : block; + impl.buffer_move_from(other_impl); + + // Insert implementation into linked list of all implementations. + asio::detail::mutex::scoped_lock lock(mutex_); + impl.next_ = impl_list_; + impl.prev_ = 0; + if (impl_list_) + impl_list_->prev_ = &impl; + impl_list_ = &impl; +} + +template <typename Mutex> +template <typename Traits, typename... Signatures> +void channel_service<Mutex>::move_assign( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl, + channel_service& other_service, + channel_service<Mutex>::implementation_type< + Traits, Signatures...>& other_impl) +{ + cancel(impl); + + if (this != &other_service) + { + // Remove implementation from linked list of all implementations. + asio::detail::mutex::scoped_lock lock(mutex_); + if (impl_list_ == &impl) + impl_list_ = impl.next_; + if (impl.prev_) + impl.prev_->next_ = impl.next_; + if (impl.next_) + impl.next_->prev_= impl.prev_; + impl.next_ = 0; + impl.prev_ = 0; + } + + impl.max_buffer_size_ = other_impl.max_buffer_size_; + impl.receive_state_ = other_impl.receive_state_; + other_impl.receive_state_ = block; + impl.send_state_ = other_impl.send_state_; + other_impl.send_state_ = other_impl.max_buffer_size_ ? buffer : block; + impl.buffer_move_from(other_impl); + + if (this != &other_service) + { + // Insert implementation into linked list of all implementations. + asio::detail::mutex::scoped_lock lock(other_service.mutex_); + impl.next_ = other_service.impl_list_; + impl.prev_ = 0; + if (other_service.impl_list_) + other_service.impl_list_->prev_ = &impl; + other_service.impl_list_ = &impl; + } +} + +template <typename Mutex> +inline void channel_service<Mutex>::base_destroy( + channel_service<Mutex>::base_implementation_type& impl) +{ + // Remove implementation from linked list of all implementations. + asio::detail::mutex::scoped_lock lock(mutex_); + if (impl_list_ == &impl) + impl_list_ = impl.next_; + if (impl.prev_) + impl.prev_->next_ = impl.next_; + if (impl.next_) + impl.next_->prev_= impl.prev_; + impl.next_ = 0; + impl.prev_ = 0; +} + +template <typename Mutex> +inline std::size_t channel_service<Mutex>::capacity( + const channel_service<Mutex>::base_implementation_type& impl) + const noexcept +{ + typename Mutex::scoped_lock lock(impl.mutex_); + + return impl.max_buffer_size_; +} + +template <typename Mutex> +inline bool channel_service<Mutex>::is_open( + const channel_service<Mutex>::base_implementation_type& impl) + const noexcept +{ + typename Mutex::scoped_lock lock(impl.mutex_); + + return impl.send_state_ != closed; +} + +template <typename Mutex> +template <typename Traits, typename... Signatures> +void channel_service<Mutex>::reset( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl) +{ + cancel(impl); + + typename Mutex::scoped_lock lock(impl.mutex_); + + impl.receive_state_ = block; + impl.send_state_ = impl.max_buffer_size_ ? buffer : block; + impl.buffer_clear(); +} + +template <typename Mutex> +template <typename Traits, typename... Signatures> +void channel_service<Mutex>::close( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl) +{ + typedef typename implementation_type<Traits, + Signatures...>::traits_type traits_type; + typedef typename implementation_type<Traits, + Signatures...>::payload_type payload_type; + + typename Mutex::scoped_lock lock(impl.mutex_); + + if (impl.receive_state_ == block) + { + while (channel_operation* op = impl.waiters_.front()) + { + impl.waiters_.pop(); + traits_type::invoke_receive_closed( + post_receive<payload_type, + typename traits_type::receive_closed_signature>( + static_cast<channel_receive<payload_type>*>(op))); + } + } + + impl.send_state_ = closed; + if (impl.receive_state_ != buffer) + impl.receive_state_ = closed; +} + +template <typename Mutex> +template <typename Traits, typename... Signatures> +void channel_service<Mutex>::cancel( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl) +{ + typedef typename implementation_type<Traits, + Signatures...>::traits_type traits_type; + typedef typename implementation_type<Traits, + Signatures...>::payload_type payload_type; + + typename Mutex::scoped_lock lock(impl.mutex_); + + while (channel_operation* op = impl.waiters_.front()) + { + if (impl.send_state_ == block) + { + impl.waiters_.pop(); + static_cast<channel_send<payload_type>*>(op)->cancel(); + } + else + { + impl.waiters_.pop(); + traits_type::invoke_receive_cancelled( + post_receive<payload_type, + typename traits_type::receive_cancelled_signature>( + static_cast<channel_receive<payload_type>*>(op))); + } + } + + if (impl.receive_state_ == waiter) + impl.receive_state_ = block; + if (impl.send_state_ == waiter) + impl.send_state_ = impl.max_buffer_size_ ? buffer : block; +} + +template <typename Mutex> +template <typename Traits, typename... Signatures> +void channel_service<Mutex>::cancel_by_key( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl, + void* cancellation_key) +{ + typedef typename implementation_type<Traits, + Signatures...>::traits_type traits_type; + typedef typename implementation_type<Traits, + Signatures...>::payload_type payload_type; + + typename Mutex::scoped_lock lock(impl.mutex_); + + asio::detail::op_queue<channel_operation> other_ops; + while (channel_operation* op = impl.waiters_.front()) + { + if (op->cancellation_key_ == cancellation_key) + { + if (impl.send_state_ == block) + { + impl.waiters_.pop(); + static_cast<channel_send<payload_type>*>(op)->cancel(); + } + else + { + impl.waiters_.pop(); + traits_type::invoke_receive_cancelled( + post_receive<payload_type, + typename traits_type::receive_cancelled_signature>( + static_cast<channel_receive<payload_type>*>(op))); + } + } + else + { + impl.waiters_.pop(); + other_ops.push(op); + } + } + impl.waiters_.push(other_ops); + + if (impl.waiters_.empty()) + { + if (impl.receive_state_ == waiter) + impl.receive_state_ = block; + if (impl.send_state_ == waiter) + impl.send_state_ = impl.max_buffer_size_ ? buffer : block; + } +} + +template <typename Mutex> +inline bool channel_service<Mutex>::ready( + const channel_service<Mutex>::base_implementation_type& impl) + const noexcept +{ + typename Mutex::scoped_lock lock(impl.mutex_); + + return impl.receive_state_ != block; +} + +template <typename Mutex> +template <typename Message, typename Traits, + typename... Signatures, typename... Args> +bool channel_service<Mutex>::try_send( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl, + bool via_dispatch, Args&&... args) +{ + typedef typename implementation_type<Traits, + Signatures...>::payload_type payload_type; + + typename Mutex::scoped_lock lock(impl.mutex_); + + switch (impl.send_state_) + { + case block: + { + return false; + } + case buffer: + { + impl.buffer_push(Message(0, static_cast<Args&&>(args)...)); + impl.receive_state_ = buffer; + if (impl.buffer_size() == impl.max_buffer_size_) + impl.send_state_ = block; + return true; + } + case waiter: + { + payload_type payload(Message(0, static_cast<Args&&>(args)...)); + channel_receive<payload_type>* receive_op = + static_cast<channel_receive<payload_type>*>(impl.waiters_.front()); + impl.waiters_.pop(); + if (impl.waiters_.empty()) + impl.send_state_ = impl.max_buffer_size_ ? buffer : block; + lock.unlock(); + if (via_dispatch) + receive_op->dispatch(static_cast<payload_type&&>(payload)); + else + receive_op->post(static_cast<payload_type&&>(payload)); + return true; + } + case closed: + default: + { + return false; + } + } +} + +template <typename Mutex> +template <typename Message, typename Traits, + typename... Signatures, typename... Args> +std::size_t channel_service<Mutex>::try_send_n( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl, + std::size_t count, bool via_dispatch, Args&&... args) +{ + typedef typename implementation_type<Traits, + Signatures...>::payload_type payload_type; + + typename Mutex::scoped_lock lock(impl.mutex_); + + if (count == 0) + return 0; + + switch (impl.send_state_) + { + case block: + return 0; + case buffer: + case waiter: + break; + case closed: + default: + return 0; + } + + payload_type payload(Message(0, static_cast<Args&&>(args)...)); + + for (std::size_t i = 0; i < count; ++i) + { + switch (impl.send_state_) + { + case block: + { + return i; + } + case buffer: + { + i += impl.buffer_push_n(count - i, + static_cast<payload_type&&>(payload)); + impl.receive_state_ = buffer; + if (impl.buffer_size() == impl.max_buffer_size_) + impl.send_state_ = block; + return i; + } + case waiter: + { + channel_receive<payload_type>* receive_op = + static_cast<channel_receive<payload_type>*>(impl.waiters_.front()); + impl.waiters_.pop(); + if (impl.waiters_.empty()) + impl.send_state_ = impl.max_buffer_size_ ? buffer : block; + lock.unlock(); + if (via_dispatch) + receive_op->dispatch(payload); + else + receive_op->post(payload); + break; + } + case closed: + default: + { + return i; + } + } + } + + return count; +} + +template <typename Mutex> +template <typename Traits, typename... Signatures> +void channel_service<Mutex>::start_send_op( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl, + channel_send<typename implementation_type< + Traits, Signatures...>::payload_type>* send_op) +{ + typedef typename implementation_type<Traits, + Signatures...>::payload_type payload_type; + + typename Mutex::scoped_lock lock(impl.mutex_); + + switch (impl.send_state_) + { + case block: + { + impl.waiters_.push(send_op); + if (impl.receive_state_ == block) + impl.receive_state_ = waiter; + return; + } + case buffer: + { + impl.buffer_push(send_op->get_payload()); + impl.receive_state_ = buffer; + if (impl.buffer_size() == impl.max_buffer_size_) + impl.send_state_ = block; + send_op->immediate(); + break; + } + case waiter: + { + channel_receive<payload_type>* receive_op = + static_cast<channel_receive<payload_type>*>(impl.waiters_.front()); + impl.waiters_.pop(); + if (impl.waiters_.empty()) + impl.send_state_ = impl.max_buffer_size_ ? buffer : block; + receive_op->post(send_op->get_payload()); + send_op->immediate(); + break; + } + case closed: + default: + { + send_op->close(); + break; + } + } +} + +template <typename Mutex> +template <typename Traits, typename... Signatures, typename Handler> +bool channel_service<Mutex>::try_receive( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl, + Handler&& handler) +{ + typedef typename implementation_type<Traits, + Signatures...>::payload_type payload_type; + + typename Mutex::scoped_lock lock(impl.mutex_); + + switch (impl.receive_state_) + { + case block: + { + return false; + } + case buffer: + { + payload_type payload(impl.buffer_front()); + if (channel_send<payload_type>* send_op = + static_cast<channel_send<payload_type>*>(impl.waiters_.front())) + { + impl.buffer_pop(); + impl.buffer_push(send_op->get_payload()); + impl.waiters_.pop(); + send_op->post(); + } + else + { + impl.buffer_pop(); + if (impl.buffer_size() == 0) + impl.receive_state_ = (impl.send_state_ == closed) ? closed : block; + impl.send_state_ = (impl.send_state_ == closed) ? closed : buffer; + } + lock.unlock(); + asio::detail::non_const_lvalue<Handler> handler2(handler); + channel_handler<payload_type, decay_t<Handler>>( + static_cast<payload_type&&>(payload), handler2.value)(); + return true; + } + case waiter: + { + channel_send<payload_type>* send_op = + static_cast<channel_send<payload_type>*>(impl.waiters_.front()); + payload_type payload = send_op->get_payload(); + impl.waiters_.pop(); + if (impl.waiters_.front() == 0) + impl.receive_state_ = (impl.send_state_ == closed) ? closed : block; + send_op->post(); + lock.unlock(); + asio::detail::non_const_lvalue<Handler> handler2(handler); + channel_handler<payload_type, decay_t<Handler>>( + static_cast<payload_type&&>(payload), handler2.value)(); + return true; + } + case closed: + default: + { + return false; + } + } +} + +template <typename Mutex> +template <typename Traits, typename... Signatures> +void channel_service<Mutex>::start_receive_op( + channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl, + channel_receive<typename implementation_type< + Traits, Signatures...>::payload_type>* receive_op) +{ + typedef typename implementation_type<Traits, + Signatures...>::traits_type traits_type; + typedef typename implementation_type<Traits, + Signatures...>::payload_type payload_type; + + typename Mutex::scoped_lock lock(impl.mutex_); + + switch (impl.receive_state_) + { + case block: + { + impl.waiters_.push(receive_op); + if (impl.send_state_ != closed) + impl.send_state_ = waiter; + return; + } + case buffer: + { + payload_type payload( + static_cast<payload_type&&>(impl.buffer_front())); + if (channel_send<payload_type>* send_op = + static_cast<channel_send<payload_type>*>(impl.waiters_.front())) + { + impl.buffer_pop(); + impl.buffer_push(send_op->get_payload()); + impl.waiters_.pop(); + send_op->post(); + } + else + { + impl.buffer_pop(); + if (impl.buffer_size() == 0) + impl.receive_state_ = (impl.send_state_ == closed) ? closed : block; + impl.send_state_ = (impl.send_state_ == closed) ? closed : buffer; + } + receive_op->immediate(static_cast<payload_type&&>(payload)); + break; + } + case waiter: + { + channel_send<payload_type>* send_op = + static_cast<channel_send<payload_type>*>(impl.waiters_.front()); + payload_type payload = send_op->get_payload(); + impl.waiters_.pop(); + if (impl.waiters_.front() == 0) + impl.receive_state_ = (impl.send_state_ == closed) ? closed : block; + send_op->post(); + receive_op->immediate(static_cast<payload_type&&>(payload)); + break; + } + case closed: + default: + { + traits_type::invoke_receive_closed( + post_receive<payload_type, + typename traits_type::receive_closed_signature>(receive_op)); + break; + } + } +} + +} // namespace detail +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_DETAIL_IMPL_CHANNEL_SERVICE_HPP diff --git a/3rdparty/asio/include/asio/experimental/detail/partial_promise.hpp b/3rdparty/asio/include/asio/experimental/detail/partial_promise.hpp index 55aa6d0c2b6..8495af2f0ba 100644 --- a/3rdparty/asio/include/asio/experimental/detail/partial_promise.hpp +++ b/3rdparty/asio/include/asio/experimental/detail/partial_promise.hpp @@ -2,8 +2,8 @@ // experimental/detail/partial_promise.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2021 Klemens D. Morgenstern -// (klemens dot morgenstern at gmx dot net) +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -13,9 +13,9 @@ #define ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP #include "asio/detail/config.hpp" -#include "asio/experimental/detail/coro_traits.hpp" +#include "asio/append.hpp" #include "asio/awaitable.hpp" -#include <iostream> +#include "asio/experimental/coro_traits.hpp" #if defined(ASIO_HAS_STD_COROUTINE) # include <coroutine> @@ -45,7 +45,33 @@ using std::experimental::noop_coroutine; #endif // defined(ASIO_HAS_STD_COROUTINE) -struct partial_promise +struct partial_coro +{ + coroutine_handle<void> handle{nullptr}; +}; + +template <typename Allocator> +struct partial_promise_base +{ + template <typename Executor, typename Token, typename... Args> + void* operator new(const std::size_t size, Executor&, Token& tk, Args&...) + { + return allocate_coroutine<Allocator>(size, get_associated_allocator(tk)); + } + + void operator delete(void* raw, const std::size_t size) + { + deallocate_coroutine<Allocator>(raw, size); + } +}; + +template <> +struct partial_promise_base<std::allocator<void>> +{ +}; + +template <typename Allocator> +struct partial_promise : partial_promise_base<Allocator> { auto initial_suspend() noexcept { @@ -62,7 +88,7 @@ struct partial_promise auto await_suspend(asio::detail::coroutine_handle<>) noexcept { - p->get_return_object().destroy(); + p->get_return_object().handle.destroy(); } constexpr void await_resume() noexcept {} @@ -73,9 +99,9 @@ struct partial_promise void return_void() {} - coroutine_handle<partial_promise> get_return_object() + partial_coro get_return_object() { - return coroutine_handle<partial_promise>::from_promise(*this); + return partial_coro{coroutine_handle<partial_promise>::from_promise(*this)}; } void unhandled_exception() @@ -84,7 +110,9 @@ struct partial_promise } }; -} // namespace detail + + +}; // namespace detail } // namespace experimental } // namespace asio @@ -92,12 +120,14 @@ struct partial_promise namespace std { -template<typename ... Args> +template <typename Executor, typename Completion, typename... Args> struct coroutine_traits< - coroutine_handle<asio::experimental::detail::partial_promise>, - Args...> + asio::experimental::detail::partial_coro, + Executor, Completion, Args...> { - using promise_type = asio::experimental::detail::partial_promise; + using promise_type = + asio::experimental::detail::partial_promise< + asio::associated_allocator_t<Completion>>; }; } // namespace std @@ -106,12 +136,14 @@ struct coroutine_traits< namespace std { namespace experimental { -template<typename... Args> +template <typename Executor, typename Completion, typename... Args> struct coroutine_traits< - coroutine_handle<asio::experimental::detail::partial_promise>, - Args...> + asio::experimental::detail::partial_coro, + Executor, Completion, Args...> { - using promise_type = asio::experimental::detail::partial_promise; + using promise_type = + asio::experimental::detail::partial_promise< + asio::associated_allocator_t<Completion>>; }; }} // namespace std::experimental @@ -122,51 +154,39 @@ namespace asio { namespace experimental { namespace detail { -template<typename CompletionToken> -auto post_coroutine(CompletionToken token) noexcept - -> coroutine_handle<partial_promise> -{ - post(std::move(token)); - co_return; -} - -template<execution::executor Executor, typename CompletionToken> -auto post_coroutine(Executor exec, CompletionToken token) noexcept - -> coroutine_handle<partial_promise> -{ - post(exec, std::move(token)); - co_return; -} - -template<execution_context Context, typename CompletionToken> -auto post_coroutine(Context &ctx, CompletionToken token) noexcept - -> coroutine_handle<partial_promise> +template <execution::executor Executor, + typename CompletionToken, typename... Args> +partial_coro post_coroutine(Executor exec, + CompletionToken token, Args&&... args) noexcept { - post(ctx, std::move(token)); + post(exec, asio::append(std::move(token), std::move(args)...)); co_return; } -template<typename CompletionToken> -auto dispatch_coroutine(CompletionToken token) noexcept - -> coroutine_handle<partial_promise> +template <detail::execution_context Context, + typename CompletionToken, typename... Args> +partial_coro post_coroutine(Context& ctx, + CompletionToken token, Args&&... args) noexcept { - dispatch(std::move(token)); + post(ctx, asio::append(std::move(token), std::move(args)...)); co_return; } -template<execution::executor Executor, typename CompletionToken> -auto dispatch_coroutine(Executor exec, CompletionToken token) noexcept - -> coroutine_handle<partial_promise> +template <execution::executor Executor, + typename CompletionToken, typename... Args> +partial_coro dispatch_coroutine(Executor exec, + CompletionToken token, Args&&... args) noexcept { - dispatch(exec, std::move(token)); + dispatch(exec, asio::append(std::move(token), std::move(args)...)); co_return; } -template<execution_context Context, typename CompletionToken> -auto dispatch_coroutine(Context &ctx, CompletionToken token) noexcept - -> coroutine_handle<partial_promise> +template <detail::execution_context Context, + typename CompletionToken, typename... Args> +partial_coro dispatch_coroutine(Context& ctx, + CompletionToken token, Args &&... args) noexcept { - dispatch(ctx, std::move(token)); + dispatch(ctx, asio::append(std::move(token), std::move(args)...)); co_return; } diff --git a/3rdparty/asio/include/asio/experimental/impl/append.hpp b/3rdparty/asio/include/asio/experimental/impl/append.hpp deleted file mode 100644 index 7a764832e1b..00000000000 --- a/3rdparty/asio/include/asio/experimental/impl/append.hpp +++ /dev/null @@ -1,217 +0,0 @@ -// -// experimental/impl/append.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IMPL_EXPERIMENTAL_APPEND_HPP -#define ASIO_IMPL_EXPERIMENTAL_APPEND_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#include "asio/associator.hpp" -#include "asio/async_result.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace experimental { -namespace detail { - -// Class to adapt a append_t as a completion handler. -template <typename Handler, typename... Values> -class append_handler -{ -public: - typedef void result_type; - - template <typename H> - append_handler(ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values) - : handler_(ASIO_MOVE_CAST(H)(handler)), - values_(ASIO_MOVE_CAST(std::tuple<Values...>)(values)) - { - } - - template <typename... Args> - void operator()(ASIO_MOVE_ARG(Args)... args) - { - this->invoke( - std::make_index_sequence<sizeof...(Values)>{}, - ASIO_MOVE_CAST(Args)(args)...); - } - - template <std::size_t... I, typename... Args> - void invoke(std::index_sequence<I...>, ASIO_MOVE_ARG(Args)... args) - { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( - ASIO_MOVE_CAST(Args)(args)..., - ASIO_MOVE_CAST(Values)(std::get<I>(values_))...); - } - -//private: - Handler handler_; - std::tuple<Values...> values_; -}; - -template <typename Handler> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - append_handler<Handler>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - append_handler<Handler>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> -inline bool asio_handler_is_continuation( - append_handler<Handler>* this_handler) -{ - return asio_handler_cont_helpers::is_continuation( - this_handler->handler_); -} - -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - append_handler<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - append_handler<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Signature, typename... Values> -struct append_signature; - -template <typename R, typename... Args, typename... Values> -struct append_signature<R(Args...), Values...> -{ - typedef R type(typename decay<Args>::type..., Values...); -}; - -} // namespace detail -} // namespace experimental - -#if !defined(GENERATING_DOCUMENTATION) - -template <typename CompletionToken, typename... Values, typename Signature> -struct async_result< - experimental::append_t<CompletionToken, Values...>, Signature> - : async_result<CompletionToken, - typename experimental::detail::append_signature< - Signature, Values...>::type> -{ - typedef typename experimental::detail::append_signature< - Signature, Values...>::type signature; - - template <typename Initiation> - struct init_wrapper - { - init_wrapper(Initiation init) - : initiation_(ASIO_MOVE_CAST(Initiation)(init)) - { - } - - template <typename Handler, typename... Args> - void operator()( - ASIO_MOVE_ARG(Handler) handler, - std::tuple<Values...> values, - ASIO_MOVE_ARG(Args)... args) - { - ASIO_MOVE_CAST(Initiation)(initiation_)( - experimental::detail::append_handler< - typename decay<Handler>::type, Values...>( - ASIO_MOVE_CAST(Handler)(handler), - ASIO_MOVE_CAST(std::tuple<Values...>)(values)), - ASIO_MOVE_CAST(Args)(args)...); - } - - Initiation initiation_; - }; - - template <typename Initiation, typename RawCompletionToken, typename... Args> - static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, signature, - (async_initiate<CompletionToken, signature>( - declval<init_wrapper<typename decay<Initiation>::type> >(), - declval<CompletionToken&>(), - declval<std::tuple<Values...> >(), - declval<ASIO_MOVE_ARG(Args)>()...))) - initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token, - ASIO_MOVE_ARG(Args)... args) - { - return async_initiate<CompletionToken, signature>( - init_wrapper<typename decay<Initiation>::type>( - ASIO_MOVE_CAST(Initiation)(initiation)), - token.token_, - ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_), - ASIO_MOVE_CAST(Args)(args)...); - } -}; - -template <template <typename, typename> class Associator, - typename Handler, typename DefaultCandidate> -struct associator<Associator, - experimental::detail::append_handler<Handler>, DefaultCandidate> - : Associator<Handler, DefaultCandidate> -{ - static typename Associator<Handler, DefaultCandidate>::type get( - const experimental::detail::append_handler<Handler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT - { - return Associator<Handler, DefaultCandidate>::get(h.handler_, c); - } -}; - -#endif // !defined(GENERATING_DOCUMENTATION) - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IMPL_EXPERIMENTAL_APPEND_HPP diff --git a/3rdparty/asio/include/asio/experimental/impl/as_single.hpp b/3rdparty/asio/include/asio/experimental/impl/as_single.hpp index dce5f2a3052..d183cf5679e 100644 --- a/3rdparty/asio/include/asio/experimental/impl/as_single.hpp +++ b/3rdparty/asio/include/asio/experimental/impl/as_single.hpp @@ -2,7 +2,7 @@ // experimental/impl/as_single.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,16 +16,11 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - #include <tuple> - #include "asio/associator.hpp" #include "asio/async_result.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" #include "asio/detail/push_options.hpp" @@ -42,33 +37,32 @@ public: template <typename CompletionToken> as_single_handler(as_single_t<CompletionToken> e) - : handler_(ASIO_MOVE_CAST(CompletionToken)(e.token_)) + : handler_(static_cast<CompletionToken&&>(e.token_)) { } template <typename RedirectedHandler> - as_single_handler(ASIO_MOVE_ARG(RedirectedHandler) h) - : handler_(ASIO_MOVE_CAST(RedirectedHandler)(h)) + as_single_handler(RedirectedHandler&& h) + : handler_(static_cast<RedirectedHandler&&>(h)) { } void operator()() { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)(); + static_cast<Handler&&>(handler_)(); } template <typename Arg> - void operator()(ASIO_MOVE_ARG(Arg) arg) + void operator()(Arg&& arg) { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( - ASIO_MOVE_CAST(Arg)(arg)); + static_cast<Handler&&>(handler_)(static_cast<Arg&&>(arg)); } template <typename... Args> - void operator()(ASIO_MOVE_ARG(Args)... args) + void operator()(Args&&... args) { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( - std::make_tuple(ASIO_MOVE_CAST(Args)(args)...)); + static_cast<Handler&&>(handler_)( + std::make_tuple(static_cast<Args&&>(args)...)); } //private: @@ -76,32 +70,6 @@ public: }; template <typename Handler> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - as_single_handler<Handler>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - as_single_handler<Handler>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> inline bool asio_handler_is_continuation( as_single_handler<Handler>* this_handler) { @@ -109,30 +77,6 @@ inline bool asio_handler_is_continuation( this_handler->handler_); } -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - as_single_handler<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - as_single_handler<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - template <typename Signature> struct as_single_signature { @@ -154,7 +98,7 @@ struct as_single_signature<R(Arg)> template <typename R, typename... Args> struct as_single_signature<R(Args...)> { - typedef R type(std::tuple<typename decay<Args>::type...>); + typedef R type(std::tuple<decay_t<Args>...>); }; } // namespace detail @@ -165,44 +109,41 @@ struct as_single_signature<R(Args...)> template <typename CompletionToken, typename Signature> struct async_result<experimental::as_single_t<CompletionToken>, Signature> { - typedef typename async_result<CompletionToken, - typename experimental::detail::as_single_signature<Signature>::type> - ::return_type return_type; - template <typename Initiation> struct init_wrapper { init_wrapper(Initiation init) - : initiation_(ASIO_MOVE_CAST(Initiation)(init)) + : initiation_(static_cast<Initiation&&>(init)) { } template <typename Handler, typename... Args> - void operator()( - ASIO_MOVE_ARG(Handler) handler, - ASIO_MOVE_ARG(Args)... args) + void operator()(Handler&& handler, Args&&... args) { - ASIO_MOVE_CAST(Initiation)(initiation_)( - experimental::detail::as_single_handler< - typename decay<Handler>::type>( - ASIO_MOVE_CAST(Handler)(handler)), - ASIO_MOVE_CAST(Args)(args)...); + static_cast<Initiation&&>(initiation_)( + experimental::detail::as_single_handler<decay_t<Handler>>( + static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); } Initiation initiation_; }; template <typename Initiation, typename RawCompletionToken, typename... Args> - static return_type initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token, - ASIO_MOVE_ARG(Args)... args) + static auto initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) + -> decltype( + async_initiate<CompletionToken, + typename experimental::detail::as_single_signature<Signature>::type>( + init_wrapper<decay_t<Initiation>>( + static_cast<Initiation&&>(initiation)), + token.token_, static_cast<Args&&>(args)...)) { return async_initiate<CompletionToken, typename experimental::detail::as_single_signature<Signature>::type>( - init_wrapper<typename decay<Initiation>::type>( - ASIO_MOVE_CAST(Initiation)(initiation)), - token.token_, ASIO_MOVE_CAST(Args)(args)...); + init_wrapper<decay_t<Initiation>>( + static_cast<Initiation&&>(initiation)), + token.token_, static_cast<Args&&>(args)...); } }; @@ -213,8 +154,14 @@ struct associator<Associator, : Associator<Handler, DefaultCandidate> { static typename Associator<Handler, DefaultCandidate>::type get( - const experimental::detail::as_single_handler<Handler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const experimental::detail::as_single_handler<Handler>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const experimental::detail::as_single_handler<Handler>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } diff --git a/3rdparty/asio/include/asio/experimental/impl/as_tuple.hpp b/3rdparty/asio/include/asio/experimental/impl/as_tuple.hpp deleted file mode 100644 index a1135de49dc..00000000000 --- a/3rdparty/asio/include/asio/experimental/impl/as_tuple.hpp +++ /dev/null @@ -1,246 +0,0 @@ -// -// experimental/impl/as_tuple.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IMPL_EXPERIMENTAL_AS_TUPLE_HPP -#define ASIO_IMPL_EXPERIMENTAL_AS_TUPLE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#include <tuple> - -#include "asio/associator.hpp" -#include "asio/async_result.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace experimental { -namespace detail { - -// Class to adapt a as_tuple_t as a completion handler. -template <typename Handler> -class as_tuple_handler -{ -public: - typedef void result_type; - - template <typename CompletionToken> - as_tuple_handler(as_tuple_t<CompletionToken> e) - : handler_(ASIO_MOVE_CAST(CompletionToken)(e.token_)) - { - } - - template <typename RedirectedHandler> - as_tuple_handler(ASIO_MOVE_ARG(RedirectedHandler) h) - : handler_(ASIO_MOVE_CAST(RedirectedHandler)(h)) - { - } - - template <typename... Args> - void operator()(ASIO_MOVE_ARG(Args)... args) - { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( - std::make_tuple(ASIO_MOVE_CAST(Args)(args)...)); - } - -//private: - Handler handler_; -}; - -template <typename Handler> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - as_tuple_handler<Handler>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - as_tuple_handler<Handler>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> -inline bool asio_handler_is_continuation( - as_tuple_handler<Handler>* this_handler) -{ - return asio_handler_cont_helpers::is_continuation( - this_handler->handler_); -} - -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - as_tuple_handler<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - as_tuple_handler<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Signature> -struct as_tuple_signature; - -template <typename R, typename... Args> -struct as_tuple_signature<R(Args...)> -{ - typedef R type(std::tuple<typename decay<Args>::type...>); -}; - -#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -template <typename R, typename... Args> -struct as_tuple_signature<R(Args...) &> -{ - typedef R type(std::tuple<typename decay<Args>::type...>) &; -}; - -template <typename R, typename... Args> -struct as_tuple_signature<R(Args...) &&> -{ - typedef R type(std::tuple<typename decay<Args>::type...>) &&; -}; - -# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) - -template <typename R, typename... Args> -struct as_tuple_signature<R(Args...) noexcept> -{ - typedef R type(std::tuple<typename decay<Args>::type...>) noexcept; -}; - -template <typename R, typename... Args> -struct as_tuple_signature<R(Args...) & noexcept> -{ - typedef R type(std::tuple<typename decay<Args>::type...>) & noexcept; -}; - -template <typename R, typename... Args> -struct as_tuple_signature<R(Args...) && noexcept> -{ - typedef R type(std::tuple<typename decay<Args>::type...>) && noexcept; -}; - -# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) -#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -} // namespace detail -} // namespace experimental - -#if !defined(GENERATING_DOCUMENTATION) - -template <typename CompletionToken, typename... Signatures> -struct async_result<experimental::as_tuple_t<CompletionToken>, Signatures...> - : async_result<CompletionToken, - typename experimental::detail::as_tuple_signature<Signatures>::type...> -{ - typedef async_result<CompletionToken, - typename experimental::detail::as_tuple_signature<Signatures>::type...> - base_async_result; - - template <typename Initiation> - struct init_wrapper - { - init_wrapper(Initiation init) - : initiation_(ASIO_MOVE_CAST(Initiation)(init)) - { - } - - template <typename Handler, typename... Args> - void operator()( - ASIO_MOVE_ARG(Handler) handler, - ASIO_MOVE_ARG(Args)... args) - { - ASIO_MOVE_CAST(Initiation)(initiation_)( - experimental::detail::as_tuple_handler< - typename decay<Handler>::type>( - ASIO_MOVE_CAST(Handler)(handler)), - ASIO_MOVE_CAST(Args)(args)...); - } - - Initiation initiation_; - }; - - template <typename Initiation, typename RawCompletionToken, typename... Args> - static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, - typename experimental::detail::as_tuple_signature<Signatures>::type..., - (base_async_result::initiate( - declval<init_wrapper<typename decay<Initiation>::type> >(), - declval<CompletionToken>(), - declval<ASIO_MOVE_ARG(Args)>()...))) - initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token, - ASIO_MOVE_ARG(Args)... args) - { - return base_async_result::initiate( - init_wrapper<typename decay<Initiation>::type>( - ASIO_MOVE_CAST(Initiation)(initiation)), - token.token_, ASIO_MOVE_CAST(Args)(args)...); - } -}; - -template <template <typename, typename> class Associator, - typename Handler, typename DefaultCandidate> -struct associator<Associator, - experimental::detail::as_tuple_handler<Handler>, DefaultCandidate> - : Associator<Handler, DefaultCandidate> -{ - static typename Associator<Handler, DefaultCandidate>::type get( - const experimental::detail::as_tuple_handler<Handler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT - { - return Associator<Handler, DefaultCandidate>::get(h.handler_, c); - } -}; - -#endif // !defined(GENERATING_DOCUMENTATION) - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IMPL_EXPERIMENTAL_AS_TUPLE_HPP diff --git a/3rdparty/asio/include/asio/experimental/impl/channel_error.ipp b/3rdparty/asio/include/asio/experimental/impl/channel_error.ipp new file mode 100644 index 00000000000..3f4b9829774 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/impl/channel_error.ipp @@ -0,0 +1,61 @@ +// +// experimental/impl/channel_error.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_IMPL_CHANNEL_ERROR_IPP +#define ASIO_EXPERIMENTAL_IMPL_CHANNEL_ERROR_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/experimental/channel_error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace error { +namespace detail { + +class channel_category : public asio::error_category +{ +public: + const char* name() const noexcept + { + return "asio.channel"; + } + + std::string message(int value) const + { + switch (value) + { + case channel_closed: return "Channel closed"; + case channel_cancelled: return "Channel cancelled"; + default: return "asio.channel error"; + } + } +}; + +} // namespace detail + +const asio::error_category& get_channel_category() +{ + static detail::channel_category instance; + return instance; +} + +} // namespace error +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_IMPL_CHANNEL_ERROR_IPP diff --git a/3rdparty/asio/include/asio/experimental/impl/co_composed.hpp b/3rdparty/asio/include/asio/experimental/impl/co_composed.hpp new file mode 100644 index 00000000000..3eef2e2ee2c --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/impl/co_composed.hpp @@ -0,0 +1,1174 @@ +// +// experimental/impl/co_composed.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_EXPERIMENTAL_CO_COMPOSED_HPP +#define ASIO_IMPL_EXPERIMENTAL_CO_COMPOSED_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <new> +#include <tuple> +#include <variant> +#include "asio/associated_cancellation_slot.hpp" +#include "asio/associator.hpp" +#include "asio/async_result.hpp" +#include "asio/cancellation_state.hpp" +#include "asio/detail/composed_work.hpp" +#include "asio/detail/recycling_allocator.hpp" +#include "asio/detail/throw_error.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/error.hpp" + +#if defined(ASIO_HAS_STD_COROUTINE) +# include <coroutine> +#else // defined(ASIO_HAS_STD_COROUTINE) +# include <experimental/coroutine> +#endif // defined(ASIO_HAS_STD_COROUTINE) + +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) +# include "asio/detail/source_location.hpp" +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { +namespace detail { + +#if defined(ASIO_HAS_STD_COROUTINE) +using std::coroutine_handle; +using std::suspend_always; +using std::suspend_never; +#else // defined(ASIO_HAS_STD_COROUTINE) +using std::experimental::coroutine_handle; +using std::experimental::suspend_always; +using std::experimental::suspend_never; +#endif // defined(ASIO_HAS_STD_COROUTINE) + +using asio::detail::composed_io_executors; +using asio::detail::composed_work; +using asio::detail::composed_work_guard; +using asio::detail::get_composed_io_executor; +using asio::detail::make_composed_io_executors; +using asio::detail::recycling_allocator; +using asio::detail::throw_error; + +template <typename Executors, typename Handler, typename Return> +class co_composed_state; + +template <typename Executors, typename Handler, typename Return> +class co_composed_handler_base; + +template <typename Executors, typename Handler, typename Return> +class co_composed_promise; + +template <completion_signature... Signatures> +class co_composed_returns +{ +}; + +struct co_composed_on_suspend +{ + void (*fn_)(void*) = nullptr; + void* arg_ = nullptr; +}; + +template <typename... T> +struct co_composed_completion : std::tuple<T&&...> +{ + template <typename... U> + co_composed_completion(U&&... u) noexcept + : std::tuple<T&&...>(std::forward<U>(u)...) + { + } +}; + +template <typename Executors, typename Handler, + typename Return, typename Signature> +class co_composed_state_return_overload; + +template <typename Executors, typename Handler, + typename Return, typename R, typename... Args> +class co_composed_state_return_overload< + Executors, Handler, Return, R(Args...)> +{ +public: + using derived_type = co_composed_state<Executors, Handler, Return>; + using promise_type = co_composed_promise<Executors, Handler, Return>; + using return_type = std::tuple<Args...>; + + void on_cancellation_complete_with(Args... args) + { + derived_type& state = *static_cast<derived_type*>(this); + state.return_value_ = std::make_tuple(std::move(args)...); + state.cancellation_on_suspend_fn( + [](void* p) + { + auto& promise = *static_cast<promise_type*>(p); + + co_composed_handler_base<Executors, Handler, + Return> composed_handler(promise); + + Handler handler(std::move(promise.state().handler_)); + return_type result( + std::move(std::get<return_type>(promise.state().return_value_))); + + co_composed_handler_base<Executors, Handler, + Return>(std::move(composed_handler)); + + std::apply(std::move(handler), std::move(result)); + }); + } +}; + +template <typename Executors, typename Handler, typename Return> +class co_composed_state_return; + +template <typename Executors, typename Handler, typename... Signatures> +class co_composed_state_return< + Executors, Handler, co_composed_returns<Signatures...>> + : public co_composed_state_return_overload<Executors, + Handler, co_composed_returns<Signatures...>, Signatures>... +{ +public: + using co_composed_state_return_overload<Executors, + Handler, co_composed_returns<Signatures...>, + Signatures>::on_cancellation_complete_with...; + +private: + template <typename, typename, typename, typename> + friend class co_composed_promise_return_overload; + template <typename, typename, typename, typename> + friend class co_composed_state_return_overload; + + std::variant<std::monostate, + typename co_composed_state_return_overload< + Executors, Handler, co_composed_returns<Signatures...>, + Signatures>::return_type...> return_value_; +}; + +template <typename Executors, typename Handler, + typename Return, typename... Signatures> +struct co_composed_state_default_cancellation_on_suspend_impl; + +template <typename Executors, typename Handler, typename Return> +struct co_composed_state_default_cancellation_on_suspend_impl< + Executors, Handler, Return> +{ + static constexpr void (*fn())(void*) + { + return nullptr; + } +}; + +template <typename Executors, typename Handler, typename Return, + typename R, typename... Args, typename... Signatures> +struct co_composed_state_default_cancellation_on_suspend_impl< + Executors, Handler, Return, R(Args...), Signatures...> +{ + static constexpr void (*fn())(void*) + { + return co_composed_state_default_cancellation_on_suspend_impl< + Executors, Handler, Return, Signatures...>::fn(); + } +}; + +template <typename Executors, typename Handler, typename Return, + typename R, typename... Args, typename... Signatures> +struct co_composed_state_default_cancellation_on_suspend_impl<Executors, + Handler, Return, R(asio::error_code, Args...), Signatures...> +{ + using promise_type = co_composed_promise<Executors, Handler, Return>; + using return_type = std::tuple<asio::error_code, Args...>; + + static constexpr void (*fn())(void*) + { + if constexpr ((is_constructible<Args>::value && ...)) + { + return [](void* p) + { + auto& promise = *static_cast<promise_type*>(p); + + co_composed_handler_base<Executors, Handler, + Return> composed_handler(promise); + + Handler handler(std::move(promise.state().handler_)); + + co_composed_handler_base<Executors, Handler, + Return>(std::move(composed_handler)); + + std::move(handler)( + asio::error_code(asio::error::operation_aborted), + Args{}...); + }; + } + else + { + return co_composed_state_default_cancellation_on_suspend_impl< + Executors, Handler, Return, Signatures...>::fn(); + } + } +}; + +template <typename Executors, typename Handler, typename Return, + typename R, typename... Args, typename... Signatures> +struct co_composed_state_default_cancellation_on_suspend_impl<Executors, + Handler, Return, R(std::exception_ptr, Args...), Signatures...> +{ + using promise_type = co_composed_promise<Executors, Handler, Return>; + using return_type = std::tuple<std::exception_ptr, Args...>; + + static constexpr void (*fn())(void*) + { + if constexpr ((is_constructible<Args>::value && ...)) + { + return [](void* p) + { + auto& promise = *static_cast<promise_type*>(p); + + co_composed_handler_base<Executors, Handler, + Return> composed_handler(promise); + + Handler handler(std::move(promise.state().handler_)); + + co_composed_handler_base<Executors, Handler, + Return>(std::move(composed_handler)); + + std::move(handler)( + std::make_exception_ptr( + asio::system_error( + asio::error::operation_aborted, "co_await")), + Args{}...); + }; + } + else + { + return co_composed_state_default_cancellation_on_suspend_impl< + Executors, Handler, Return, Signatures...>::fn(); + } + } +}; + +template <typename Executors, typename Handler, typename Return> +struct co_composed_state_default_cancellation_on_suspend; + +template <typename Executors, typename Handler, typename... Signatures> +struct co_composed_state_default_cancellation_on_suspend< + Executors, Handler, co_composed_returns<Signatures...>> + : co_composed_state_default_cancellation_on_suspend_impl<Executors, + Handler, co_composed_returns<Signatures...>, Signatures...> +{ +}; + +template <typename Executors, typename Handler, typename Return> +class co_composed_state_cancellation +{ +public: + using cancellation_slot_type = cancellation_slot; + + cancellation_slot_type get_cancellation_slot() const noexcept + { + return cancellation_state_.slot(); + } + + cancellation_state get_cancellation_state() const noexcept + { + return cancellation_state_; + } + + void reset_cancellation_state() + { + cancellation_state_ = cancellation_state( + (get_associated_cancellation_slot)( + static_cast<co_composed_state<Executors, Handler, Return>*>( + this)->handler())); + } + + template <typename Filter> + void reset_cancellation_state(Filter filter) + { + cancellation_state_ = cancellation_state( + (get_associated_cancellation_slot)( + static_cast<co_composed_state<Executors, Handler, Return>*>( + this)->handler()), filter, filter); + } + + template <typename InFilter, typename OutFilter> + void reset_cancellation_state(InFilter&& in_filter, OutFilter&& out_filter) + { + cancellation_state_ = cancellation_state( + (get_associated_cancellation_slot)( + static_cast<co_composed_state<Executors, Handler, Return>*>( + this)->handler()), + std::forward<InFilter>(in_filter), + std::forward<OutFilter>(out_filter)); + } + + cancellation_type_t cancelled() const noexcept + { + return cancellation_state_.cancelled(); + } + + void clear_cancellation_slot() noexcept + { + cancellation_state_.slot().clear(); + } + + [[nodiscard]] bool throw_if_cancelled() const noexcept + { + return throw_if_cancelled_; + } + + void throw_if_cancelled(bool b) noexcept + { + throw_if_cancelled_ = b; + } + + [[nodiscard]] bool complete_if_cancelled() const noexcept + { + return complete_if_cancelled_; + } + + void complete_if_cancelled(bool b) noexcept + { + complete_if_cancelled_ = b; + } + +private: + template <typename, typename, typename> + friend class co_composed_promise; + template <typename, typename, typename, typename> + friend class co_composed_state_return_overload; + + void cancellation_on_suspend_fn(void (*fn)(void*)) + { + cancellation_on_suspend_fn_ = fn; + } + + void check_for_cancellation_on_transform() + { + if (throw_if_cancelled_ && !!cancelled()) + throw_error(asio::error::operation_aborted, "co_await"); + } + + bool check_for_cancellation_on_suspend( + co_composed_promise<Executors, Handler, Return>& promise) noexcept + { + if (complete_if_cancelled_ && !!cancelled() && cancellation_on_suspend_fn_) + { + promise.state().work_.reset(); + promise.state().on_suspend_->fn_ = cancellation_on_suspend_fn_; + promise.state().on_suspend_->arg_ = &promise; + return false; + } + return true; + } + + cancellation_state cancellation_state_; + void (*cancellation_on_suspend_fn_)(void*) = + co_composed_state_default_cancellation_on_suspend< + Executors, Handler, Return>::fn(); + bool throw_if_cancelled_ = false; + bool complete_if_cancelled_ = true; +}; + +template <typename Executors, typename Handler, typename Return> + requires is_same< + typename associated_cancellation_slot< + Handler, cancellation_slot + >::asio_associated_cancellation_slot_is_unspecialised, + void>::value +class co_composed_state_cancellation<Executors, Handler, Return> +{ +public: + void reset_cancellation_state() + { + } + + template <typename Filter> + void reset_cancellation_state(Filter) + { + } + + template <typename InFilter, typename OutFilter> + void reset_cancellation_state(InFilter&&, OutFilter&&) + { + } + + cancellation_type_t cancelled() const noexcept + { + return cancellation_type::none; + } + + void clear_cancellation_slot() noexcept + { + } + + [[nodiscard]] bool throw_if_cancelled() const noexcept + { + return false; + } + + void throw_if_cancelled(bool) noexcept + { + } + + [[nodiscard]] bool complete_if_cancelled() const noexcept + { + return false; + } + + void complete_if_cancelled(bool) noexcept + { + } + +private: + template <typename, typename, typename> + friend class co_composed_promise; + template <typename, typename, typename, typename> + friend class co_composed_state_return_overload; + + void cancellation_on_suspend_fn(void (*)(void*)) + { + } + + void check_for_cancellation_on_transform() noexcept + { + } + + bool check_for_cancellation_on_suspend( + co_composed_promise<Executors, Handler, Return>&) noexcept + { + return true; + } +}; + +template <typename Executors, typename Handler, typename Return> +class co_composed_state + : public co_composed_state_return<Executors, Handler, Return>, + public co_composed_state_cancellation<Executors, Handler, Return> +{ +public: + using io_executor_type = typename composed_work_guard< + typename composed_work<Executors>::head_type>::executor_type; + + template <typename H> + co_composed_state(composed_io_executors<Executors>&& executors, + H&& h, co_composed_on_suspend& on_suspend) + : work_(std::move(executors)), + handler_(std::forward<H>(h)), + on_suspend_(&on_suspend) + { + this->reset_cancellation_state(enable_terminal_cancellation()); + } + + io_executor_type get_io_executor() const noexcept + { + return work_.head_.get_executor(); + } + + template <typename... Args> + [[nodiscard]] co_composed_completion<Args...> complete(Args&&... args) + requires requires { declval<Handler>()(std::forward<Args>(args)...); } + { + return co_composed_completion<Args...>(std::forward<Args>(args)...); + } + + const Handler& handler() const noexcept + { + return handler_; + } + +private: + template <typename, typename, typename> + friend class co_composed_handler_base; + template <typename, typename, typename> + friend class co_composed_promise; + template <typename, typename, typename, typename> + friend class co_composed_promise_return_overload; + template <typename, typename, typename> + friend class co_composed_state_cancellation; + template <typename, typename, typename, typename> + friend class co_composed_state_return_overload; + template <typename, typename, typename, typename...> + friend struct co_composed_state_default_cancellation_on_suspend_impl; + + composed_work<Executors> work_; + Handler handler_; + co_composed_on_suspend* on_suspend_; +}; + +template <typename Executors, typename Handler, typename Return> +class co_composed_handler_cancellation +{ +public: + using cancellation_slot_type = cancellation_slot; + + cancellation_slot_type get_cancellation_slot() const noexcept + { + return static_cast< + const co_composed_handler_base<Executors, Handler, Return>*>( + this)->promise().state().get_cancellation_slot(); + } +}; + +template <typename Executors, typename Handler, typename Return> + requires is_same< + typename associated_cancellation_slot< + Handler, cancellation_slot + >::asio_associated_cancellation_slot_is_unspecialised, + void>::value +class co_composed_handler_cancellation<Executors, Handler, Return> +{ +}; + +template <typename Executors, typename Handler, typename Return> +class co_composed_handler_base : + public co_composed_handler_cancellation<Executors, Handler, Return> +{ +public: + co_composed_handler_base( + co_composed_promise<Executors, Handler, Return>& p) noexcept + : p_(&p) + { + } + + co_composed_handler_base(co_composed_handler_base&& other) noexcept + : p_(std::exchange(other.p_, nullptr)) + { + } + + ~co_composed_handler_base() + { + if (p_) [[unlikely]] + p_->destroy(); + } + + co_composed_promise<Executors, Handler, Return>& promise() const noexcept + { + return *p_; + } + +protected: + void resume(void* result) + { + co_composed_on_suspend on_suspend{}; + std::exchange(p_, nullptr)->resume(p_, result, on_suspend); + if (on_suspend.fn_) + on_suspend.fn_(on_suspend.arg_); + } + +private: + co_composed_promise<Executors, Handler, Return>* p_; +}; + +template <typename Executors, typename Handler, + typename Return, typename Signature> +class co_composed_handler; + +template <typename Executors, typename Handler, + typename Return, typename R, typename... Args> +class co_composed_handler<Executors, Handler, Return, R(Args...)> + : public co_composed_handler_base<Executors, Handler, Return> +{ +public: + using co_composed_handler_base<Executors, + Handler, Return>::co_composed_handler_base; + + using result_type = std::tuple<decay_t<Args>...>; + + template <typename... T> + void operator()(T&&... args) + { + result_type result(std::forward<T>(args)...); + this->resume(&result); + } + + static auto on_resume(void* result) + { + auto& args = *static_cast<result_type*>(result); + if constexpr (sizeof...(Args) == 0) + return; + else if constexpr (sizeof...(Args) == 1) + return std::move(std::get<0>(args)); + else + return std::move(args); + } +}; + +template <typename Executors, typename Handler, + typename Return, typename R, typename... Args> +class co_composed_handler<Executors, Handler, + Return, R(asio::error_code, Args...)> + : public co_composed_handler_base<Executors, Handler, Return> +{ +public: + using co_composed_handler_base<Executors, + Handler, Return>::co_composed_handler_base; + + using args_type = std::tuple<decay_t<Args>...>; + using result_type = std::tuple<asio::error_code, args_type>; + + template <typename... T> + void operator()(const asio::error_code& ec, T&&... args) + { + result_type result(ec, args_type(std::forward<T>(args)...)); + this->resume(&result); + } + + static auto on_resume(void* result) + { + auto& [ec, args] = *static_cast<result_type*>(result); + throw_error(ec); + if constexpr (sizeof...(Args) == 0) + return; + else if constexpr (sizeof...(Args) == 1) + return std::move(std::get<0>(args)); + else + return std::move(args); + } +}; + +template <typename Executors, typename Handler, + typename Return, typename R, typename... Args> +class co_composed_handler<Executors, Handler, + Return, R(std::exception_ptr, Args...)> + : public co_composed_handler_base<Executors, Handler, Return> +{ +public: + using co_composed_handler_base<Executors, + Handler, Return>::co_composed_handler_base; + + using args_type = std::tuple<decay_t<Args>...>; + using result_type = std::tuple<std::exception_ptr, args_type>; + + template <typename... T> + void operator()(std::exception_ptr ex, T&&... args) + { + result_type result(std::move(ex), args_type(std::forward<T>(args)...)); + this->resume(&result); + } + + static auto on_resume(void* result) + { + auto& [ex, args] = *static_cast<result_type*>(result); + if (ex) + std::rethrow_exception(ex); + if constexpr (sizeof...(Args) == 0) + return; + else if constexpr (sizeof...(Args) == 1) + return std::move(std::get<0>(args)); + else + return std::move(args); + } +}; + +template <typename Executors, typename Handler, typename Return> +class co_composed_promise_return; + +template <typename Executors, typename Handler> +class co_composed_promise_return<Executors, Handler, co_composed_returns<>> +{ +public: + auto final_suspend() noexcept + { + return suspend_never(); + } + + void return_void() noexcept + { + } +}; + +template <typename Executors, typename Handler, + typename Return, typename Signature> +class co_composed_promise_return_overload; + +template <typename Executors, typename Handler, + typename Return, typename R, typename... Args> +class co_composed_promise_return_overload< + Executors, Handler, Return, R(Args...)> +{ +public: + using derived_type = co_composed_promise<Executors, Handler, Return>; + using return_type = std::tuple<Args...>; + + void return_value(std::tuple<Args...>&& value) + { + derived_type& promise = *static_cast<derived_type*>(this); + promise.state().return_value_ = std::move(value); + promise.state().work_.reset(); + promise.state().on_suspend_->arg_ = this; + promise.state().on_suspend_->fn_ = + [](void* p) + { + auto& promise = *static_cast<derived_type*>(p); + + co_composed_handler_base<Executors, Handler, + Return> composed_handler(promise); + + Handler handler(std::move(promise.state().handler_)); + return_type result( + std::move(std::get<return_type>(promise.state().return_value_))); + + co_composed_handler_base<Executors, Handler, + Return>(std::move(composed_handler)); + + std::apply(std::move(handler), std::move(result)); + }; + } +}; + +template <typename Executors, typename Handler, typename... Signatures> +class co_composed_promise_return<Executors, + Handler, co_composed_returns<Signatures...>> + : public co_composed_promise_return_overload<Executors, + Handler, co_composed_returns<Signatures...>, Signatures>... +{ +public: + auto final_suspend() noexcept + { + return suspend_always(); + } + + using co_composed_promise_return_overload<Executors, Handler, + co_composed_returns<Signatures...>, Signatures>::return_value...; + +private: + template <typename, typename, typename, typename> + friend class co_composed_promise_return_overload; +}; + +template <typename Executors, typename Handler, typename Return> +class co_composed_promise + : public co_composed_promise_return<Executors, Handler, Return> +{ +public: + template <typename... Args> + void* operator new(std::size_t size, + co_composed_state<Executors, Handler, Return>& state, Args&&...) + { + block_allocator_type allocator( + (get_associated_allocator)(state.handler_, + recycling_allocator<void>())); + + block* base_ptr = std::allocator_traits<block_allocator_type>::allocate( + allocator, blocks(sizeof(allocator_type)) + blocks(size)); + + new (static_cast<void*>(base_ptr)) allocator_type(std::move(allocator)); + + return base_ptr + blocks(sizeof(allocator_type)); + } + + template <typename C, typename... Args> + void* operator new(std::size_t size, C&&, + co_composed_state<Executors, Handler, Return>& state, Args&&...) + { + return co_composed_promise::operator new(size, state); + } + + void operator delete(void* ptr, std::size_t size) + { + block* base_ptr = static_cast<block*>(ptr) - blocks(sizeof(allocator_type)); + + allocator_type* allocator_ptr = std::launder( + static_cast<allocator_type*>(static_cast<void*>(base_ptr))); + + block_allocator_type block_allocator(std::move(*allocator_ptr)); + allocator_ptr->~allocator_type(); + + std::allocator_traits<block_allocator_type>::deallocate(block_allocator, + base_ptr, blocks(sizeof(allocator_type)) + blocks(size)); + } + + template <typename... Args> + co_composed_promise( + co_composed_state<Executors, Handler, Return>& state, Args&&...) + : state_(state) + { + } + + template <typename C, typename... Args> + co_composed_promise(C&&, + co_composed_state<Executors, Handler, Return>& state, Args&&...) + : state_(state) + { + } + + void destroy() noexcept + { + coroutine_handle<co_composed_promise>::from_promise(*this).destroy(); + } + + void resume(co_composed_promise*& owner, void* result, + co_composed_on_suspend& on_suspend) + { + state_.on_suspend_ = &on_suspend; + state_.clear_cancellation_slot(); + owner_ = &owner; + result_ = result; + coroutine_handle<co_composed_promise>::from_promise(*this).resume(); + } + + co_composed_state<Executors, Handler, Return>& state() noexcept + { + return state_; + } + + void get_return_object() noexcept + { + } + + auto initial_suspend() noexcept + { + return suspend_never(); + } + + void unhandled_exception() + { + if (owner_) + *owner_ = this; + throw; + } + + template <async_operation Op> + auto await_transform(Op&& op +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + , asio::detail::source_location location + = asio::detail::source_location::current() +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + ) + { + class [[nodiscard]] awaitable + { + public: + awaitable(Op&& op, co_composed_promise& promise +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + , const asio::detail::source_location& location +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + ) + : op_(std::forward<Op>(op)), + promise_(promise) +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + , location_(location) +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + { + } + + constexpr bool await_ready() const noexcept + { + return false; + } + + void await_suspend(coroutine_handle<co_composed_promise>) + { + if (promise_.state_.check_for_cancellation_on_suspend(promise_)) + { + promise_.state_.on_suspend_->arg_ = this; + promise_.state_.on_suspend_->fn_ = + [](void* p) + { +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + ASIO_HANDLER_LOCATION(( + static_cast<awaitable*>(p)->location_.file_name(), + static_cast<awaitable*>(p)->location_.line(), + static_cast<awaitable*>(p)->location_.function_name())); +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + std::forward<Op>(static_cast<awaitable*>(p)->op_)( + co_composed_handler<Executors, Handler, + Return, completion_signature_of_t<Op>>( + static_cast<awaitable*>(p)->promise_)); + }; + } + } + + auto await_resume() + { + return co_composed_handler<Executors, Handler, Return, + completion_signature_of_t<Op>>::on_resume(promise_.result_); + } + + private: + Op&& op_; + co_composed_promise& promise_; +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + asio::detail::source_location location_; +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + }; + + state_.check_for_cancellation_on_transform(); + return awaitable{std::forward<Op>(op), *this +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + , location +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + }; + } + + template <typename... Args> + auto yield_value(co_composed_completion<Args...>&& result) + { + class [[nodiscard]] awaitable + { + public: + awaitable(co_composed_completion<Args...>&& result, + co_composed_promise& promise) + : result_(std::move(result)), + promise_(promise) + { + } + + constexpr bool await_ready() const noexcept + { + return false; + } + + void await_suspend(coroutine_handle<co_composed_promise>) + { + promise_.state_.work_.reset(); + promise_.state_.on_suspend_->arg_ = this; + promise_.state_.on_suspend_->fn_ = + [](void* p) + { + awaitable& a = *static_cast<awaitable*>(p); + + co_composed_handler_base<Executors, Handler, + Return> composed_handler(a.promise_); + + Handler handler(std::move(a.promise_.state_.handler_)); + std::tuple<decay_t<Args>...> result( + std::move(static_cast<std::tuple<Args&&...>>(a.result_))); + + co_composed_handler_base<Executors, Handler, + Return>(std::move(composed_handler)); + + std::apply(std::move(handler), std::move(result)); + }; + } + + void await_resume() noexcept + { + } + + private: + co_composed_completion<Args...> result_; + co_composed_promise& promise_; + }; + + return awaitable{std::move(result), *this}; + } + +private: + using allocator_type = + associated_allocator_t<Handler, recycling_allocator<void>>; + + union block + { + std::max_align_t max_align; + alignas(allocator_type) char pad[alignof(allocator_type)]; + }; + + using block_allocator_type = + typename std::allocator_traits<allocator_type> + ::template rebind_alloc<block>; + + static constexpr std::size_t blocks(std::size_t size) + { + return (size + sizeof(block) - 1) / sizeof(block); + } + + co_composed_state<Executors, Handler, Return>& state_; + co_composed_promise** owner_ = nullptr; + void* result_ = nullptr; +}; + +template <typename Implementation, typename Executors, typename... Signatures> +class initiate_co_composed +{ +public: + using executor_type = typename composed_io_executors<Executors>::head_type; + + template <typename I> + initiate_co_composed(I&& impl, composed_io_executors<Executors>&& executors) + : implementation_(std::forward<I>(impl)), + executors_(std::move(executors)) + { + } + + executor_type get_executor() const noexcept + { + return executors_.head_; + } + + template <typename Handler, typename... InitArgs> + void operator()(Handler&& handler, InitArgs&&... init_args) const & + { + using handler_type = decay_t<Handler>; + using returns_type = co_composed_returns<Signatures...>; + co_composed_on_suspend on_suspend{}; + implementation_( + co_composed_state<Executors, handler_type, returns_type>( + executors_, std::forward<Handler>(handler), on_suspend), + std::forward<InitArgs>(init_args)...); + if (on_suspend.fn_) + on_suspend.fn_(on_suspend.arg_); + } + + template <typename Handler, typename... InitArgs> + void operator()(Handler&& handler, InitArgs&&... init_args) && + { + using handler_type = decay_t<Handler>; + using returns_type = co_composed_returns<Signatures...>; + co_composed_on_suspend on_suspend{}; + std::move(implementation_)( + co_composed_state<Executors, handler_type, returns_type>( + std::move(executors_), std::forward<Handler>(handler), on_suspend), + std::forward<InitArgs>(init_args)...); + if (on_suspend.fn_) + on_suspend.fn_(on_suspend.arg_); + } + +private: + Implementation implementation_; + composed_io_executors<Executors> executors_; +}; + +template <typename... Signatures, typename Implementation, typename Executors> +inline initiate_co_composed<Implementation, Executors, Signatures...> +make_initiate_co_composed(Implementation&& implementation, + composed_io_executors<Executors>&& executors) +{ + return initiate_co_composed< + decay_t<Implementation>, Executors, Signatures...>( + std::forward<Implementation>(implementation), std::move(executors)); +} + +} // namespace detail + +template <completion_signature... Signatures, + typename Implementation, typename... IoObjectsOrExecutors> +inline auto co_composed(Implementation&& implementation, + IoObjectsOrExecutors&&... io_objects_or_executors) +{ + return detail::make_initiate_co_composed<Signatures...>( + std::forward<Implementation>(implementation), + detail::make_composed_io_executors( + detail::get_composed_io_executor( + std::forward<IoObjectsOrExecutors>( + io_objects_or_executors))...)); +} + +} // namespace experimental + +#if !defined(GENERATING_DOCUMENTATION) + +template <template <typename, typename> class Associator, + typename Executors, typename Handler, typename Return, + typename Signature, typename DefaultCandidate> +struct associator<Associator, + experimental::detail::co_composed_handler< + Executors, Handler, Return, Signature>, + DefaultCandidate> + : Associator<Handler, DefaultCandidate> +{ + static typename Associator<Handler, DefaultCandidate>::type get( + const experimental::detail::co_composed_handler< + Executors, Handler, Return, Signature>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get( + h.promise().state().handler()); + } + + static auto get( + const experimental::detail::co_composed_handler< + Executors, Handler, Return, Signature>& h, + const DefaultCandidate& c) noexcept + -> decltype( + Associator<Handler, DefaultCandidate>::get( + h.promise().state().handler(), c)) + { + return Associator<Handler, DefaultCandidate>::get( + h.promise().state().handler(), c); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio + +#if !defined(GENERATING_DOCUMENTATION) +# if defined(ASIO_HAS_STD_COROUTINE) +namespace std { +# else // defined(ASIO_HAS_STD_COROUTINE) +namespace std { namespace experimental { +# endif // defined(ASIO_HAS_STD_COROUTINE) + +template <typename C, typename Executors, + typename Handler, typename Return, typename... Args> +struct coroutine_traits<void, C&, + asio::experimental::detail::co_composed_state< + Executors, Handler, Return>, + Args...> +{ + using promise_type = + asio::experimental::detail::co_composed_promise< + Executors, Handler, Return>; +}; + +template <typename C, typename Executors, + typename Handler, typename Return, typename... Args> +struct coroutine_traits<void, C&&, + asio::experimental::detail::co_composed_state< + Executors, Handler, Return>, + Args...> +{ + using promise_type = + asio::experimental::detail::co_composed_promise< + Executors, Handler, Return>; +}; + +template <typename Executors, typename Handler, + typename Return, typename... Args> +struct coroutine_traits<void, + asio::experimental::detail::co_composed_state< + Executors, Handler, Return>, + Args...> +{ + using promise_type = + asio::experimental::detail::co_composed_promise< + Executors, Handler, Return>; +}; + +# if defined(ASIO_HAS_STD_COROUTINE) +} // namespace std +# else // defined(ASIO_HAS_STD_COROUTINE) +}} // namespace std::experimental +# endif // defined(ASIO_HAS_STD_COROUTINE) +#endif // !defined(GENERATING_DOCUMENTATION) + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_EXPERIMENTAL_CO_COMPOSED_HPP diff --git a/3rdparty/asio/include/asio/experimental/impl/coro.hpp b/3rdparty/asio/include/asio/experimental/impl/coro.hpp new file mode 100644 index 00000000000..872d1a0255c --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/impl/coro.hpp @@ -0,0 +1,1222 @@ +// +// experimental/impl/coro.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// +#ifndef ASIO_EXPERIMENTAL_IMPL_CORO_HPP +#define ASIO_EXPERIMENTAL_IMPL_CORO_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/append.hpp" +#include "asio/associated_cancellation_slot.hpp" +#include "asio/bind_allocator.hpp" +#include "asio/deferred.hpp" +#include "asio/experimental/detail/coro_completion_handler.hpp" +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { + +template <typename Yield, typename Return, + typename Executor, typename Allocator> +struct coro; + +namespace detail { + +struct coro_cancellation_source +{ + cancellation_slot slot; + cancellation_state state; + bool throw_if_cancelled_ = true; + + void reset_cancellation_state() + { + state = cancellation_state(slot); + } + + template <typename Filter> + void reset_cancellation_state(Filter&& filter) + { + state = cancellation_state(slot, static_cast<Filter&&>(filter)); + } + + template <typename InFilter, typename OutFilter> + void reset_cancellation_state(InFilter&& in_filter, + OutFilter&& out_filter) + { + state = cancellation_state(slot, + static_cast<InFilter&&>(in_filter), + static_cast<OutFilter&&>(out_filter)); + } + + bool throw_if_cancelled() const + { + return throw_if_cancelled_; + } + + void throw_if_cancelled(bool value) + { + throw_if_cancelled_ = value; + } +}; + +template <typename Signature, typename Return, + typename Executor, typename Allocator> +struct coro_promise; + +template <typename T> +struct is_noexcept : std::false_type +{ +}; + +template <typename Return, typename... Args> +struct is_noexcept<Return(Args...)> : std::false_type +{ +}; + +template <typename Return, typename... Args> +struct is_noexcept<Return(Args...) noexcept> : std::true_type +{ +}; + +template <typename T> +constexpr bool is_noexcept_v = is_noexcept<T>::value; + +template <typename T> +struct coro_error; + +template <> +struct coro_error<asio::error_code> +{ + static asio::error_code invalid() + { + return asio::error::fault; + } + + static asio::error_code cancelled() + { + return asio::error::operation_aborted; + } + + static asio::error_code interrupted() + { + return asio::error::interrupted; + } + + static asio::error_code done() + { + return asio::error::broken_pipe; + } +}; + +template <> +struct coro_error<std::exception_ptr> +{ + static std::exception_ptr invalid() + { + return std::make_exception_ptr( + asio::system_error( + coro_error<asio::error_code>::invalid())); + } + + static std::exception_ptr cancelled() + { + return std::make_exception_ptr( + asio::system_error( + coro_error<asio::error_code>::cancelled())); + } + + static std::exception_ptr interrupted() + { + return std::make_exception_ptr( + asio::system_error( + coro_error<asio::error_code>::interrupted())); + } + + static std::exception_ptr done() + { + return std::make_exception_ptr( + asio::system_error( + coro_error<asio::error_code>::done())); + } +}; + +template <typename T, typename Coroutine > +struct coro_with_arg +{ + using coro_t = Coroutine; + T value; + coro_t& coro; + + struct awaitable_t + { + T value; + coro_t& coro; + + constexpr static bool await_ready() { return false; } + + template <typename Y, typename R, typename E, typename A> + auto await_suspend(coroutine_handle<coro_promise<Y, R, E, A>> h) + -> coroutine_handle<> + { + auto& hp = h.promise(); + + if constexpr (!coro_promise<Y, R, E, A>::is_noexcept) + { + if ((hp.cancel->state.cancelled() != cancellation_type::none) + && hp.cancel->throw_if_cancelled_) + { + asio::detail::throw_error( + asio::error::operation_aborted, "coro-cancelled"); + } + } + + if (hp.get_executor() == coro.get_executor()) + { + coro.coro_->awaited_from = h; + coro.coro_->reset_error(); + coro.coro_->input_ = std::move(value); + coro.coro_->cancel = hp.cancel; + return coro.coro_->get_handle(); + } + else + { + coro.coro_->awaited_from = + dispatch_coroutine( + asio::prefer(hp.get_executor(), + execution::outstanding_work.tracked), + [h]() mutable { h.resume(); }).handle; + + coro.coro_->reset_error(); + coro.coro_->input_ = std::move(value); + + struct cancel_handler + { + using src = std::pair<cancellation_signal, + detail::coro_cancellation_source>; + + std::shared_ptr<src> st = std::make_shared<src>(); + + cancel_handler(E e, coro_t& coro) : e(e), coro_(coro.coro_) + { + st->second.state = + cancellation_state(st->second.slot = st->first.slot()); + } + + E e; + typename coro_t::promise_type* coro_; + + void operator()(cancellation_type ct) + { + asio::dispatch(e, [ct, st = st]() mutable + { + auto & [sig, state] = *st; + sig.emit(ct); + }); + } + }; + + if (hp.cancel->state.slot().is_connected()) + { + hp.cancel->state.slot().template emplace<cancel_handler>( + coro.get_executor(), coro); + } + + auto hh = detail::coroutine_handle< + typename coro_t::promise_type>::from_promise(*coro.coro_); + + return dispatch_coroutine( + coro.coro_->get_executor(), [hh]() mutable { hh.resume(); }).handle; + } + } + + auto await_resume() -> typename coro_t::result_type + { + coro.coro_->cancel = nullptr; + coro.coro_->rethrow_if(); + return std::move(coro.coro_->result_); + } + }; + + template <typename CompletionToken> + auto async_resume(CompletionToken&& token) && + { + return coro.async_resume(std::move(value), + std::forward<CompletionToken>(token)); + } + + auto operator co_await() && + { + return awaitable_t{std::move(value), coro}; + } +}; + +template <bool IsNoexcept> +struct coro_promise_error; + +template <> +struct coro_promise_error<false> +{ + std::exception_ptr error_; + + void reset_error() + { + error_ = std::exception_ptr{}; + } + + void unhandled_exception() + { + error_ = std::current_exception(); + } + + void rethrow_if() + { + if (error_) + std::rethrow_exception(error_); + } +}; + +#if defined(__GNUC__) +# pragma GCC diagnostic push +# if defined(__clang__) +# pragma GCC diagnostic ignored "-Wexceptions" +# else +# pragma GCC diagnostic ignored "-Wterminate" +# endif +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning (disable:4297) +#endif + +template <> +struct coro_promise_error<true> +{ + void reset_error() + { + } + + void unhandled_exception() noexcept + { + throw; + } + + void rethrow_if() + { + } +}; + +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#elif defined(_MSC_VER) +# pragma warning(pop) +#endif + +template <typename T = void> +struct yield_input +{ + T& value; + coroutine_handle<> awaited_from{noop_coroutine()}; + + bool await_ready() const noexcept + { + return false; + } + + template <typename U> + coroutine_handle<> await_suspend(coroutine_handle<U>) noexcept + { + return std::exchange(awaited_from, noop_coroutine()); + } + + T await_resume() const noexcept + { + return std::move(value); + } +}; + +template <> +struct yield_input<void> +{ + coroutine_handle<> awaited_from{noop_coroutine()}; + + bool await_ready() const noexcept + { + return false; + } + + auto await_suspend(coroutine_handle<>) noexcept + { + return std::exchange(awaited_from, noop_coroutine()); + } + + constexpr void await_resume() const noexcept + { + } +}; + +struct coro_awaited_from +{ + coroutine_handle<> awaited_from{noop_coroutine()}; + + auto final_suspend() noexcept + { + struct suspendor + { + coroutine_handle<> awaited_from; + + constexpr static bool await_ready() noexcept + { + return false; + } + + auto await_suspend(coroutine_handle<>) noexcept + { + return std::exchange(awaited_from, noop_coroutine()); + } + + constexpr static void await_resume() noexcept + { + } + }; + + return suspendor{std::exchange(awaited_from, noop_coroutine())}; + } + + ~coro_awaited_from() + { + awaited_from.resume(); + }//must be on the right executor +}; + +template <typename Yield, typename Input, typename Return> +struct coro_promise_exchange : coro_awaited_from +{ + using result_type = coro_result_t<Yield, Return>; + + result_type result_; + Input input_; + + auto yield_value(Yield&& y) + { + result_ = std::move(y); + return yield_input<Input>{std::move(input_), + std::exchange(awaited_from, noop_coroutine())}; + } + + auto yield_value(const Yield& y) + { + result_ = y; + return yield_input<Input>{std::move(input_), + std::exchange(awaited_from, noop_coroutine())}; + } + + void return_value(const Return& r) + { + result_ = r; + } + + void return_value(Return&& r) + { + result_ = std::move(r); + } +}; + +template <typename YieldReturn> +struct coro_promise_exchange<YieldReturn, void, YieldReturn> : coro_awaited_from +{ + using result_type = coro_result_t<YieldReturn, YieldReturn>; + + result_type result_; + + auto yield_value(const YieldReturn& y) + { + result_ = y; + return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; + } + + auto yield_value(YieldReturn&& y) + { + result_ = std::move(y); + return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; + } + + void return_value(const YieldReturn& r) + { + result_ = r; + } + + void return_value(YieldReturn&& r) + { + result_ = std::move(r); + } +}; + +template <typename Yield, typename Return> +struct coro_promise_exchange<Yield, void, Return> : coro_awaited_from +{ + using result_type = coro_result_t<Yield, Return>; + + result_type result_; + + auto yield_value(const Yield& y) + { + result_.template emplace<0>(y); + return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; + } + + auto yield_value(Yield&& y) + { + result_.template emplace<0>(std::move(y)); + return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; + } + + void return_value(const Return& r) + { + result_.template emplace<1>(r); + } + + void return_value(Return&& r) + { + result_.template emplace<1>(std::move(r)); + } +}; + +template <typename Yield, typename Input> +struct coro_promise_exchange<Yield, Input, void> : coro_awaited_from +{ + using result_type = coro_result_t<Yield, void>; + + result_type result_; + Input input_; + + auto yield_value(Yield&& y) + { + result_ = std::move(y); + return yield_input<Input>{input_, + std::exchange(awaited_from, noop_coroutine())}; + } + + auto yield_value(const Yield& y) + { + result_ = y; + return yield_input<Input>{input_, + std::exchange(awaited_from, noop_coroutine())}; + } + + void return_void() + { + result_.reset(); + } +}; + +template <typename Return> +struct coro_promise_exchange<void, void, Return> : coro_awaited_from +{ + using result_type = coro_result_t<void, Return>; + + result_type result_; + + void yield_value(); + + void return_value(const Return& r) + { + result_ = r; + } + + void return_value(Return&& r) + { + result_ = std::move(r); + } +}; + +template <> +struct coro_promise_exchange<void, void, void> : coro_awaited_from +{ + void return_void() {} + + void yield_value(); +}; + +template <typename Yield> +struct coro_promise_exchange<Yield, void, void> : coro_awaited_from +{ + using result_type = coro_result_t<Yield, void>; + + result_type result_; + + auto yield_value(const Yield& y) + { + result_ = y; + return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; + } + + auto yield_value(Yield&& y) + { + result_ = std::move(y); + return yield_input<void>{std::exchange(awaited_from, noop_coroutine())}; + } + + void return_void() + { + result_.reset(); + } +}; + +template <typename Yield, typename Return, + typename Executor, typename Allocator> +struct coro_promise final : + coro_promise_allocator<Allocator>, + coro_promise_error<coro_traits<Yield, Return, Executor>::is_noexcept>, + coro_promise_exchange< + typename coro_traits<Yield, Return, Executor>::yield_type, + typename coro_traits<Yield, Return, Executor>::input_type, + typename coro_traits<Yield, Return, Executor>::return_type> +{ + using coro_type = coro<Yield, Return, Executor, Allocator>; + + auto handle() + { + return coroutine_handle<coro_promise>::from_promise(this); + } + + using executor_type = Executor; + + executor_type executor_; + + std::optional<coro_cancellation_source> cancel_source; + coro_cancellation_source * cancel; + + using cancellation_slot_type = asio::cancellation_slot; + + cancellation_slot_type get_cancellation_slot() const noexcept + { + return cancel ? cancel->slot : cancellation_slot_type{}; + } + + using allocator_type = + typename std::allocator_traits<associated_allocator_t<Executor>>:: + template rebind_alloc<std::byte>; + using traits = coro_traits<Yield, Return, Executor>; + + using input_type = typename traits::input_type; + using yield_type = typename traits::yield_type; + using return_type = typename traits::return_type; + using error_type = typename traits::error_type; + using result_type = typename traits::result_type; + constexpr static bool is_noexcept = traits::is_noexcept; + + auto get_executor() const -> Executor + { + return executor_; + } + + auto get_handle() + { + return coroutine_handle<coro_promise>::from_promise(*this); + } + + template <typename... Args> + coro_promise(Executor executor, Args&&... args) noexcept + : coro_promise_allocator<Allocator>( + executor, std::forward<Args>(args)...), + executor_(std::move(executor)) + { + } + + template <typename First, typename... Args> + coro_promise(First&& f, Executor executor, Args&&... args) noexcept + : coro_promise_allocator<Allocator>( + f, executor, std::forward<Args>(args)...), + executor_(std::move(executor)) + { + } + + template <typename First, detail::execution_context Context, typename... Args> + coro_promise(First&& f, Context&& ctx, Args&&... args) noexcept + : coro_promise_allocator<Allocator>( + f, ctx, std::forward<Args>(args)...), + executor_(ctx.get_executor()) + { + } + + template <detail::execution_context Context, typename... Args> + coro_promise(Context&& ctx, Args&&... args) noexcept + : coro_promise_allocator<Allocator>( + ctx, std::forward<Args>(args)...), + executor_(ctx.get_executor()) + { + } + + auto get_return_object() + { + return coro<Yield, Return, Executor, Allocator>{this}; + } + + auto initial_suspend() noexcept + { + return suspend_always{}; + } + + using coro_promise_exchange< + typename coro_traits<Yield, Return, Executor>::yield_type, + typename coro_traits<Yield, Return, Executor>::input_type, + typename coro_traits<Yield, Return, Executor>::return_type>::yield_value; + + auto await_transform(this_coro::executor_t) const + { + struct exec_helper + { + const executor_type& value; + + constexpr static bool await_ready() noexcept + { + return true; + } + + constexpr static void await_suspend(coroutine_handle<>) noexcept + { + } + + executor_type await_resume() const noexcept + { + return value; + } + }; + + return exec_helper{executor_}; + } + + auto await_transform(this_coro::cancellation_state_t) const + { + struct exec_helper + { + const asio::cancellation_state& value; + + constexpr static bool await_ready() noexcept + { + return true; + } + + constexpr static void await_suspend(coroutine_handle<>) noexcept + { + } + + asio::cancellation_state await_resume() const noexcept + { + return value; + } + }; + assert(cancel); + return exec_helper{cancel->state}; + } + + // This await transformation resets the associated cancellation state. + auto await_transform(this_coro::reset_cancellation_state_0_t) noexcept + { + struct result + { + detail::coro_cancellation_source * src_; + + bool await_ready() const noexcept + { + return true; + } + + void await_suspend(coroutine_handle<void>) noexcept + { + } + + auto await_resume() const + { + return src_->reset_cancellation_state(); + } + }; + + return result{cancel}; + } + + // This await transformation resets the associated cancellation state. + template <typename Filter> + auto await_transform( + this_coro::reset_cancellation_state_1_t<Filter> reset) noexcept + { + struct result + { + detail::coro_cancellation_source* src_; + Filter filter_; + + bool await_ready() const noexcept + { + return true; + } + + void await_suspend(coroutine_handle<void>) noexcept + { + } + + auto await_resume() + { + return src_->reset_cancellation_state( + static_cast<Filter&&>(filter_)); + } + }; + + return result{cancel, static_cast<Filter&&>(reset.filter)}; + } + + // This await transformation resets the associated cancellation state. + template <typename InFilter, typename OutFilter> + auto await_transform( + this_coro::reset_cancellation_state_2_t<InFilter, OutFilter> reset) + noexcept + { + struct result + { + detail::coro_cancellation_source* src_; + InFilter in_filter_; + OutFilter out_filter_; + + bool await_ready() const noexcept + { + return true; + } + + void await_suspend(coroutine_handle<void>) noexcept + { + } + + auto await_resume() + { + return src_->reset_cancellation_state( + static_cast<InFilter&&>(in_filter_), + static_cast<OutFilter&&>(out_filter_)); + } + }; + + return result{cancel, + static_cast<InFilter&&>(reset.in_filter), + static_cast<OutFilter&&>(reset.out_filter)}; + } + + // This await transformation determines whether cancellation is propagated as + // an exception. + auto await_transform(this_coro::throw_if_cancelled_0_t) noexcept + requires (!is_noexcept) + { + struct result + { + detail::coro_cancellation_source* src_; + + bool await_ready() const noexcept + { + return true; + } + + void await_suspend(coroutine_handle<void>) noexcept + { + } + + auto await_resume() + { + return src_->throw_if_cancelled(); + } + }; + + return result{cancel}; + } + + // This await transformation sets whether cancellation is propagated as an + // exception. + auto await_transform( + this_coro::throw_if_cancelled_1_t throw_if_cancelled) noexcept + requires (!is_noexcept) + { + struct result + { + detail::coro_cancellation_source* src_; + bool value_; + + bool await_ready() const noexcept + { + return true; + } + + void await_suspend(coroutine_handle<void>) noexcept + { + } + + auto await_resume() + { + src_->throw_if_cancelled(value_); + } + }; + + return result{cancel, throw_if_cancelled.value}; + } + + template <typename Yield_, typename Return_, + typename Executor_, typename Allocator_> + auto await_transform(coro<Yield_, Return_, Executor_, Allocator_>& kr) + -> decltype(auto) + { + return kr; + } + + template <typename Yield_, typename Return_, + typename Executor_, typename Allocator_> + auto await_transform(coro<Yield_, Return_, Executor_, Allocator_>&& kr) + { + return std::move(kr); + } + + template <typename T_, typename Coroutine > + auto await_transform(coro_with_arg<T_, Coroutine>&& kr) -> decltype(auto) + { + return std::move(kr); + } + + template <typename T_> + requires requires(T_ t) {{ t.async_wait(deferred) }; } + auto await_transform(T_& t) -> decltype(auto) + { + return await_transform(t.async_wait(deferred)); + } + + template <typename Op> + auto await_transform(Op&& op, + constraint_t<is_async_operation<Op>::value> = 0) + { + if ((cancel->state.cancelled() != cancellation_type::none) + && cancel->throw_if_cancelled_) + { + asio::detail::throw_error( + asio::error::operation_aborted, "coro-cancelled"); + } + using signature = completion_signature_of_t<Op>; + using result_type = detail::coro_completion_handler_type_t<signature>; + using handler_type = + typename detail::coro_completion_handler_type<signature>::template + completion_handler<coro_promise>; + + struct aw_t + { + Op op; + std::optional<result_type> result; + + constexpr static bool await_ready() + { + return false; + } + + void await_suspend(coroutine_handle<coro_promise> h) + { + std::move(op)(handler_type{h, result}); + } + + auto await_resume() + { + if constexpr (is_noexcept) + { + if constexpr (std::tuple_size_v<result_type> == 0u) + return; + else if constexpr (std::tuple_size_v<result_type> == 1u) + return std::get<0>(std::move(result).value()); + else + return std::move(result).value(); + } + else + return detail::coro_interpret_result(std::move(result).value()); + } + }; + + return aw_t{std::move(op), {}}; + } +}; + +} // namespace detail + +template <typename Yield, typename Return, + typename Executor, typename Allocator> +struct coro<Yield, Return, Executor, Allocator>::awaitable_t +{ + coro& coro_; + + constexpr static bool await_ready() { return false; } + + template <typename Y, typename R, typename E, typename A> + auto await_suspend( + detail::coroutine_handle<detail::coro_promise<Y, R, E, A>> h) + -> detail::coroutine_handle<> + { + auto& hp = h.promise(); + + if constexpr (!detail::coro_promise<Y, R, E, A>::is_noexcept) + { + if ((hp.cancel->state.cancelled() != cancellation_type::none) + && hp.cancel->throw_if_cancelled_) + { + asio::detail::throw_error( + asio::error::operation_aborted, "coro-cancelled"); + } + } + + if (hp.get_executor() == coro_.get_executor()) + { + coro_.coro_->awaited_from = h; + coro_.coro_->cancel = hp.cancel; + coro_.coro_->reset_error(); + + return coro_.coro_->get_handle(); + } + else + { + coro_.coro_->awaited_from = detail::dispatch_coroutine( + asio::prefer(hp.get_executor(), + execution::outstanding_work.tracked), + [h]() mutable + { + h.resume(); + }).handle; + + coro_.coro_->reset_error(); + + struct cancel_handler + { + std::shared_ptr<std::pair<cancellation_signal, + detail::coro_cancellation_source>> st = std::make_shared< + std::pair<cancellation_signal, detail::coro_cancellation_source>>(); + + cancel_handler(E e, coro& coro) : e(e), coro_(coro.coro_) + { + st->second.state = cancellation_state( + st->second.slot = st->first.slot()); + } + + E e; + typename coro::promise_type* coro_; + + void operator()(cancellation_type ct) + { + asio::dispatch(e, + [ct, st = st]() mutable + { + auto & [sig, state] = *st; + sig.emit(ct); + }); + } + }; + + if (hp.cancel->state.slot().is_connected()) + { + hp.cancel->state.slot().template emplace<cancel_handler>( + coro_.get_executor(), coro_); + } + + auto hh = detail::coroutine_handle< + detail::coro_promise<Yield, Return, Executor, Allocator>>::from_promise( + *coro_.coro_); + + return detail::dispatch_coroutine( + coro_.coro_->get_executor(), + [hh]() mutable { hh.resume(); }).handle; + } + } + + auto await_resume() -> result_type + { + coro_.coro_->cancel = nullptr; + coro_.coro_->rethrow_if(); + if constexpr (!std::is_void_v<result_type>) + return std::move(coro_.coro_->result_); + } +}; + +template <typename Yield, typename Return, + typename Executor, typename Allocator> +struct coro<Yield, Return, Executor, Allocator>::initiate_async_resume +{ + typedef Executor executor_type; + typedef Allocator allocator_type; + typedef asio::cancellation_slot cancellation_slot_type; + + explicit initiate_async_resume(coro* self) + : coro_(self->coro_) + { + } + + executor_type get_executor() const noexcept + { + return coro_->get_executor(); + } + + allocator_type get_allocator() const noexcept + { + return coro_->get_allocator(); + } + + template <typename E, typename WaitHandler> + auto handle(E exec, WaitHandler&& handler, + std::true_type /* error is noexcept */, + std::true_type /* result is void */) //noexcept + { + return [this, the_coro = coro_, + h = std::forward<WaitHandler>(handler), + exec = std::move(exec)]() mutable + { + assert(the_coro); + + auto ch = detail::coroutine_handle<promise_type>::from_promise(*the_coro); + assert(ch && !ch.done()); + + the_coro->awaited_from = post_coroutine(std::move(exec), std::move(h)); + the_coro->reset_error(); + ch.resume(); + }; + } + + template <typename E, typename WaitHandler> + requires (!std::is_void_v<result_type>) + auto handle(E exec, WaitHandler&& handler, + std::true_type /* error is noexcept */, + std::false_type /* result is void */) //noexcept + { + return [the_coro = coro_, + h = std::forward<WaitHandler>(handler), + exec = std::move(exec)]() mutable + { + assert(the_coro); + + auto ch = detail::coroutine_handle<promise_type>::from_promise(*the_coro); + assert(ch && !ch.done()); + + the_coro->awaited_from = detail::post_coroutine( + exec, std::move(h), the_coro->result_).handle; + the_coro->reset_error(); + ch.resume(); + }; + } + + template <typename E, typename WaitHandler> + auto handle(E exec, WaitHandler&& handler, + std::false_type /* error is noexcept */, + std::true_type /* result is void */) + { + return [the_coro = coro_, + h = std::forward<WaitHandler>(handler), + exec = std::move(exec)]() mutable + { + if (!the_coro) + return asio::post(exec, + asio::append(std::move(h), + detail::coro_error<error_type>::invalid())); + + auto ch = detail::coroutine_handle<promise_type>::from_promise(*the_coro); + if (!ch) + return asio::post(exec, + asio::append(std::move(h), + detail::coro_error<error_type>::invalid())); + else if (ch.done()) + return asio::post(exec, + asio::append(std::move(h), + detail::coro_error<error_type>::done())); + else + { + the_coro->awaited_from = detail::post_coroutine( + exec, std::move(h), the_coro->error_).handle; + the_coro->reset_error(); + ch.resume(); + } + }; + } + + template <typename E, typename WaitHandler> + auto handle(E exec, WaitHandler&& handler, + std::false_type /* error is noexcept */, + std::false_type /* result is void */) + { + return [the_coro = coro_, + h = std::forward<WaitHandler>(handler), + exec = std::move(exec)]() mutable + { + if (!the_coro) + return asio::post(exec, + asio::append(std::move(h), + detail::coro_error<error_type>::invalid(), result_type{})); + + auto ch = + detail::coroutine_handle<promise_type>::from_promise(*the_coro); + if (!ch) + return asio::post(exec, + asio::append(std::move(h), + detail::coro_error<error_type>::invalid(), result_type{})); + else if (ch.done()) + return asio::post(exec, + asio::append(std::move(h), + detail::coro_error<error_type>::done(), result_type{})); + else + { + the_coro->awaited_from = detail::post_coroutine( + exec, std::move(h), the_coro->error_, the_coro->result_).handle; + the_coro->reset_error(); + ch.resume(); + } + }; + } + + template <typename WaitHandler> + void operator()(WaitHandler&& handler) + { + const auto exec = asio::prefer( + get_associated_executor(handler, get_executor()), + execution::outstanding_work.tracked); + + coro_->cancel = &coro_->cancel_source.emplace(); + coro_->cancel->state = cancellation_state( + coro_->cancel->slot = get_associated_cancellation_slot(handler)); + asio::dispatch(get_executor(), + handle(exec, std::forward<WaitHandler>(handler), + std::integral_constant<bool, is_noexcept>{}, + std::is_void<result_type>{})); + } + + template <typename WaitHandler, typename Input> + void operator()(WaitHandler&& handler, Input&& input) + { + const auto exec = asio::prefer( + get_associated_executor(handler, get_executor()), + execution::outstanding_work.tracked); + + coro_->cancel = &coro_->cancel_source.emplace(); + coro_->cancel->state = cancellation_state( + coro_->cancel->slot = get_associated_cancellation_slot(handler)); + asio::dispatch(get_executor(), + [h = handle(exec, std::forward<WaitHandler>(handler), + std::integral_constant<bool, is_noexcept>{}, + std::is_void<result_type>{}), + in = std::forward<Input>(input), the_coro = coro_]() mutable + { + the_coro->input_ = std::move(in); + std::move(h)(); + }); + } + +private: + typename coro::promise_type* coro_; +}; + +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_IMPL_CORO_HPP diff --git a/3rdparty/asio/include/asio/experimental/impl/deferred.hpp b/3rdparty/asio/include/asio/experimental/impl/deferred.hpp deleted file mode 100644 index e9b9b29fa2f..00000000000 --- a/3rdparty/asio/include/asio/experimental/impl/deferred.hpp +++ /dev/null @@ -1,104 +0,0 @@ -// -// experimental/impl/deferred.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_EXPERIMENTAL_IMPL_DEFERRED_HPP -#define ASIO_EXPERIMENTAL_IMPL_DEFERRED_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/push_options.hpp" - -namespace asio { - -#if !defined(GENERATING_DOCUMENTATION) - -template <typename R, typename... Args> -class async_result< - experimental::detail::deferred_signature_probe, R(Args...)> -{ -public: - typedef experimental::detail::deferred_signature_probe_result<void(Args...)> - return_type; - - template <typename Initiation, typename... InitArgs> - static return_type initiate( - ASIO_MOVE_ARG(Initiation), - experimental::detail::deferred_signature_probe, - ASIO_MOVE_ARG(InitArgs)...) - { - return return_type{}; - } -}; - -template <typename Signature> -class async_result<experimental::deferred_t, Signature> -{ -public: - template <typename Initiation, typename... InitArgs> - static experimental::deferred_async_operation< - Signature, Initiation, InitArgs...> - initiate(ASIO_MOVE_ARG(Initiation) initiation, - experimental::deferred_t, ASIO_MOVE_ARG(InitArgs)... args) - { - return experimental::deferred_async_operation< - Signature, Initiation, InitArgs...>( - experimental::deferred_init_tag{}, - ASIO_MOVE_CAST(Initiation)(initiation), - ASIO_MOVE_CAST(InitArgs)(args)...); - } -}; - -template <typename Function, typename R, typename... Args> -class async_result< - experimental::deferred_function<Function>, R(Args...)> -{ -public: - template <typename Initiation, typename... InitArgs> - static auto initiate(ASIO_MOVE_ARG(Initiation) initiation, - experimental::deferred_function<Function> token, - ASIO_MOVE_ARG(InitArgs)... init_args) - { - return experimental::deferred_sequence< - experimental::deferred_async_operation< - R(Args...), Initiation, InitArgs...>, - Function>(experimental::deferred_init_tag{}, - experimental::deferred_async_operation< - R(Args...), Initiation, InitArgs...>( - experimental::deferred_init_tag{}, - ASIO_MOVE_CAST(Initiation)(initiation), - ASIO_MOVE_CAST(InitArgs)(init_args)...), - ASIO_MOVE_CAST(Function)(token.function_)); - } -}; - -template <template <typename, typename> class Associator, - typename Handler, typename Tail, typename DefaultCandidate> -struct associator<Associator, - experimental::detail::deferred_sequence_handler<Handler, Tail>, - DefaultCandidate> - : Associator<Handler, DefaultCandidate> -{ - static typename Associator<Handler, DefaultCandidate>::type get( - const experimental::detail::deferred_sequence_handler<Handler, Tail>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT - { - return Associator<Handler, DefaultCandidate>::get(h.handler_, c); - } -}; - -#endif // !defined(GENERATING_DOCUMENTATION) - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_EXPERIMENTAL_IMPL_DEFERRED_HPP diff --git a/3rdparty/asio/include/asio/experimental/impl/parallel_group.hpp b/3rdparty/asio/include/asio/experimental/impl/parallel_group.hpp index e1cfc1e2c98..75e8a151876 100644 --- a/3rdparty/asio/include/asio/experimental/impl/parallel_group.hpp +++ b/3rdparty/asio/include/asio/experimental/impl/parallel_group.hpp @@ -2,7 +2,7 @@ // experimental/impl/parallel_group.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,6 +17,7 @@ #include "asio/detail/config.hpp" #include <atomic> +#include <deque> #include <memory> #include <new> #include <tuple> @@ -83,12 +84,12 @@ private: template <typename Handler, typename... Ops> struct parallel_group_completion_handler { - typedef typename decay< - typename prefer_result< - typename associated_executor<Handler>::type, + typedef decay_t< + prefer_result_t< + associated_executor_t<Handler>, execution::outstanding_work_t::tracked_t - >::type - >::type executor_type; + > + > executor_type; parallel_group_completion_handler(Handler&& h) : handler_(std::move(h)), @@ -106,11 +107,11 @@ struct parallel_group_completion_handler void operator()() { - this->invoke(std::make_index_sequence<sizeof...(Ops)>()); + this->invoke(asio::detail::make_index_sequence<sizeof...(Ops)>()); } template <std::size_t... I> - void invoke(std::index_sequence<I...>) + void invoke(asio::detail::index_sequence<I...>) { this->invoke(std::tuple_cat(std::move(std::get<I>(args_).get())...)); } @@ -118,11 +119,13 @@ struct parallel_group_completion_handler template <typename... Args> void invoke(std::tuple<Args...>&& args) { - this->invoke(std::move(args), std::make_index_sequence<sizeof...(Args)>()); + this->invoke(std::move(args), + asio::detail::index_sequence_for<Args...>()); } template <typename... Args, std::size_t... I> - void invoke(std::tuple<Args...>&& args, std::index_sequence<I...>) + void invoke(std::tuple<Args...>&& args, + asio::detail::index_sequence<I...>) { std::move(handler_)(completion_order_, std::move(std::get<I>(args))...); } @@ -133,7 +136,7 @@ struct parallel_group_completion_handler std::tuple< parallel_group_op_result< typename parallel_op_signature_as_tuple< - typename parallel_op_signature<Ops>::type + completion_signature_of_t<Ops> >::type >... > args_{}; @@ -186,7 +189,7 @@ struct parallel_group_op_handler typedef asio::cancellation_slot cancellation_slot_type; parallel_group_op_handler( - std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state) + std::shared_ptr<parallel_group_state<Condition, Handler, Ops...>> state) : state_(std::move(state)) { } @@ -227,7 +230,7 @@ struct parallel_group_op_handler asio::dispatch(std::move(state_->handler_)); } - std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state_; + std::shared_ptr<parallel_group_state<Condition, Handler, Ops...>> state_; }; // Handler for an individual operation within the parallel group that has an @@ -242,7 +245,7 @@ struct parallel_group_op_handler_with_executor : typedef Executor executor_type; parallel_group_op_handler_with_executor( - std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state, + std::shared_ptr<parallel_group_state<Condition, Handler, Ops...>> state, executor_type ex) : parallel_group_op_handler<I, Condition, Handler, Ops...>(std::move(state)) { @@ -266,7 +269,7 @@ struct parallel_group_op_handler_with_executor : { cancel_proxy( std::shared_ptr<parallel_group_state< - Condition, Handler, Ops...> > state, + Condition, Handler, Ops...>> state, executor_type ex) : state_(std::move(state)), executor_(std::move(ex)) @@ -283,7 +286,7 @@ struct parallel_group_op_handler_with_executor : } } - std::weak_ptr<parallel_group_state<Condition, Handler, Ops...> > state_; + std::weak_ptr<parallel_group_state<Condition, Handler, Ops...>> state_; asio::cancellation_signal signal_; executor_type executor_; }; @@ -298,9 +301,9 @@ struct parallel_group_op_launcher template <typename Condition, typename Handler, typename... Ops> static void launch(Op& op, const std::shared_ptr<parallel_group_state< - Condition, Handler, Ops...> >& state) + Condition, Handler, Ops...>>& state) { - typedef typename associated_executor<Op>::type ex_type; + typedef associated_executor_t<Op> ex_type; ex_type ex = asio::get_associated_executor(op); std::move(op)( parallel_group_op_handler_with_executor<ex_type, I, @@ -311,18 +314,18 @@ struct parallel_group_op_launcher // Specialised launcher for operations that specify no executor. template <std::size_t I, typename Op> struct parallel_group_op_launcher<I, Op, - typename enable_if< + enable_if_t< is_same< typename associated_executor< Op>::asio_associated_executor_is_unspecialised, void >::value - >::type> + >> { template <typename Condition, typename Handler, typename... Ops> static void launch(Op& op, const std::shared_ptr<parallel_group_state< - Condition, Handler, Ops...> >& state) + Condition, Handler, Ops...>>& state) { std::move(op)( parallel_group_op_handler<I, Condition, Handler, Ops...>(state)); @@ -333,7 +336,7 @@ template <typename Condition, typename Handler, typename... Ops> struct parallel_group_cancellation_handler { parallel_group_cancellation_handler( - std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state) + std::shared_ptr<parallel_group_state<Condition, Handler, Ops...>> state) : state_(std::move(state)) { } @@ -344,22 +347,23 @@ struct parallel_group_cancellation_handler // yet completed and requested cancellation, emit a signal for each // operation in the group. if (cancel_type != cancellation_type::none) - if (state_->cancellations_requested_++ == 0) - for (std::size_t i = 0; i < sizeof...(Ops); ++i) - state_->cancellation_signals_[i].emit(cancel_type); + if (auto state = state_.lock()) + if (state->cancellations_requested_++ == 0) + for (std::size_t i = 0; i < sizeof...(Ops); ++i) + state->cancellation_signals_[i].emit(cancel_type); } - std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state_; + std::weak_ptr<parallel_group_state<Condition, Handler, Ops...>> state_; }; template <typename Condition, typename Handler, typename... Ops, std::size_t... I> void parallel_group_launch(Condition cancellation_condition, Handler handler, - std::tuple<Ops...>& ops, std::index_sequence<I...>) + std::tuple<Ops...>& ops, asio::detail::index_sequence<I...>) { // Get the user's completion handler's cancellation slot, so that we can allow // cancellation of the entire group. - typename associated_cancellation_slot<Handler>::type slot + associated_cancellation_slot_t<Handler> slot = asio::get_associated_cancellation_slot(handler); // Create the shared state for the operation. @@ -386,29 +390,348 @@ void parallel_group_launch(Condition cancellation_condition, Handler handler, if (slot.is_connected()) slot.template emplace< parallel_group_cancellation_handler< - Condition, Handler, Ops...> >(state); + Condition, Handler, Ops...>>(state); } -} // namespace detail -} // namespace experimental +// Proxy completion handler for the ranged group of parallel operatations. +// Unpacks and recombines the individual operations' results, and invokes the +// user's completion handler. +template <typename Handler, typename Op, typename Allocator> +struct ranged_parallel_group_completion_handler +{ + typedef decay_t< + prefer_result_t< + associated_executor_t<Handler>, + execution::outstanding_work_t::tracked_t + > + > executor_type; + + typedef typename parallel_op_signature_as_tuple< + completion_signature_of_t<Op> + >::type op_tuple_type; + + typedef parallel_group_op_result<op_tuple_type> op_result_type; + + ranged_parallel_group_completion_handler(Handler&& h, + std::size_t size, const Allocator& allocator) + : handler_(std::move(h)), + executor_( + asio::prefer( + asio::get_associated_executor(handler_), + execution::outstanding_work.tracked)), + allocator_(allocator), + completion_order_(size, 0, + ASIO_REBIND_ALLOC(Allocator, std::size_t)(allocator)), + args_(ASIO_REBIND_ALLOC(Allocator, op_result_type)(allocator)) + { + for (std::size_t i = 0; i < size; ++i) + args_.emplace_back(); + } + + executor_type get_executor() const noexcept + { + return executor_; + } + + void operator()() + { + this->invoke( + asio::detail::make_index_sequence< + std::tuple_size<op_tuple_type>::value>()); + } + + template <std::size_t... I> + void invoke(asio::detail::index_sequence<I...>) + { + typedef typename parallel_op_signature_as_tuple< + typename ranged_parallel_group_signature< + completion_signature_of_t<Op>, + Allocator + >::raw_type + >::type vectors_type; + + // Construct all result vectors using the supplied allocator. + vectors_type vectors{ + typename std::tuple_element<I, vectors_type>::type( + ASIO_REBIND_ALLOC(Allocator, int)(allocator_))...}; + + // Reserve sufficient space in each of the result vectors. + int reserve_fold[] = { 0, + ( std::get<I>(vectors).reserve(completion_order_.size()), + 0 )... + }; + (void)reserve_fold; + + // Copy the results from all operations into the result vectors. + for (std::size_t idx = 0; idx < completion_order_.size(); ++idx) + { + int pushback_fold[] = { 0, + ( std::get<I>(vectors).push_back( + std::move(std::get<I>(args_[idx].get()))), + 0 )... + }; + (void)pushback_fold; + } + + std::move(handler_)(std::move(completion_order_), + std::move(std::get<I>(vectors))...); + } + + Handler handler_; + executor_type executor_; + Allocator allocator_; + std::vector<std::size_t, + ASIO_REBIND_ALLOC(Allocator, std::size_t)> completion_order_; + std::deque<op_result_type, + ASIO_REBIND_ALLOC(Allocator, op_result_type)> args_; +}; -template <typename R, typename... Args> -class async_result< - experimental::detail::parallel_op_signature_probe, - R(Args...)> +// Shared state for the parallel group. +template <typename Condition, typename Handler, typename Op, typename Allocator> +struct ranged_parallel_group_state { -public: - typedef experimental::detail::parallel_op_signature_probe_result< - void(Args...)> return_type; + ranged_parallel_group_state(Condition&& c, Handler&& h, + std::size_t size, const Allocator& allocator) + : cancellations_requested_(size), + outstanding_(size), + cancellation_signals_( + ASIO_REBIND_ALLOC(Allocator, + asio::cancellation_signal)(allocator)), + cancellation_condition_(std::move(c)), + handler_(std::move(h), size, allocator) + { + for (std::size_t i = 0; i < size; ++i) + cancellation_signals_.emplace_back(); + } + + // The number of operations that have completed so far. Used to determine the + // order of completion. + std::atomic<unsigned int> completed_{0}; + + // The non-none cancellation type that resulted from a cancellation condition. + // Stored here for use by the group's initiating function. + std::atomic<cancellation_type_t> cancel_type_{cancellation_type::none}; + + // The number of cancellations that have been requested, either on completion + // of the operations within the group, or via the cancellation slot for the + // group operation. Initially set to the number of operations to prevent + // cancellation signals from being emitted until after all of the group's + // operations' initiating functions have completed. + std::atomic<unsigned int> cancellations_requested_; - template <typename Initiation, typename... InitArgs> - static return_type initiate(Initiation&&, - experimental::detail::parallel_op_signature_probe, InitArgs&&...) + // The number of operations that are yet to complete. Used to determine when + // it is safe to invoke the user's completion handler. + std::atomic<unsigned int> outstanding_; + + // The cancellation signals for each operation in the group. + std::deque<asio::cancellation_signal, + ASIO_REBIND_ALLOC(Allocator, asio::cancellation_signal)> + cancellation_signals_; + + // The cancellation condition is used to determine whether the results from an + // individual operation warrant a cancellation request for the whole group. + Condition cancellation_condition_; + + // The proxy handler to be invoked once all operations in the group complete. + ranged_parallel_group_completion_handler<Handler, Op, Allocator> handler_; +}; + +// Handler for an individual operation within the parallel group. +template <typename Condition, typename Handler, typename Op, typename Allocator> +struct ranged_parallel_group_op_handler +{ + typedef asio::cancellation_slot cancellation_slot_type; + + ranged_parallel_group_op_handler( + std::shared_ptr<ranged_parallel_group_state< + Condition, Handler, Op, Allocator>> state, + std::size_t idx) + : state_(std::move(state)), + idx_(idx) { - return return_type{}; } + + cancellation_slot_type get_cancellation_slot() const noexcept + { + return state_->cancellation_signals_[idx_].slot(); + } + + template <typename... Args> + void operator()(Args... args) + { + // Capture this operation into the completion order. + state_->handler_.completion_order_[state_->completed_++] = idx_; + + // Determine whether the results of this operation require cancellation of + // the whole group. + cancellation_type_t cancel_type = state_->cancellation_condition_(args...); + + // Capture the result of the operation into the proxy completion handler. + state_->handler_.args_[idx_].emplace(std::move(args)...); + + if (cancel_type != cancellation_type::none) + { + // Save the type for potential use by the group's initiating function. + state_->cancel_type_ = cancel_type; + + // If we are the first operation to request cancellation, emit a signal + // for each operation in the group. + if (state_->cancellations_requested_++ == 0) + for (std::size_t i = 0; i < state_->cancellation_signals_.size(); ++i) + if (i != idx_) + state_->cancellation_signals_[i].emit(cancel_type); + } + + // If this is the last outstanding operation, invoke the user's handler. + if (--state_->outstanding_ == 0) + asio::dispatch(std::move(state_->handler_)); + } + + std::shared_ptr<ranged_parallel_group_state< + Condition, Handler, Op, Allocator>> state_; + std::size_t idx_; }; +// Handler for an individual operation within the parallel group that has an +// explicitly specified executor. +template <typename Executor, typename Condition, + typename Handler, typename Op, typename Allocator> +struct ranged_parallel_group_op_handler_with_executor : + ranged_parallel_group_op_handler<Condition, Handler, Op, Allocator> +{ + typedef ranged_parallel_group_op_handler< + Condition, Handler, Op, Allocator> base_type; + typedef asio::cancellation_slot cancellation_slot_type; + typedef Executor executor_type; + + ranged_parallel_group_op_handler_with_executor( + std::shared_ptr<ranged_parallel_group_state< + Condition, Handler, Op, Allocator>> state, + executor_type ex, std::size_t idx) + : ranged_parallel_group_op_handler<Condition, Handler, Op, Allocator>( + std::move(state), idx) + { + cancel_proxy_ = + &this->state_->cancellation_signals_[idx].slot().template + emplace<cancel_proxy>(this->state_, std::move(ex)); + } + + cancellation_slot_type get_cancellation_slot() const noexcept + { + return cancel_proxy_->signal_.slot(); + } + + executor_type get_executor() const noexcept + { + return cancel_proxy_->executor_; + } + + // Proxy handler that forwards the emitted signal to the correct executor. + struct cancel_proxy + { + cancel_proxy( + std::shared_ptr<ranged_parallel_group_state< + Condition, Handler, Op, Allocator>> state, + executor_type ex) + : state_(std::move(state)), + executor_(std::move(ex)) + { + } + + void operator()(cancellation_type_t type) + { + if (auto state = state_.lock()) + { + asio::cancellation_signal* sig = &signal_; + asio::dispatch(executor_, + [state, sig, type]{ sig->emit(type); }); + } + } + + std::weak_ptr<ranged_parallel_group_state< + Condition, Handler, Op, Allocator>> state_; + asio::cancellation_signal signal_; + executor_type executor_; + }; + + cancel_proxy* cancel_proxy_; +}; + +template <typename Condition, typename Handler, typename Op, typename Allocator> +struct ranged_parallel_group_cancellation_handler +{ + ranged_parallel_group_cancellation_handler( + std::shared_ptr<ranged_parallel_group_state< + Condition, Handler, Op, Allocator>> state) + : state_(std::move(state)) + { + } + + void operator()(cancellation_type_t cancel_type) + { + // If we are the first place to request cancellation, i.e. no operation has + // yet completed and requested cancellation, emit a signal for each + // operation in the group. + if (cancel_type != cancellation_type::none) + if (auto state = state_.lock()) + if (state->cancellations_requested_++ == 0) + for (std::size_t i = 0; i < state->cancellation_signals_.size(); ++i) + state->cancellation_signals_[i].emit(cancel_type); + } + + std::weak_ptr<ranged_parallel_group_state< + Condition, Handler, Op, Allocator>> state_; +}; + +template <typename Condition, typename Handler, + typename Range, typename Allocator> +void ranged_parallel_group_launch(Condition cancellation_condition, + Handler handler, Range&& range, const Allocator& allocator) +{ + // Get the user's completion handler's cancellation slot, so that we can allow + // cancellation of the entire group. + associated_cancellation_slot_t<Handler> slot + = asio::get_associated_cancellation_slot(handler); + + // The type of the asynchronous operation. + typedef decay_t<decltype(*declval<typename Range::iterator>())> op_type; + + // Create the shared state for the operation. + typedef ranged_parallel_group_state<Condition, + Handler, op_type, Allocator> state_type; + std::shared_ptr<state_type> state = std::allocate_shared<state_type>( + asio::detail::recycling_allocator<state_type, + asio::detail::thread_info_base::parallel_group_tag>(), + std::move(cancellation_condition), + std::move(handler), range.size(), allocator); + + std::size_t idx = 0; + for (auto&& op : std::forward<Range>(range)) + { + typedef associated_executor_t<op_type> ex_type; + ex_type ex = asio::get_associated_executor(op); + std::move(op)( + ranged_parallel_group_op_handler_with_executor< + ex_type, Condition, Handler, op_type, Allocator>( + state, std::move(ex), idx++)); + } + + // Check if any of the operations has already requested cancellation, and if + // so, emit a signal for each operation in the group. + if ((state->cancellations_requested_ -= range.size()) > 0) + for (auto& signal : state->cancellation_signals_) + signal.emit(state->cancel_type_); + + // Register a handler with the user's completion handler's cancellation slot. + if (slot.is_connected()) + slot.template emplace< + ranged_parallel_group_cancellation_handler< + Condition, Handler, op_type, Allocator>>(state); +} + +} // namespace detail +} // namespace experimental + template <template <typename, typename> class Associator, typename Handler, typename... Ops, typename DefaultCandidate> struct associator<Associator, @@ -418,8 +741,41 @@ struct associator<Associator, { static typename Associator<Handler, DefaultCandidate>::type get( const experimental::detail::parallel_group_completion_handler< + Handler, Ops...>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const experimental::detail::parallel_group_completion_handler< Handler, Ops...>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) + { + return Associator<Handler, DefaultCandidate>::get(h.handler_, c); + } +}; + +template <template <typename, typename> class Associator, typename Handler, + typename Op, typename Allocator, typename DefaultCandidate> +struct associator<Associator, + experimental::detail::ranged_parallel_group_completion_handler< + Handler, Op, Allocator>, + DefaultCandidate> + : Associator<Handler, DefaultCandidate> +{ + static typename Associator<Handler, DefaultCandidate>::type get( + const experimental::detail::ranged_parallel_group_completion_handler< + Handler, Op, Allocator>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const experimental::detail::ranged_parallel_group_completion_handler< + Handler, Op, Allocator>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } diff --git a/3rdparty/asio/include/asio/experimental/impl/prepend.hpp b/3rdparty/asio/include/asio/experimental/impl/prepend.hpp deleted file mode 100644 index 73978348f7a..00000000000 --- a/3rdparty/asio/include/asio/experimental/impl/prepend.hpp +++ /dev/null @@ -1,217 +0,0 @@ -// -// experimental/impl/prepend.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IMPL_EXPERIMENTAL_PREPEND_HPP -#define ASIO_IMPL_EXPERIMENTAL_PREPEND_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#include "asio/associator.hpp" -#include "asio/async_result.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace experimental { -namespace detail { - -// Class to adapt a prepend_t as a completion handler. -template <typename Handler, typename... Values> -class prepend_handler -{ -public: - typedef void result_type; - - template <typename H> - prepend_handler(ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values) - : handler_(ASIO_MOVE_CAST(H)(handler)), - values_(ASIO_MOVE_CAST(std::tuple<Values...>)(values)) - { - } - - template <typename... Args> - void operator()(ASIO_MOVE_ARG(Args)... args) - { - this->invoke( - std::make_index_sequence<sizeof...(Values)>{}, - ASIO_MOVE_CAST(Args)(args)...); - } - - template <std::size_t... I, typename... Args> - void invoke(std::index_sequence<I...>, ASIO_MOVE_ARG(Args)... args) - { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( - ASIO_MOVE_CAST(Values)(std::get<I>(values_))..., - ASIO_MOVE_CAST(Args)(args)...); - } - -//private: - Handler handler_; - std::tuple<Values...> values_; -}; - -template <typename Handler> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - prepend_handler<Handler>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - prepend_handler<Handler>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> -inline bool asio_handler_is_continuation( - prepend_handler<Handler>* this_handler) -{ - return asio_handler_cont_helpers::is_continuation( - this_handler->handler_); -} - -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - prepend_handler<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - prepend_handler<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Signature, typename... Values> -struct prepend_signature; - -template <typename R, typename... Args, typename... Values> -struct prepend_signature<R(Args...), Values...> -{ - typedef R type(Values..., typename decay<Args>::type...); -}; - -} // namespace detail -} // namespace experimental - -#if !defined(GENERATING_DOCUMENTATION) - -template <typename CompletionToken, typename... Values, typename Signature> -struct async_result< - experimental::prepend_t<CompletionToken, Values...>, Signature> - : async_result<CompletionToken, - typename experimental::detail::prepend_signature< - Signature, Values...>::type> -{ - typedef typename experimental::detail::prepend_signature< - Signature, Values...>::type signature; - - template <typename Initiation> - struct init_wrapper - { - init_wrapper(Initiation init) - : initiation_(ASIO_MOVE_CAST(Initiation)(init)) - { - } - - template <typename Handler, typename... Args> - void operator()( - ASIO_MOVE_ARG(Handler) handler, - std::tuple<Values...> values, - ASIO_MOVE_ARG(Args)... args) - { - ASIO_MOVE_CAST(Initiation)(initiation_)( - experimental::detail::prepend_handler< - typename decay<Handler>::type, Values...>( - ASIO_MOVE_CAST(Handler)(handler), - ASIO_MOVE_CAST(std::tuple<Values...>)(values)), - ASIO_MOVE_CAST(Args)(args)...); - } - - Initiation initiation_; - }; - - template <typename Initiation, typename RawCompletionToken, typename... Args> - static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, signature, - (async_initiate<CompletionToken, signature>( - declval<init_wrapper<typename decay<Initiation>::type> >(), - declval<CompletionToken&>(), - declval<std::tuple<Values...> >(), - declval<ASIO_MOVE_ARG(Args)>()...))) - initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token, - ASIO_MOVE_ARG(Args)... args) - { - return async_initiate<CompletionToken, signature>( - init_wrapper<typename decay<Initiation>::type>( - ASIO_MOVE_CAST(Initiation)(initiation)), - token.token_, - ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_), - ASIO_MOVE_CAST(Args)(args)...); - } -}; - -template <template <typename, typename> class Associator, - typename Handler, typename DefaultCandidate> -struct associator<Associator, - experimental::detail::prepend_handler<Handler>, DefaultCandidate> - : Associator<Handler, DefaultCandidate> -{ - static typename Associator<Handler, DefaultCandidate>::type get( - const experimental::detail::prepend_handler<Handler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT - { - return Associator<Handler, DefaultCandidate>::get(h.handler_, c); - } -}; - -#endif // !defined(GENERATING_DOCUMENTATION) - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IMPL_EXPERIMENTAL_PREPEND_HPP diff --git a/3rdparty/asio/include/asio/experimental/impl/promise.hpp b/3rdparty/asio/include/asio/experimental/impl/promise.hpp index 803b41e1a27..a80cf110baa 100644 --- a/3rdparty/asio/include/asio/experimental/impl/promise.hpp +++ b/3rdparty/asio/include/asio/experimental/impl/promise.hpp @@ -2,8 +2,8 @@ // experimental/impl/promise.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2021 Klemens D. Morgenstern -// (klemens dot morgenstern at gmx dot net) +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -11,61 +11,199 @@ #ifndef ASIO_EXPERIMENTAL_IMPL_PROMISE_HPP #define ASIO_EXPERIMENTAL_IMPL_PROMISE_HPP +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" #include "asio/cancellation_signal.hpp" -#include "asio/experimental/detail/completion_handler_erasure.hpp" +#include "asio/detail/utility.hpp" +#include "asio/error.hpp" +#include "asio/system_error.hpp" #include <tuple> -#include <optional> #include "asio/detail/push_options.hpp" namespace asio { namespace experimental { -template<typename Signature = void(), typename Executor = any_io_executor> +template<typename Signature = void(), + typename Executor = asio::any_io_executor, + typename Allocator = std::allocator<void>> struct promise; namespace detail { -template<typename Signature, typename Executor> +template<typename Signature, typename Executor, typename Allocator> struct promise_impl; -template<typename ... Ts, typename Executor> -struct promise_impl<void(Ts...), Executor> +template<typename... Ts, typename Executor, typename Allocator> +struct promise_impl<void(Ts...), Executor, Allocator> { using result_type = std::tuple<Ts...>; - promise_impl(Executor executor = {}) - : executor(std::move(executor)) + promise_impl(Allocator allocator, Executor executor) + : allocator(std::move(allocator)), executor(std::move(executor)) { } - std::optional<result_type> result; - bool done{false}; - detail::completion_handler_erasure<void(Ts...), Executor> completion; + promise_impl(const promise_impl&) = delete; + + ~promise_impl() + { + if (completion) + this->cancel_(); + + if (done) + reinterpret_cast<result_type*>(&result)->~result_type(); + } + + aligned_storage_t<sizeof(result_type), alignof(result_type)> result; + std::atomic<bool> done{false}; cancellation_signal cancel; + Allocator allocator; Executor executor; -}; -template<typename Signature = void(), typename Executor = any_io_executor> -struct promise_handler; + template<typename Func, std::size_t... Idx> + void apply_impl(Func f, asio::detail::index_sequence<Idx...>) + { + auto& result_type = *reinterpret_cast<promise_impl::result_type*>(&result); + f(std::get<Idx>(std::move(result_type))...); + } + + using allocator_type = Allocator; + allocator_type get_allocator() {return allocator;} + + using executor_type = Executor; + executor_type get_executor() {return executor;} + + template<typename Func> + void apply(Func f) + { + apply_impl(std::forward<Func>(f), + asio::detail::make_index_sequence<sizeof...(Ts)>{}); + } + + struct completion_base + { + virtual void invoke(Ts&&...ts) = 0; + }; + + template<typename Alloc, typename WaitHandler_> + struct completion_impl final : completion_base + { + WaitHandler_ handler; + Alloc allocator; + void invoke(Ts&&... ts) + { + auto h = std::move(handler); + + using alloc_t = typename std::allocator_traits< + typename asio::decay<Alloc>::type>::template + rebind_alloc<completion_impl>; + + alloc_t alloc_{allocator}; + this->~completion_impl(); + std::allocator_traits<alloc_t>::deallocate(alloc_, this, 1u); + std::move(h)(std::forward<Ts>(ts)...); + } + + template<typename Alloc_, typename Handler_> + completion_impl(Alloc_&& alloc, Handler_&& wh) + : handler(std::forward<Handler_>(wh)), + allocator(std::forward<Alloc_>(alloc)) + { + } + }; + + completion_base* completion = nullptr; + typename asio::aligned_storage<sizeof(void*) * 4, + alignof(completion_base)>::type completion_opt; + + template<typename Alloc, typename Handler> + void set_completion(Alloc&& alloc, Handler&& handler) + { + if (completion) + cancel_(); + + using impl_t = completion_impl< + typename asio::decay<Alloc>::type, Handler>; + using alloc_t = typename std::allocator_traits< + typename asio::decay<Alloc>::type>::template rebind_alloc<impl_t>; + + alloc_t alloc_{alloc}; + auto p = std::allocator_traits<alloc_t>::allocate(alloc_, 1u); + completion = new (p) impl_t(std::forward<Alloc>(alloc), + std::forward<Handler>(handler)); + } + + template<typename... T_> + void complete(T_&&... ts) + { + assert(completion); + std::exchange(completion, nullptr)->invoke(std::forward<T_>(ts)...); + } + + template<std::size_t... Idx> + void complete_with_result_impl(asio::detail::index_sequence<Idx...>) + { + auto& result_type = *reinterpret_cast<promise_impl::result_type*>(&result); + this->complete(std::get<Idx>(std::move(result_type))...); + } -template<typename Signature, typename Executor> + void complete_with_result() + { + complete_with_result_impl( + asio::detail::make_index_sequence<sizeof...(Ts)>{}); + } + + template<typename... T_> + void cancel_impl_(std::exception_ptr*, T_*...) + { + complete( + std::make_exception_ptr( + asio::system_error( + asio::error::operation_aborted)), + T_{}...); + } + + template<typename... T_> + void cancel_impl_(asio::error_code*, T_*...) + { + complete(asio::error::operation_aborted, T_{}...); + } + + template<typename... T_> + void cancel_impl_(T_*...) + { + complete(T_{}...); + } + + void cancel_() + { + cancel_impl_(static_cast<Ts*>(nullptr)...); + } +}; + +template<typename Signature = void(), + typename Executor = asio::any_io_executor, + typename Allocator = any_io_executor> struct promise_handler; -template<typename ... Ts, typename Executor> -struct promise_handler<void(Ts...), Executor> +template<typename... Ts, typename Executor, typename Allocator> +struct promise_handler<void(Ts...), Executor, Allocator> { - using promise_type = promise<void(Ts...), Executor>; + using promise_type = promise<void(Ts...), Executor, Allocator>; - promise_handler(Executor executor) // get_associated_allocator(exec) - : impl_{ - std::allocate_shared<promise_impl<void(Ts...), Executor>>( - get_associated_allocator(executor))} + promise_handler( + Allocator allocator, Executor executor) // get_associated_allocator(exec) + : impl_( + std::allocate_shared<promise_impl<void(Ts...), Executor, Allocator>>( + allocator, allocator, executor)) { - impl_->executor = std::move(executor); } - std::shared_ptr<promise_impl<void(Ts...), Executor>> impl_; + std::shared_ptr<promise_impl<void(Ts...), Executor, Allocator>> impl_; using cancellation_slot_type = cancellation_slot; @@ -74,18 +212,37 @@ struct promise_handler<void(Ts...), Executor> return impl_->cancel.slot(); } - auto make_promise() -> promise<void(Ts...), Executor> + using allocator_type = Allocator; + + allocator_type get_allocator() const noexcept + { + return impl_->get_allocator(); + } + + using executor_type = Executor; + + Executor get_executor() const noexcept { - return {impl_}; + return impl_->get_executor(); + } + + auto make_promise() -> promise<void(Ts...), executor_type, allocator_type> + { + return promise<void(Ts...), executor_type, allocator_type>{impl_}; } void operator()(std::remove_reference_t<Ts>... ts) { assert(impl_); - impl_->result.emplace(std::move(ts)...); + + using result_type = typename promise_impl< + void(Ts...), allocator_type, executor_type>::result_type ; + + new (&impl_->result) result_type(std::move(ts)...); impl_->done = true; - if (auto f = std::exchange(impl_->completion, nullptr); f != nullptr) - std::apply(std::move(f), std::move(*impl_->result)); + + if (impl_->completion) + impl_->complete_with_result(); } }; diff --git a/3rdparty/asio/include/asio/experimental/impl/use_coro.hpp b/3rdparty/asio/include/asio/experimental/impl/use_coro.hpp new file mode 100644 index 00000000000..ab5a2e68959 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/impl/use_coro.hpp @@ -0,0 +1,214 @@ +// +// experimental/impl/use_coro.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP +#define ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/deferred.hpp" +#include "asio/experimental/coro.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename Allocator, typename R> +struct async_result<experimental::use_coro_t<Allocator>, R()> +{ + template <typename Initiation, typename... InitArgs> + static auto initiate_impl(Initiation initiation, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void() noexcept, void, + asio::associated_executor_t<Initiation>, Allocator> + { + co_await deferred_async_operation<R(), Initiation, InitArgs...>( + deferred_init_tag{}, std::move(initiation), std::move(args)...); + } + + template <typename... InitArgs> + static auto initiate_impl(asio::detail::initiation_archetype<R()>, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void(), void, + asio::any_io_executor, Allocator>; + + template <typename Initiation, typename... InitArgs> + static auto initiate(Initiation initiation, + experimental::use_coro_t<Allocator> tk, InitArgs&&... args) + { + return initiate_impl(std::move(initiation), std::allocator_arg, + tk.get_allocator(), std::forward<InitArgs>(args)...); + } +}; + +template <typename Allocator, typename R> +struct async_result< + experimental::use_coro_t<Allocator>, R(asio::error_code)> +{ + template <typename Initiation, typename... InitArgs> + static auto initiate_impl(Initiation initiation, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void() noexcept, void, + asio::associated_executor_t<Initiation>, Allocator> + { + co_await deferred_async_operation< + R(asio::error_code), Initiation, InitArgs...>( + deferred_init_tag{}, std::move(initiation), std::move(args)...); + } + + template <typename... InitArgs> + static auto initiate_impl( + asio::detail::initiation_archetype<R(asio::error_code)>, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void(), void, + asio::any_io_executor, Allocator>; + + template <typename Initiation, typename... InitArgs> + static auto initiate(Initiation initiation, + experimental::use_coro_t<Allocator> tk, InitArgs&&... args) + { + return initiate_impl(std::move(initiation), std::allocator_arg, + tk.get_allocator(), std::forward<InitArgs>(args)...); + } +}; + +template <typename Allocator, typename R> +struct async_result< + experimental::use_coro_t<Allocator>, R(std::exception_ptr)> +{ + template <typename Initiation, typename... InitArgs> + static auto initiate_impl(Initiation initiation, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void(), void, + asio::associated_executor_t<Initiation>, Allocator> + { + co_await deferred_async_operation< + R(std::exception_ptr), Initiation, InitArgs...>( + deferred_init_tag{}, std::move(initiation), std::move(args)...); + } + + template <typename... InitArgs> + static auto initiate_impl( + asio::detail::initiation_archetype<R(std::exception_ptr)>, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void(), void, + asio::any_io_executor, Allocator>; + + template <typename Initiation, typename... InitArgs> + static auto initiate(Initiation initiation, + experimental::use_coro_t<Allocator> tk, InitArgs&&... args) + { + return initiate_impl(std::move(initiation), std::allocator_arg, + tk.get_allocator(), std::forward<InitArgs>(args)...); + } +}; + +template <typename Allocator, typename R, typename T> +struct async_result<experimental::use_coro_t<Allocator>, R(T)> +{ + + template <typename Initiation, typename... InitArgs> + static auto initiate_impl(Initiation initiation, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void() noexcept, T, + asio::associated_executor_t<Initiation>, Allocator> + { + co_return co_await deferred_async_operation<R(T), Initiation, InitArgs...>( + deferred_init_tag{}, std::move(initiation), std::move(args)...); + } + + template <typename... InitArgs> + static auto initiate_impl(asio::detail::initiation_archetype<R(T)>, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void() noexcept, T, + asio::any_io_executor, Allocator>; + + template <typename Initiation, typename... InitArgs> + static auto initiate(Initiation initiation, + experimental::use_coro_t<Allocator> tk, InitArgs&&... args) + { + return initiate_impl(std::move(initiation), std::allocator_arg, + tk.get_allocator(), std::forward<InitArgs>(args)...); + } +}; + +template <typename Allocator, typename R, typename T> +struct async_result< + experimental::use_coro_t<Allocator>, R(asio::error_code, T)> +{ + template <typename Initiation, typename... InitArgs> + static auto initiate_impl(Initiation initiation, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void(), T, + asio::associated_executor_t<Initiation>, Allocator> + { + co_return co_await deferred_async_operation< + R(asio::error_code, T), Initiation, InitArgs...>( + deferred_init_tag{}, std::move(initiation), std::move(args)...); + } + + template <typename... InitArgs> + static auto initiate_impl( + asio::detail::initiation_archetype< + R(asio::error_code, T)>, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void(), T, asio::any_io_executor, Allocator>; + + template <typename Initiation, typename... InitArgs> + static auto initiate(Initiation initiation, + experimental::use_coro_t<Allocator> tk, InitArgs&&... args) + { + return initiate_impl(std::move(initiation), std::allocator_arg, + tk.get_allocator(), std::forward<InitArgs>(args)...); + } +}; + +template <typename Allocator, typename R, typename T> +struct async_result< + experimental::use_coro_t<Allocator>, R(std::exception_ptr, T)> +{ + template <typename Initiation, typename... InitArgs> + static auto initiate_impl(Initiation initiation, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void(), T, + asio::associated_executor_t<Initiation>, Allocator> + { + co_return co_await deferred_async_operation< + R(std::exception_ptr, T), Initiation, InitArgs...>( + deferred_init_tag{}, std::move(initiation), std::move(args)...); + } + + template <typename... InitArgs> + static auto initiate_impl( + asio::detail::initiation_archetype<R(std::exception_ptr, T)>, + std::allocator_arg_t, Allocator, InitArgs... args) + -> experimental::coro<void(), T, asio::any_io_executor, Allocator>; + + template <typename Initiation, typename... InitArgs> + static auto initiate(Initiation initiation, + experimental::use_coro_t<Allocator> tk, InitArgs&&... args) + { + return initiate_impl(std::move(initiation), std::allocator_arg, + tk.get_allocator(), std::forward<InitArgs>(args)...); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP diff --git a/3rdparty/asio/include/asio/experimental/impl/use_promise.hpp b/3rdparty/asio/include/asio/experimental/impl/use_promise.hpp new file mode 100644 index 00000000000..259edb394bf --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/impl/use_promise.hpp @@ -0,0 +1,66 @@ +// +// experimental/impl/use_promise.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_IMPL_USE_PROMISE_HPP +#define ASIO_EXPERIMENTAL_IMPL_USE_PROMISE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <memory> +#include "asio/async_result.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { + +template <typename Allocator> +struct use_promise_t; + +namespace detail { + +template<typename Signature, typename Executor, typename Allocator> +struct promise_handler; + +} // namespace detail +} // namespace experimental + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename Allocator, typename R, typename... Args> +struct async_result<experimental::use_promise_t<Allocator>, R(Args...)> +{ + template <typename Initiation, typename... InitArgs> + static auto initiate(Initiation initiation, + experimental::use_promise_t<Allocator> up, InitArgs... args) + -> experimental::promise<void(decay_t<Args>...), + asio::associated_executor_t<Initiation>, Allocator> + { + using handler_type = experimental::detail::promise_handler< + void(decay_t<Args>...), + asio::associated_executor_t<Initiation>, Allocator>; + + handler_type ht{up.get_allocator(), get_associated_executor(initiation)}; + std::move(initiation)(ht, std::move(args)...); + return ht.make_promise(); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_EXPERIMENTAL_IMPL_USE_PROMISE_HPP diff --git a/3rdparty/asio/include/asio/experimental/parallel_group.hpp b/3rdparty/asio/include/asio/experimental/parallel_group.hpp index 8a097286199..967fc8802db 100644 --- a/3rdparty/asio/include/asio/experimental/parallel_group.hpp +++ b/3rdparty/asio/include/asio/experimental/parallel_group.hpp @@ -2,7 +2,7 @@ // experimental/parallel_group.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,8 +16,12 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" -#include <utility> +#include <vector> +#include "asio/async_result.hpp" #include "asio/detail/array.hpp" +#include "asio/detail/memory.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/detail/utility.hpp" #include "asio/experimental/cancellation_condition.hpp" #include "asio/detail/push_options.hpp" @@ -26,23 +30,6 @@ namespace asio { namespace experimental { namespace detail { -// Helper trait for getting the completion signature from an async operation. - -struct parallel_op_signature_probe {}; - -template <typename T> -struct parallel_op_signature_probe_result -{ - typedef T type; -}; - -template <typename Op> -struct parallel_op_signature -{ - typedef typename decltype(declval<Op>()( - declval<parallel_op_signature_probe>()))::type type; -}; - // Helper trait for getting a tuple from a completion signature. template <typename Signature> @@ -51,7 +38,7 @@ struct parallel_op_signature_as_tuple; template <typename R, typename... Args> struct parallel_op_signature_as_tuple<R(Args...)> { - typedef std::tuple<typename decay<Args>::type...> type; + typedef std::tuple<decay_t<Args>...> type; }; // Helper trait for concatenating completion signatures. @@ -93,10 +80,59 @@ struct parallel_group_signature<N, Sig0, Sig1, SigN...> template <typename Condition, typename Handler, typename... Ops, std::size_t... I> void parallel_group_launch(Condition cancellation_condition, Handler handler, - std::tuple<Ops...>& ops, std::index_sequence<I...>); + std::tuple<Ops...>& ops, asio::detail::index_sequence<I...>); + +// Helper trait for determining ranged parallel group completion signatures. + +template <typename Signature, typename Allocator> +struct ranged_parallel_group_signature; + +template <typename R, typename... Args, typename Allocator> +struct ranged_parallel_group_signature<R(Args...), Allocator> +{ + typedef std::vector<std::size_t, + ASIO_REBIND_ALLOC(Allocator, std::size_t)> order_type; + typedef R raw_type( + std::vector<Args, ASIO_REBIND_ALLOC(Allocator, Args)>...); + typedef R type(order_type, + std::vector<Args, ASIO_REBIND_ALLOC(Allocator, Args)>...); +}; + +template <typename Condition, typename Handler, + typename Range, typename Allocator> +void ranged_parallel_group_launch(Condition cancellation_condition, + Handler handler, Range&& range, const Allocator& allocator); + +char (¶llel_group_has_iterator_helper(...))[2]; + +template <typename T> +char parallel_group_has_iterator_helper(T*, typename T::iterator* = 0); + +template <typename T> +struct parallel_group_has_iterator_typedef +{ + enum { value = (sizeof((parallel_group_has_iterator_helper)((T*)(0))) == 1) }; +}; } // namespace detail +/// Type trait used to determine whether a type is a range of asynchronous +/// operations that can be used with with @c make_parallel_group. +template <typename T> +struct is_async_operation_range +{ +#if defined(GENERATING_DOCUMENTATION) + /// The value member is true if the type may be used as a range of + /// asynchronous operations. + static const bool value; +#else + enum + { + value = detail::parallel_group_has_iterator_typedef<T>::value + }; +#endif +}; + /// A group of asynchronous operations that may be launched in parallel. /** * See the documentation for asio::experimental::make_parallel_group for @@ -105,6 +141,20 @@ void parallel_group_launch(Condition cancellation_condition, Handler handler, template <typename... Ops> class parallel_group { +private: + struct initiate_async_wait + { + template <typename Handler, typename Condition> + void operator()(Handler&& h, Condition&& c, std::tuple<Ops...>&& ops) const + { + detail::parallel_group_launch( + std::forward<Condition>(c), std::forward<Handler>(h), + ops, asio::detail::index_sequence_for<Ops...>()); + } + }; + + std::tuple<Ops...> ops_; + public: /// Constructor. explicit parallel_group(Ops... ops) @@ -114,7 +164,7 @@ public: /// The completion signature for the group of operations. typedef typename detail::parallel_group_signature<sizeof...(Ops), - typename detail::parallel_op_signature<Ops>::type...>::type signature; + completion_signature_of_t<Ops>...>::type signature; /// Initiate an asynchronous wait for the group of operations. /** @@ -127,7 +177,7 @@ public: * operations, it must return a asio::cancellation_type value other * than <tt>asio::cancellation_type::none</tt>. * - * @param token A completion token whose signature is comprised of + * @param token A @ref completion_token whose signature is comprised of * a @c std::array<std::size_t, N> indicating the completion order of the * operations, followed by all operations' completion handler arguments. * @@ -142,24 +192,15 @@ public: ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken> auto async_wait(CancellationCondition cancellation_condition, CompletionToken&& token) + -> decltype( + asio::async_initiate<CompletionToken, signature>( + declval<initiate_async_wait>(), token, + std::move(cancellation_condition), std::move(ops_))) { return asio::async_initiate<CompletionToken, signature>( initiate_async_wait(), token, std::move(cancellation_condition), std::move(ops_)); } - -private: - struct initiate_async_wait - { - template <typename Handler, typename Condition> - void operator()(Handler&& h, Condition&& c, std::tuple<Ops...>&& ops) const - { - detail::parallel_group_launch(std::move(c), std::move(h), - ops, std::make_index_sequence<sizeof...(Ops)>()); - } - }; - - std::tuple<Ops...> ops_; }; /// Create a group of operations that may be launched in parallel. @@ -200,11 +241,212 @@ private: * @endcode */ template <typename... Ops> -inline parallel_group<Ops...> make_parallel_group(Ops... ops) +ASIO_NODISCARD inline parallel_group<Ops...> +make_parallel_group(Ops... ops) { return parallel_group<Ops...>(std::move(ops)...); } +/// A range-based group of asynchronous operations that may be launched in +/// parallel. +/** + * See the documentation for asio::experimental::make_parallel_group for + * a usage example. + */ +template <typename Range, typename Allocator = std::allocator<void>> +class ranged_parallel_group +{ +private: + struct initiate_async_wait + { + template <typename Handler, typename Condition> + void operator()(Handler&& h, Condition&& c, + Range&& range, const Allocator& allocator) const + { + detail::ranged_parallel_group_launch(std::move(c), + std::move(h), std::forward<Range>(range), allocator); + } + }; + + Range range_; + Allocator allocator_; + +public: + /// Constructor. + explicit ranged_parallel_group(Range range, + const Allocator& allocator = Allocator()) + : range_(std::move(range)), + allocator_(allocator) + { + } + + /// The completion signature for the group of operations. + typedef typename detail::ranged_parallel_group_signature< + completion_signature_of_t< + decay_t<decltype(*std::declval<typename Range::iterator>())>>, + Allocator>::type signature; + + /// Initiate an asynchronous wait for the group of operations. + /** + * Launches the group and asynchronously waits for completion. + * + * @param cancellation_condition A function object, called on completion of + * an operation within the group, that is used to determine whether to cancel + * the remaining operations. The function object is passed the arguments of + * the completed operation's handler. To trigger cancellation of the remaining + * operations, it must return a asio::cancellation_type value other + * than <tt>asio::cancellation_type::none</tt>. + * + * @param token A @ref completion_token whose signature is comprised of + * a @c std::vector<std::size_t, Allocator> indicating the completion order of + * the operations, followed by a vector for each of the completion signature's + * arguments. + * + * The library provides the following @c cancellation_condition types: + * + * @li asio::experimental::wait_for_all + * @li asio::experimental::wait_for_one + * @li asio::experimental::wait_for_one_error + * @li asio::experimental::wait_for_one_success + */ + template <typename CancellationCondition, + ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken> + auto async_wait(CancellationCondition cancellation_condition, + CompletionToken&& token) + -> decltype( + asio::async_initiate<CompletionToken, signature>( + declval<initiate_async_wait>(), token, + std::move(cancellation_condition), + std::move(range_), allocator_)) + { + return asio::async_initiate<CompletionToken, signature>( + initiate_async_wait(), token, + std::move(cancellation_condition), + std::move(range_), allocator_); + } +}; + +/// Create a group of operations that may be launched in parallel. +/** + * @param range A range containing the operations to be launched. + * + * For example: + * @code + * using op_type = decltype( + * socket1.async_read_some( + * asio::buffer(data1), + * asio::deferred + * ) + * ); + * + * std::vector<op_type> ops; + * + * ops.push_back( + * socket1.async_read_some( + * asio::buffer(data1), + * asio::deferred + * ) + * ); + * + * ops.push_back( + * socket2.async_read_some( + * asio::buffer(data2), + * asio::deferred + * ) + * ); + * + * asio::experimental::make_parallel_group(ops).async_wait( + * asio::experimental::wait_for_all(), + * []( + * std::vector<std::size_t> completion_order, + * std::vector<std::error_code> e, + * std::vector<std::size_t> n + * ) + * { + * for (std::size_t i = 0; i < completion_order.size(); ++i) + * { + * std::size_t idx = completion_order[i]; + * std::cout << "socket " << idx << " finished: "; + * std::cout << e[idx] << ", " << n[idx] << "\n"; + * } + * } + * ); + * @endcode + */ +template <typename Range> +ASIO_NODISCARD inline ranged_parallel_group<decay_t<Range>> +make_parallel_group(Range&& range, + constraint_t< + is_async_operation_range<decay_t<Range>>::value + > = 0) +{ + return ranged_parallel_group<decay_t<Range>>(std::forward<Range>(range)); +} + +/// Create a group of operations that may be launched in parallel. +/** + * @param allocator Specifies the allocator to be used with the result vectors. + * + * @param range A range containing the operations to be launched. + * + * For example: + * @code + * using op_type = decltype( + * socket1.async_read_some( + * asio::buffer(data1), + * asio::deferred + * ) + * ); + * + * std::vector<op_type> ops; + * + * ops.push_back( + * socket1.async_read_some( + * asio::buffer(data1), + * asio::deferred + * ) + * ); + * + * ops.push_back( + * socket2.async_read_some( + * asio::buffer(data2), + * asio::deferred + * ) + * ); + * + * asio::experimental::make_parallel_group( + * std::allocator_arg_t, + * my_allocator, + * ops + * ).async_wait( + * asio::experimental::wait_for_all(), + * []( + * std::vector<std::size_t> completion_order, + * std::vector<std::error_code> e, + * std::vector<std::size_t> n + * ) + * { + * for (std::size_t i = 0; i < completion_order.size(); ++i) + * { + * std::size_t idx = completion_order[i]; + * std::cout << "socket " << idx << " finished: "; + * std::cout << e[idx] << ", " << n[idx] << "\n"; + * } + * } + * ); + * @endcode + */ +template <typename Allocator, typename Range> +ASIO_NODISCARD inline ranged_parallel_group<decay_t<Range>, Allocator> +make_parallel_group(allocator_arg_t, const Allocator& allocator, Range&& range, + constraint_t< + is_async_operation_range<decay_t<Range>>::value + > = 0) +{ + return ranged_parallel_group<decay_t<Range>, Allocator>( + std::forward<Range>(range), allocator); +} + } // namespace experimental } // namespace asio diff --git a/3rdparty/asio/include/asio/experimental/prepend.hpp b/3rdparty/asio/include/asio/experimental/prepend.hpp index 4f892999e3e..503981f776f 100644 --- a/3rdparty/asio/include/asio/experimental/prepend.hpp +++ b/3rdparty/asio/include/asio/experimental/prepend.hpp @@ -2,7 +2,7 @@ // experimental/prepend.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,56 +16,21 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" -#include <tuple> -#include "asio/detail/type_traits.hpp" +#include "asio/prepend.hpp" #include "asio/detail/push_options.hpp" namespace asio { namespace experimental { -/// Completion token type used to specify that the completion handler -/// arguments should be passed additional values before the results of the -/// operation. -template <typename CompletionToken, typename... Values> -class prepend_t -{ -public: - /// Constructor. - template <typename T, typename... V> - ASIO_CONSTEXPR explicit prepend_t( - ASIO_MOVE_ARG(T) completion_token, - ASIO_MOVE_ARG(V)... values) - : token_(ASIO_MOVE_CAST(T)(completion_token)), - values_(ASIO_MOVE_CAST(V)(values)...) - { - } - -//private: - CompletionToken token_; - std::tuple<Values...> values_; -}; - -/// Completion token type used to specify that the completion handler -/// arguments should be passed additional values before the results of the -/// operation. -template <typename CompletionToken, typename... Values> -inline ASIO_CONSTEXPR prepend_t< - typename decay<CompletionToken>::type, typename decay<Values>::type...> -prepend(ASIO_MOVE_ARG(CompletionToken) completion_token, - ASIO_MOVE_ARG(Values)... values) -{ - return prepend_t< - typename decay<CompletionToken>::type, typename decay<Values>::type...>( - ASIO_MOVE_CAST(CompletionToken)(completion_token), - ASIO_MOVE_CAST(Values)(values)...); -} +#if !defined(ASIO_NO_DEPRECATED) +using asio::prepend_t; +using asio::prepend; +#endif // !defined(ASIO_NO_DEPRECATED) } // namespace experimental } // namespace asio #include "asio/detail/pop_options.hpp" -#include "asio/experimental/impl/prepend.hpp" - #endif // ASIO_EXPERIMENTAL_PREPEND_HPP diff --git a/3rdparty/asio/include/asio/experimental/promise.hpp b/3rdparty/asio/include/asio/experimental/promise.hpp index 89ca9c1b496..2bcf66b4e30 100644 --- a/3rdparty/asio/include/asio/experimental/promise.hpp +++ b/3rdparty/asio/include/asio/experimental/promise.hpp @@ -2,8 +2,8 @@ // experimental/promise.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2021 Klemens D. Morgenstern -// (klemens dot morgenstern at gmx dot net) +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -12,28 +12,28 @@ #ifndef ASIO_EXPERIMENTAL_PROMISE_HPP #define ASIO_EXPERIMENTAL_PROMISE_HPP +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" #include "asio/any_io_executor.hpp" #include "asio/associated_cancellation_slot.hpp" +#include "asio/associated_executor.hpp" #include "asio/bind_executor.hpp" #include "asio/cancellation_signal.hpp" -#include "asio/experimental/detail/completion_handler_erasure.hpp" +#include "asio/dispatch.hpp" #include "asio/experimental/impl/promise.hpp" #include "asio/post.hpp" -#include <variant> +#include <algorithm> #include "asio/detail/push_options.hpp" namespace asio { namespace experimental { -template <typename Executor = any_io_executor> -struct use_promise_t {}; - -constexpr use_promise_t<> use_promise; - template <typename T> struct is_promise : std::false_type {}; @@ -43,9 +43,6 @@ struct is_promise<promise<Ts...>> : std::true_type {}; template <typename T> constexpr bool is_promise_v = is_promise<T>::value; -template <typename T> -concept is_promise_c = is_promise_v<std::remove_reference_t<T>>; - template <typename ... Ts> struct promise_value_type { @@ -61,48 +58,70 @@ struct promise_value_type<T> template <> struct promise_value_type<> { - using type = std::monostate; + using type = std::tuple<>; }; #if defined(GENERATING_DOCUMENTATION) -/// The primary template is not defined. -template<typename Signature = void(), typename Executor = any_io_executor> +/// A disposable handle for an eager operation. +/** + * @tparam Signature The signature of the operation. + * + * @tparam Executor The executor to be used by the promise (taken from the + * operation). + * + * @tparam Allocator The allocator used for the promise. Can be set through + * use_allocator. + * + * A promise can be used to initiate an asynchronous option that can be + * completed later. If the promise gets destroyed before completion, the + * operation gets a cancel signal and the result is ignored. + * + * A promise fulfills the requirements of async_operation. + * + * @par Examples + * Reading and writing from one coroutine. + * @code + * awaitable<void> read_write_some(asio::ip::tcp::socket & sock, + * asio::mutable_buffer read_buf, asio::const_buffer to_write) + * { + * auto p = asio::async_read(read_buf, asio::use_awaitable); + * co_await asio::async_write_some(to_write, asio::deferred); + * co_await p; + * } + * @endcode + */ +template<typename Signature = void(), + typename Executor = asio::any_io_executor, + typename Allocator = std::allocator<void>> struct promise -{ -}; +#else +template <typename ... Ts, typename Executor, typename Allocator> +struct promise<void(Ts...), Executor, Allocator> #endif // defined(GENERATING_DOCUMENTATION) - -template <typename ... Ts, typename Executor> -struct promise<void(Ts...), Executor> { + /// The value that's returned by the promise. using value_type = typename promise_value_type<Ts...>::type; - using tuple_type = std::tuple<Ts...>; - using executor_type = Executor; - - executor_type get_executor() const - { - if (impl_) - return impl_->executor; - else - return {}; - } + /// Cancel the promise. Usually done through the destructor. void cancel(cancellation_type level = cancellation_type::all) { if (impl_ && !impl_->done) { asio::dispatch(impl_->executor, - [level, impl = impl_]{impl->cancel.emit(level);}); + [level, impl = impl_]{ impl->cancel.emit(level); }); } } - bool complete() const noexcept + /// Check if the promise is completed already. + bool completed() const noexcept { return impl_ && impl_->done; } - template <typename CompletionToken> - auto async_wait(CompletionToken&& token) + /// Wait for the promise to become ready. + template <ASIO_COMPLETION_TOKEN_FOR(void(Ts...)) CompletionToken> + inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(Ts...)) + operator()(CompletionToken&& token) { assert(impl_); @@ -114,435 +133,52 @@ struct promise<void(Ts...), Executor> promise(const promise& ) = delete; promise(promise&& ) noexcept = default; + /// Destruct the promise and cancel the operation. + /** + * It is safe to destruct a promise of a promise that didn't complete. + */ ~promise() { cancel(); } - template <execution::executor Executor1, is_promise_c ... Ps> - static auto race(Executor1 exec, Ps ... ps) - -> promise<void(std::variant<typename Ps::value_type...>), Executor1> - { - using var_t = std::variant<typename Ps::value_type...>; - using pi = detail::promise_impl<void(var_t), Executor1>; - - struct impl_t : pi - { - impl_t(Executor1 exec, Ps&& ... ps) - : pi(std::move(exec)), - tup(std::move(ps)...) - { - this->slot.template emplace<cancel_handler>(this); - } - - struct cancel_handler - { - impl_t* self; - - cancel_handler(impl_t* self) - : self(self) - { - } - - void operator()(cancellation_type ct) - { - [ct, s=self]<std::size_t... Idx>(std::index_sequence<Idx...>) - { - (std::get<Idx>(s->tup).cancel(ct), ... ); - }(std::make_index_sequence<sizeof...(Ps)>{}); - } - }; - - std::tuple<std::remove_reference_t<Ps>...> tup; - cancellation_slot slot{this->cancel.slot()}; - }; - - auto impl = std::allocate_shared<impl_t>( - get_associated_allocator(exec), exec, std::move(ps)...); - - impl->executor = exec; - - [impl, exec]<std::size_t... Idx>(std::index_sequence<Idx...>) - { - auto step = - [&]<std::size_t I>(std::integral_constant<std::size_t, I>) - { - return [impl]<typename... Args > (Args&& ... args) - { - if (impl->done) - return; - impl->result = var_t(std::in_place_index<I>, - std::forward<Args>(args)...); - impl->done = true; - if (auto f = std::exchange(impl->completion, nullptr); !!f) - std::apply(std::move(f), std::move(*impl->result)); - - auto cancel = - [&]<std::size_t Id>(std::integral_constant<std::size_t, Id>) - { - if constexpr (I != Id) - get<I>(impl->tup).cancel(); - }; - - (cancel(std::integral_constant<std::size_t, Idx>{}), ...); - }; - }; - - ( - std::get<Idx>(impl->tup).async_wait( - bind_executor(exec, - step(std::integral_constant<std::size_t, Idx>{}))), - ... - ); - }(std::make_index_sequence<sizeof...(Ps)>{}); - - return {impl}; - } - - template <execution::executor Executor1, is_promise_c ... Ps> - static auto all(Executor1 exec, Ps ... ps) - -> promise<void(typename Ps::value_type...), Executor1> - { - using pi = detail::promise_impl< - void(typename Ps::value_type...), Executor1>; - - struct impl_t : pi - { - impl_t(Executor1 exec, Ps&& ... ps) - : pi(std::move(exec)), - tup(std::move(ps)...) - { - this->slot.template emplace<cancel_handler>(this); - } - - struct cancel_handler - { - impl_t* self; - - cancel_handler(impl_t* self) - : self(self) - { - } - - void operator()(cancellation_type level) - { - [level, s=self]<std::size_t... Idx>(std::index_sequence<Idx...>) - { - (std::get<Idx>(s->tup).cancel(level), ... ); - }(std::make_index_sequence<sizeof...(Ps)>{}); - } - }; - - std::tuple<std::remove_reference_t<Ps>...> tup; - std::tuple<std::optional<typename Ps::value_type>...> partial_result; - cancellation_slot slot{this->cancel.slot()}; - }; - - auto impl = std::allocate_shared<impl_t>( - get_associated_allocator(exec), exec, std::move(ps)...); - impl->executor = exec; - - [impl, exec]<std::size_t... Idx>(std::index_sequence<Idx...>) - { - auto step = - [&]<std::size_t I>(std::integral_constant<std::size_t, I>) - { - return [impl]<typename... Args>(Args&& ... args) - { - std::get<I>(impl->partial_result).emplace( - std::forward<Args>(args)...); - if ((std::get<Idx>(impl->partial_result) && ...)) // we're done. - { - impl->result = {*std::get<Idx>(impl->partial_result)...}; - - impl->done = true; - if (auto f = std::exchange(impl->completion, nullptr); !!f) - std::apply(std::move(f), std::move(*impl->result)); - } - }; - }; - - ( - std::get<Idx>(impl->tup).async_wait( - bind_executor(exec, - step(std::integral_constant<std::size_t, Idx>{}))), - ... - ); - }(std::make_index_sequence<sizeof...(Ps)>{}); - - return {impl}; - } - - template <is_promise_c ... Ps> - static auto race(Ps ... ps) - { - auto exec = get<0>(std::tie(ps...)).get_executor(); - return race(std::move(exec), std::move(ps)...); - } - - template <is_promise_c ... Ps> - static auto all(Ps ... ps) - { - auto exec = get<0>(std::tie(ps...)).get_executor(); - return all(std::move(exec), std::move(ps)...); - } - - template <execution::executor Executor1, typename Range> -#if !defined(GENERATING_DOCUMENTATION) - requires requires (Range r) - { - {*std::begin(r)} -> is_promise_c; - {*std:: end(r)} -> is_promise_c; - } -#endif // !defined(GENERATING_DOCUMENTATION) - static auto race(Executor1 exec, Range range) - { - using var_t = typename std::decay_t< - decltype(*std::begin(range))>::value_type; - using signature_type = std::conditional_t< - std::is_same_v<var_t, std::monostate>, - void(std::size_t), - void(std::size_t, var_t)>; - using pi = detail::promise_impl<signature_type, Executor1>; - using promise_t = promise<signature_type, Executor1>; - - struct impl_t : pi - { - impl_t(Executor1 exec, Range&& range) - : pi(std::move(exec)), - range(std::move(range)) - { - this->slot.template emplace<cancel_handler>(this); - } - - struct cancel_handler - { - impl_t* self; - - cancel_handler(impl_t* self) - : self(self) - { - } - - void operator()(asio::cancellation_type ct) - { - for (auto& r : self->range) - r.cancel(ct); - } - }; - - Range range; - cancellation_slot slot{this->cancel.slot()}; - }; - - const auto size = std::distance(std::begin(range), std::end(range)); - auto impl = std::allocate_shared<impl_t>( - get_associated_allocator(exec), exec, std::move(range)); - impl->executor = exec; - - if (size == 0u) - { - if constexpr (std::is_same_v<var_t, std::monostate>) - impl->result = {-1}; - else - impl->result = {-1, var_t{}}; - - impl->done = true; - if (auto f = std::exchange(impl->completion, nullptr); !!f) - { - asio::post(exec, - [impl, f = std::move(f)]() mutable - { - std::apply(std::move(f), std::move(*impl->result)); - }); - } - return promise_t{impl}; - } - auto idx = 0u; - for (auto& val : impl->range) - { - val.async_wait( - bind_executor(exec, - [idx, impl]<typename... Args>(Args&&... args) - { - if (impl->done) - return; - if constexpr (std::is_same_v<var_t, std::monostate>) - impl->result = idx; - else - impl->result = std::make_tuple(idx, - var_t(std::forward<Args>(args)...)); - impl->done = true; - if (auto f = std::exchange(impl->completion, nullptr); !!f) - std::apply(std::move(f), std::move(*impl->result)); - - auto jdx = 0u; - - for (auto &tc : impl->range) - if (jdx++ != idx) - tc.cancel(); - })); - idx++; - } - return promise_t{impl}; - } - - - template <execution::executor Executor1, typename Range> -#if !defined(GENERATING_DOCUMENTATION) - requires requires (Range r) - { - {*std::begin(r)} -> is_promise_c; - {*std:: end(r)} -> is_promise_c; - } -#endif // !defined(GENERATING_DOCUMENTATION) - static auto all(Executor1 exec, Range range) - -> promise< - void( - std::vector< - typename std::decay_t< - decltype(*std::begin(range)) - >::value_type - > - ), Executor1> - { - using var_t = typename std::decay_t< - decltype(*std::begin(range))>::value_type; - using pi = detail::promise_impl<void(std::vector<var_t>), Executor1>; - - struct impl_t : pi - { - impl_t(Executor1 exec, Range&& range) - : pi(std::move(exec)), - range(std::move(range)) - { - this->slot.template emplace<cancel_handler>(this); - } - - struct cancel_handler - { - impl_t* self; - - cancel_handler(impl_t* self) - : self(self) - { - } - - void operator()(cancellation_type ct) - { - for (auto& r : self->range) - r.cancel(ct); - } - }; - - Range range; - std::vector<std::optional<var_t>> partial_result; - cancellation_slot slot{this->cancel.slot()}; - }; - - const auto size = std::distance(std::begin(range), std::end(range)); - auto impl = std::allocate_shared<impl_t>( - get_associated_allocator(exec), exec, std::move(range)); - impl->executor = exec; - impl->partial_result.resize(size); - - if (size == 0u) - { - impl->result.emplace(); - impl->done = true; - if (auto f = std::exchange(impl->completion, nullptr); !!f) - asio::post(exec, [impl, f = std::move(f)]() mutable - { - std::apply(std::move(f), std::move(*impl->result)); - }); - return {impl}; - } - auto idx = 0u; - for (auto& val : impl->range) { - val.async_wait(bind_executor( - exec, - [idx, impl]<typename... Args>(Args&&... args) { - - impl->partial_result[idx].emplace(std::forward<Args>(args)...); - if (std::all_of(impl->partial_result.begin(), - impl->partial_result.end(), - [](auto &opt) {return opt.has_value();})) - { - impl->result.emplace(); - get<0>(*impl->result).reserve(impl->partial_result.size()); - for (auto& p : impl->partial_result) - get<0>(*impl->result).push_back(std::move(*p)); - - impl->done = true; - if (auto f = std::exchange(impl->completion, nullptr); !!f) - std::apply(std::move(f), std::move(*impl->result)); - } - - })); - idx++; - } - return {impl}; - } - - template <typename Range> -#if !defined(GENERATING_DOCUMENTATION) - requires requires (Range r) - { - {*std::begin(r)} -> is_promise_c; - {*std:: end(r)} -> is_promise_c; - } -#endif // !defined(GENERATING_DOCUMENTATION) - static auto race(Range range) - { - if (std::begin(range) == std::end(range)) - throw std::logic_error( - "Can't use race on an empty range with deduced executor"); - else - return race(std::begin(range)->get_executor(), std::move(range)); - } - - template <typename Range> -#if !defined(GENERATING_DOCUMENTATION) - requires requires (Range&& r) - { - {*std::begin(r)} -> is_promise_c; - {*std:: end(r)} -> is_promise_c; - } -#endif // !defined(GENERATING_DOCUMENTATION) - static auto all(Range range) - { - if (std::begin(range) == std::end(range)) - throw std::logic_error( - "Can't use all on an empty range with deduced executor"); - else - return all(std::begin(range)->get_executor(), std::move(range)); - } private: #if !defined(GENERATING_DOCUMENTATION) - template <typename, typename> friend struct promise; - friend struct detail::promise_handler<void(Ts...)>; + template <typename, typename, typename> friend struct promise; + friend struct detail::promise_handler<void(Ts...), Executor, Allocator>; #endif // !defined(GENERATING_DOCUMENTATION) - std::shared_ptr<detail::promise_impl<void(Ts...), Executor>> impl_; - promise(std::shared_ptr<detail::promise_impl<void(Ts...), Executor>> impl) + std::shared_ptr<detail::promise_impl< + void(Ts...), Executor, Allocator>> impl_; + + promise( + std::shared_ptr<detail::promise_impl< + void(Ts...), Executor, Allocator>> impl) : impl_(impl) { } struct initiate_async_wait { - std::shared_ptr<detail::promise_impl<void(Ts...), Executor>> self_; + std::shared_ptr<detail::promise_impl< + void(Ts...), Executor, Allocator>> self_; template <typename WaitHandler> void operator()(WaitHandler&& handler) const { - const auto exec = get_associated_executor(handler, self_->executor); + const auto alloc = get_associated_allocator( + handler, self_->get_allocator()); + auto cancel = get_associated_cancellation_slot(handler); + if (self_->done) { + auto exec = asio::get_associated_executor( + handler, self_->get_executor()); + asio::post(exec, - [self = self_, h = std::forward<WaitHandler>(handler)]() mutable + [self = std::move(self_), + handler = std::forward<WaitHandler>(handler)]() mutable { - std::apply(std::forward<WaitHandler>(h), - std::move(*self->result)); + self->apply(std::move(handler)); }); } else @@ -551,26 +187,29 @@ private: { struct cancel_handler { - std::weak_ptr<detail::promise_impl<void(Ts...), Executor>> self; + std::weak_ptr<detail::promise_impl< + void(Ts...), Executor, Allocator>> self; cancel_handler( - std::weak_ptr<detail::promise_impl<void(Ts...), Executor>> self) + std::weak_ptr<detail::promise_impl< + void(Ts...), Executor, Allocator>> self) : self(std::move(self)) { } void operator()(cancellation_type level) const { - if (auto p = self.lock(); p != nullptr) + if (auto p = self.lock()) + { p->cancel.emit(level); - + p->cancel_(); + } } }; - cancel.template emplace<cancel_handler>(self_); } - self_->completion = {exec, std::forward<WaitHandler>(handler)}; + self_->set_completion(alloc, std::forward<WaitHandler>(handler)); } } }; @@ -578,27 +217,6 @@ private: } // namespace experimental -#if !defined(GENERATING_DOCUMENTATION) - -template <typename Executor, typename R, typename... Args> -struct async_result<experimental::use_promise_t<Executor>, R(Args...)> -{ - using handler_type = experimental::detail::promise_handler< - void(typename decay<Args>::type...), Executor>; - - template <typename Initiation, typename... InitArgs> - static auto initiate(Initiation initiation, - experimental::use_promise_t<Executor>, InitArgs... args) - -> typename handler_type::promise_type - { - handler_type ht{get_associated_executor(initiation)}; - std::move(initiation)(ht, std::move(args)...); - return ht.make_promise(); - } -}; - -#endif // !defined(GENERATING_DOCUMENTATION) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/experimental/use_coro.hpp b/3rdparty/asio/include/asio/experimental/use_coro.hpp index a94d3ae5191..d9e0544106c 100644 --- a/3rdparty/asio/include/asio/experimental/use_coro.hpp +++ b/3rdparty/asio/include/asio/experimental/use_coro.hpp @@ -2,8 +2,8 @@ // experimental/use_coro.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2021 Klemens D. Morgenstern -// (klemens dot morgenstern at gmx dot net) +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -12,12 +12,14 @@ #ifndef ASIO_EXPERIMENTAL_USE_CORO_HPP #define ASIO_EXPERIMENTAL_USE_CORO_HPP +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + #include "asio/detail/config.hpp" -#include <optional> -#include "asio/bind_cancellation_slot.hpp" -#include "asio/bind_executor.hpp" -#include "asio/error_code.hpp" -#include "asio/experimental/detail/partial_promise.hpp" +#include <memory> +#include "asio/deferred.hpp" +#include "asio/detail/source_location.hpp" #include "asio/detail/push_options.hpp" @@ -27,256 +29,161 @@ class any_io_executor; namespace experimental { -template <typename Executor = any_io_executor> +/// A @ref completion_token that creates another coro for the task completion. +/** + * The @c use_coro_t class, with its value @c use_coro, is used to represent an + * operation that can be awaited by the current resumable coroutine. This + * completion token may be passed as a handler to an asynchronous operation. + * For example: + * + * @code coro<void> my_coroutine(tcp::socket my_socket) + * { + * std::size_t n = co_await my_socket.async_read_some(buffer, use_coro); + * ... + * } @endcode + * + * When used with co_await, the initiating function (@c async_read_some in the + * above example) suspends the current coroutine. The coroutine is resumed when + * the asynchronous operation completes, and the result of the operation is + * returned. + * + * Note that this token is not the most efficient (use @c asio::deferred + * for that) but does provide type erasure, as it will always return a @c coro. + */ +template <typename Allocator = std::allocator<void>> struct use_coro_t { -}; - -constexpr use_coro_t<> use_coro; - -template <typename Yield, typename Return, typename Executor> -struct coro; - -namespace detail { -template <typename Yield, typename Return, typename Executor> -struct coro_promise; - -template <typename Executor, typename... Ts> -struct coro_init_handler -{ - struct handler_t + /// The allocator type. The allocator is used when constructing the + /// @c std::promise object for a given asynchronous operation. + typedef Allocator allocator_type; + + /// Default constructor. + constexpr use_coro_t( + allocator_type allocator = allocator_type{} +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + , asio::detail::source_location location = + asio::detail::source_location::current() +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + ) + : allocator_(allocator) +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + , file_name_(location.file_name()), + line_(location.line()), + function_name_(location.function_name()) +# else // defined(ASIO_HAS_SOURCE_LOCATION) + , file_name_(0), + line_(0), + function_name_(0) +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) { - }; - - constexpr static handler_t handler{}; + } - struct init_helper; - struct promise_type + /// Specify an alternate allocator. + template <typename OtherAllocator> + use_coro_t<OtherAllocator> rebind(const OtherAllocator& allocator) const { - auto initial_suspend() noexcept { return suspend_always{}; } - - auto final_suspend() noexcept { return suspend_always(); } - - void return_void() {} - - void unhandled_exception() { assert(false); } - - auto await_transform(handler_t) - { - assert(executor); - assert(h); - return init_helper{this}; - } - - std::optional<Executor> executor; - std::optional<std::tuple<Ts...>> result; - coroutine_handle<> h; - - coro_init_handler get_return_object() { return coro_init_handler{this}; } - - cancellation_slot cancel_slot; - }; - - struct init_helper - { - promise_type *self_; - - constexpr static bool await_ready() noexcept { return true; } - - constexpr static void await_suspend(coroutine_handle<>) noexcept {} - - auto await_resume() const noexcept - { - assert(self_); - return bind_cancellation_slot(self_->cancel_slot, - bind_executor(*self_->executor, [self = self_](Ts... ts) - { - self->result.emplace(std::move(ts)...); - self->h.resume(); - })); - } - }; - - promise_type* promise; + return use_future_t<OtherAllocator>(allocator); + } - void unhandled_exception() noexcept + /// Obtain allocator. + allocator_type get_allocator() const { - throw; + return allocator_; } - struct noexcept_version + /// Constructor used to specify file name, line, and function name. + constexpr use_coro_t(const char* file_name, + int line, const char* function_name, + allocator_type allocator = allocator_type{}) : +#if defined(ASIO_ENABLE_HANDLER_TRACKING) + file_name_(file_name), + line_(line), + function_name_(function_name), +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + allocator_(allocator) { - promise_type *promise; - - constexpr static bool await_ready() noexcept { return false; } - - template <typename Yield, typename Return, - convertible_to<Executor> Executor1> - auto await_suspend( - coroutine_handle<coro_promise<Yield, Return, Executor1> > h) noexcept - { - promise->executor = h.promise().get_executor(); - promise->h = h; - return coroutine_handle<promise_type>::from_promise(*promise); - } - - template <typename... Args> - static auto resume_impl(std::tuple<Args...>&& tup) - { - return std::move(tup); - } - - template <typename Arg> - static auto resume_impl(std::tuple<Arg>&& tup) - { - return get<0>(std::move(tup)); - } - - static void resume_impl(std::tuple<>&&) {} - - auto await_resume() const noexcept - { - auto res = std::move(promise->result.value()); - coroutine_handle<promise_type>::from_promise(*promise).destroy(); - return resume_impl(std::move(res)); - } - }; +#if !defined(ASIO_ENABLE_HANDLER_TRACKING) + (void)file_name; + (void)line; + (void)function_name; +#endif // !defined(ASIO_ENABLE_HANDLER_TRACKING) + } - struct throwing_version + /// Adapts an executor to add the @c use_coro_t completion token as the + /// default. + template <typename InnerExecutor> + struct executor_with_default : InnerExecutor { - promise_type *promise; - - constexpr static bool await_ready() noexcept { return false; } - - template <typename Yield, typename Return, - convertible_to<Executor> Executor1> - auto await_suspend( - coroutine_handle<coro_promise<Yield, Return, Executor1> > h) noexcept - { - promise->executor = h.promise().get_executor(); - promise->h = h; - return coroutine_handle<promise_type>::from_promise(*promise); - } - - template <typename... Args> - static auto resume_impl(std::tuple<Args...>&& tup) - { - return std::move(tup); - } - - static void resume_impl(std::tuple<>&&) {} - - template <typename Arg> - static auto resume_impl(std::tuple<Arg>&& tup) - { - return get<0>(std::move(tup)); - } - - template <typename... Args> - static auto resume_impl(std::tuple<std::exception_ptr, Args...>&& tup) - { - auto ex = get<0>(std::move(tup)); - if (ex) - std::rethrow_exception(ex); - - if constexpr (sizeof...(Args) == 0u) - return; - else if constexpr (sizeof...(Args) == 1u) - return get<1>(std::move(tup)); - else - { - return - [&]<std::size_t... Idx>(std::index_sequence<Idx...>) - { - return std::make_tuple(std::get<Idx + 1>(std::move(tup))...); - }(std::make_index_sequence<sizeof...(Args) - 1>{}); - } - } - - template <typename... Args> - static auto resume_impl( - std::tuple<asio::error_code, Args...>&& tup) - { - auto ec = get<0>(std::move(tup)); - if (ec) - asio::detail::throw_exception( - asio::system_error(ec, "error_code in use_coro")); - - if constexpr (sizeof...(Args) == 0u) - return; - else if constexpr (sizeof...(Args) == 1u) - return get<1>(std::move(tup)); - else - return - [&]<std::size_t... Idx>(std::index_sequence<Idx...>) - { - return std::make_tuple(std::get<Idx + 1>(std::move(tup))...); - }(std::make_index_sequence<sizeof...(Args) - 1>{}); - } - - static auto resume_impl(std::tuple<std::exception_ptr>&& tup) - { - auto ex = get<0>(std::move(tup)); - if (ex) - std::rethrow_exception(ex); - } - - static auto resume_impl( - std::tuple<asio::error_code>&& tup) + /// Specify @c use_coro_t as the default completion token type. + typedef use_coro_t default_completion_token_type; + + /// Construct the adapted executor from the inner executor type. + template <typename InnerExecutor1> + executor_with_default(const InnerExecutor1& ex, + constraint_t< + conditional_t< + !is_same<InnerExecutor1, executor_with_default>::value, + is_convertible<InnerExecutor1, InnerExecutor>, + false_type + >::value + > = 0) noexcept + : InnerExecutor(ex) { - auto ec = get<0>(std::move(tup)); - if (ec) - asio::detail::throw_error(ec, "error_code in use_coro"); - } - - auto await_resume() const - { - auto res = std::move(promise->result.value()); - coroutine_handle<promise_type>::from_promise(*promise).destroy(); - return resume_impl(std::move(res)); } }; - auto as_noexcept(cancellation_slot&& sl) && noexcept + /// Type alias to adapt an I/O object to use @c use_coro_t as its + /// default completion token type. + template <typename T> + using as_default_on_t = typename T::template rebind_executor< + executor_with_default<typename T::executor_type>>::other; + + /// Function helper to adapt an I/O object to use @c use_coro_t as its + /// default completion token type. + template <typename T> + static typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> + >::other + as_default_on(T&& object) { - promise->cancel_slot = std::move(sl); - return noexcept_version{promise}; + return typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> + >::other(static_cast<T&&>(object)); } - auto as_throwing(cancellation_slot&& sl) && noexcept - { - promise->cancel_slot = std::move(sl); - return throwing_version{promise}; - } -}; - -} // namespace detail -} // namespace experimental - -#if !defined(GENERATING_DOCUMENTATION) - -template <typename Executor, typename R, typename... Args> -struct async_result<experimental::use_coro_t<Executor>, R(Args...)> -{ - using return_type = experimental::detail::coro_init_handler< - Executor, typename decay<Args>::type...>; +#if defined(ASIO_ENABLE_HANDLER_TRACKING) + const char* file_name_; + int line_; + const char* function_name_; +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) - template <typename Initiation, typename... InitArgs> - static return_type initiate(Initiation initiation, - experimental::use_coro_t<Executor>, InitArgs... args) - { - std::move(initiation)(co_await return_type::handler, std::move(args)...); - } +private: + Allocator allocator_; }; -#endif // !defined(GENERATING_DOCUMENTATION) +/// A @ref completion_token object that represents the currently executing +/// resumable coroutine. +/** + * See the documentation for asio::use_coro_t for a usage example. + */ +#if defined(GENERATING_DOCUMENTATION) +constexpr use_coro_t<> use_coro; +#else +constexpr use_coro_t<> use_coro(0, 0, 0); +#endif +} // namespace experimental } // namespace asio #include "asio/detail/pop_options.hpp" +#include "asio/experimental/impl/use_coro.hpp" #include "asio/experimental/coro.hpp" #endif // ASIO_EXPERIMENTAL_USE_CORO_HPP diff --git a/3rdparty/asio/include/asio/experimental/use_promise.hpp b/3rdparty/asio/include/asio/experimental/use_promise.hpp new file mode 100644 index 00000000000..cf19aca59d5 --- /dev/null +++ b/3rdparty/asio/include/asio/experimental/use_promise.hpp @@ -0,0 +1,111 @@ +// +// experimental/use_promise.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2021-2023 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_EXPERIMENTAL_USE_PROMISE_HPP +#define ASIO_EXPERIMENTAL_USE_PROMISE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <memory> +#include "asio/detail/type_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace experimental { + +template <typename Allocator = std::allocator<void>> +struct use_promise_t +{ + /// The allocator type. The allocator is used when constructing the + /// @c promise object for a given asynchronous operation. + typedef Allocator allocator_type; + + /// Construct using default-constructed allocator. + constexpr use_promise_t() + { + } + + /// Construct using specified allocator. + explicit use_promise_t(const Allocator& allocator) + : allocator_(allocator) + { + } + + /// Obtain allocator. + allocator_type get_allocator() const noexcept + { + return allocator_; + } + + /// Adapts an executor to add the @c use_promise_t completion token as the + /// default. + template <typename InnerExecutor> + struct executor_with_default : InnerExecutor + { + /// Specify @c use_promise_t as the default completion token type. + typedef use_promise_t<Allocator> default_completion_token_type; + + /// Construct the adapted executor from the inner executor type. + executor_with_default(const InnerExecutor& ex) noexcept + : InnerExecutor(ex) + { + } + + /// Convert the specified executor to the inner executor type, then use + /// that to construct the adapted executor. + template <typename OtherExecutor> + executor_with_default(const OtherExecutor& ex, + constraint_t< + is_convertible<OtherExecutor, InnerExecutor>::value + > = 0) noexcept + : InnerExecutor(ex) + { + } + }; + + /// Function helper to adapt an I/O object to use @c use_promise_t as its + /// default completion token type. + template <typename T> + static typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> + >::other + as_default_on(T&& object) + { + return typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> + >::other(static_cast<T&&>(object)); + } + + /// Specify an alternate allocator. + template <typename OtherAllocator> + use_promise_t<OtherAllocator> rebind(const OtherAllocator& allocator) const + { + return use_promise_t<OtherAllocator>(allocator); + } + +private: + Allocator allocator_; +}; + +constexpr use_promise_t<> use_promise; + +} // namespace experimental +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/experimental/impl/use_promise.hpp" + +#endif // ASIO_EXPERIMENTAL_USE_CORO_HPP diff --git a/3rdparty/asio/include/asio/file_base.hpp b/3rdparty/asio/include/asio/file_base.hpp new file mode 100644 index 00000000000..5e8ac4f2ed5 --- /dev/null +++ b/3rdparty/asio/include/asio/file_base.hpp @@ -0,0 +1,166 @@ +// +// file_base.hpp +// ~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_FILE_BASE_HPP +#define ASIO_FILE_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_FILE) \ + || defined(GENERATING_DOCUMENTATION) + +#if !defined(ASIO_WINDOWS) +# include <fcntl.h> +#endif // !defined(ASIO_WINDOWS) + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// The file_base class is used as a base for the basic_stream_file and +/// basic_random_access_file class templates so that we have a common place to +/// define flags. +class file_base +{ +public: +#if defined(GENERATING_DOCUMENTATION) + /// A bitmask type (C++ Std [lib.bitmask.types]). + typedef unspecified flags; + + /// Open the file for reading. + static const flags read_only = implementation_defined; + + /// Open the file for writing. + static const flags write_only = implementation_defined; + + /// Open the file for reading and writing. + static const flags read_write = implementation_defined; + + /// Open the file in append mode. + static const flags append = implementation_defined; + + /// Create the file if it does not exist. + static const flags create = implementation_defined; + + /// Ensure a new file is created. Must be combined with @c create. + static const flags exclusive = implementation_defined; + + /// Open the file with any existing contents truncated. + static const flags truncate = implementation_defined; + + /// Open the file so that write operations automatically synchronise the file + /// data and metadata to disk. + static const flags sync_all_on_write = implementation_defined; +#else + enum flags + { +#if defined(ASIO_WINDOWS) + read_only = 1, + write_only = 2, + read_write = 4, + append = 8, + create = 16, + exclusive = 32, + truncate = 64, + sync_all_on_write = 128 +#else // defined(ASIO_WINDOWS) + read_only = O_RDONLY, + write_only = O_WRONLY, + read_write = O_RDWR, + append = O_APPEND, + create = O_CREAT, + exclusive = O_EXCL, + truncate = O_TRUNC, + sync_all_on_write = O_SYNC +#endif // defined(ASIO_WINDOWS) + }; + + // Implement bitmask operations as shown in C++ Std [lib.bitmask.types]. + + friend flags operator&(flags x, flags y) + { + return static_cast<flags>( + static_cast<unsigned int>(x) & static_cast<unsigned int>(y)); + } + + friend flags operator|(flags x, flags y) + { + return static_cast<flags>( + static_cast<unsigned int>(x) | static_cast<unsigned int>(y)); + } + + friend flags operator^(flags x, flags y) + { + return static_cast<flags>( + static_cast<unsigned int>(x) ^ static_cast<unsigned int>(y)); + } + + friend flags operator~(flags x) + { + return static_cast<flags>(~static_cast<unsigned int>(x)); + } + + friend flags& operator&=(flags& x, flags y) + { + x = x & y; + return x; + } + + friend flags& operator|=(flags& x, flags y) + { + x = x | y; + return x; + } + + friend flags& operator^=(flags& x, flags y) + { + x = x ^ y; + return x; + } +#endif + + /// Basis for seeking in a file. + enum seek_basis + { +#if defined(GENERATING_DOCUMENTATION) + /// Seek to an absolute position. + seek_set = implementation_defined, + + /// Seek to an offset relative to the current file position. + seek_cur = implementation_defined, + + /// Seek to an offset relative to the end of the file. + seek_end = implementation_defined +#else + seek_set = SEEK_SET, + seek_cur = SEEK_CUR, + seek_end = SEEK_END +#endif + }; + +protected: + /// Protected destructor to prevent deletion through this type. + ~file_base() + { + } +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_FILE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_FILE_BASE_HPP diff --git a/3rdparty/asio/include/asio/generic/basic_endpoint.hpp b/3rdparty/asio/include/asio/generic/basic_endpoint.hpp index 64dd940026e..e7e1f6d4103 100644 --- a/3rdparty/asio/include/asio/generic/basic_endpoint.hpp +++ b/3rdparty/asio/include/asio/generic/basic_endpoint.hpp @@ -2,7 +2,7 @@ // generic/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -54,7 +54,7 @@ public: #endif /// Default constructor. - basic_endpoint() ASIO_NOEXCEPT + basic_endpoint() noexcept { } @@ -78,13 +78,11 @@ public: { } -#if defined(ASIO_HAS_MOVE) /// Move constructor. basic_endpoint(basic_endpoint&& other) : impl_(other.impl_) { } -#endif // defined(ASIO_HAS_MOVE) /// Assign from another endpoint. basic_endpoint& operator=(const basic_endpoint& other) @@ -93,14 +91,12 @@ public: return *this; } -#if defined(ASIO_HAS_MOVE) /// Move-assign from another endpoint. basic_endpoint& operator=(basic_endpoint&& other) { impl_ = other.impl_; return *this; } -#endif // defined(ASIO_HAS_MOVE) /// The protocol associated with the endpoint. protocol_type protocol() const diff --git a/3rdparty/asio/include/asio/generic/datagram_protocol.hpp b/3rdparty/asio/include/asio/generic/datagram_protocol.hpp index 6bb711b9d24..6e81cd6a084 100644 --- a/3rdparty/asio/include/asio/generic/datagram_protocol.hpp +++ b/3rdparty/asio/include/asio/generic/datagram_protocol.hpp @@ -2,7 +2,7 @@ // generic/datagram_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -73,19 +73,19 @@ public: } /// Obtain an identifier for the type of the protocol. - int type() const ASIO_NOEXCEPT + int type() const noexcept { return ASIO_OS_DEF(SOCK_DGRAM); } /// Obtain an identifier for the protocol. - int protocol() const ASIO_NOEXCEPT + int protocol() const noexcept { return protocol_; } /// Obtain an identifier for the protocol family. - int family() const ASIO_NOEXCEPT + int family() const noexcept { return family_; } diff --git a/3rdparty/asio/include/asio/generic/detail/endpoint.hpp b/3rdparty/asio/include/asio/generic/detail/endpoint.hpp index e58271a660a..fdbcde92e5a 100644 --- a/3rdparty/asio/include/asio/generic/detail/endpoint.hpp +++ b/3rdparty/asio/include/asio/generic/detail/endpoint.hpp @@ -2,7 +2,7 @@ // generic/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/generic/detail/impl/endpoint.ipp b/3rdparty/asio/include/asio/generic/detail/impl/endpoint.ipp index 6a1124a791a..3e88c21098b 100644 --- a/3rdparty/asio/include/asio/generic/detail/impl/endpoint.ipp +++ b/3rdparty/asio/include/asio/generic/detail/impl/endpoint.ipp @@ -2,7 +2,7 @@ // generic/detail/impl/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/generic/raw_protocol.hpp b/3rdparty/asio/include/asio/generic/raw_protocol.hpp index 69abfc190b5..fc81cdd1ee9 100644 --- a/3rdparty/asio/include/asio/generic/raw_protocol.hpp +++ b/3rdparty/asio/include/asio/generic/raw_protocol.hpp @@ -2,7 +2,7 @@ // generic/raw_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -73,19 +73,19 @@ public: } /// Obtain an identifier for the type of the protocol. - int type() const ASIO_NOEXCEPT + int type() const noexcept { return ASIO_OS_DEF(SOCK_RAW); } /// Obtain an identifier for the protocol. - int protocol() const ASIO_NOEXCEPT + int protocol() const noexcept { return protocol_; } /// Obtain an identifier for the protocol family. - int family() const ASIO_NOEXCEPT + int family() const noexcept { return family_; } diff --git a/3rdparty/asio/include/asio/generic/seq_packet_protocol.hpp b/3rdparty/asio/include/asio/generic/seq_packet_protocol.hpp index 1734cb0b9f1..e0342a47836 100644 --- a/3rdparty/asio/include/asio/generic/seq_packet_protocol.hpp +++ b/3rdparty/asio/include/asio/generic/seq_packet_protocol.hpp @@ -2,7 +2,7 @@ // generic/seq_packet_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -72,19 +72,19 @@ public: } /// Obtain an identifier for the type of the protocol. - int type() const ASIO_NOEXCEPT + int type() const noexcept { return ASIO_OS_DEF(SOCK_SEQPACKET); } /// Obtain an identifier for the protocol. - int protocol() const ASIO_NOEXCEPT + int protocol() const noexcept { return protocol_; } /// Obtain an identifier for the protocol family. - int family() const ASIO_NOEXCEPT + int family() const noexcept { return family_; } diff --git a/3rdparty/asio/include/asio/generic/stream_protocol.hpp b/3rdparty/asio/include/asio/generic/stream_protocol.hpp index 78c92eead89..270006e60ed 100644 --- a/3rdparty/asio/include/asio/generic/stream_protocol.hpp +++ b/3rdparty/asio/include/asio/generic/stream_protocol.hpp @@ -2,7 +2,7 @@ // generic/stream_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -74,19 +74,19 @@ public: } /// Obtain an identifier for the type of the protocol. - int type() const ASIO_NOEXCEPT + int type() const noexcept { return ASIO_OS_DEF(SOCK_STREAM); } /// Obtain an identifier for the protocol. - int protocol() const ASIO_NOEXCEPT + int protocol() const noexcept { return protocol_; } /// Obtain an identifier for the protocol family. - int family() const ASIO_NOEXCEPT + int family() const noexcept { return family_; } diff --git a/3rdparty/asio/include/asio/handler_alloc_hook.hpp b/3rdparty/asio/include/asio/handler_alloc_hook.hpp deleted file mode 100644 index 16f4f5a5b2a..00000000000 --- a/3rdparty/asio/include/asio/handler_alloc_hook.hpp +++ /dev/null @@ -1,104 +0,0 @@ -// -// handler_alloc_hook.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_HANDLER_ALLOC_HOOK_HPP -#define ASIO_HANDLER_ALLOC_HOOK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include <cstddef> - -#include "asio/detail/push_options.hpp" - -namespace asio { - -#if defined(ASIO_NO_DEPRECATED) - -// Places in asio that would have previously called the allocate or deallocate -// hooks to manage memory, now call them only to check whether the result types -// are these types. If the result is not the correct type, it indicates that -// the user code still has the old hooks in place, and if so we want to trigger -// a compile error. -enum asio_handler_allocate_is_no_longer_used {}; -enum asio_handler_deallocate_is_no_longer_used {}; - -typedef asio_handler_allocate_is_no_longer_used - asio_handler_allocate_is_deprecated; -typedef asio_handler_deallocate_is_no_longer_used - asio_handler_deallocate_is_deprecated; - -#else // defined(ASIO_NO_DEPRECATED) - -typedef void* asio_handler_allocate_is_deprecated; -typedef void asio_handler_deallocate_is_deprecated; - -#endif // defined(ASIO_NO_DEPRECATED) - -/// (Deprecated: Use the associated_allocator trait.) Default allocation -/// function for handlers. -/** - * Asynchronous operations may need to allocate temporary objects. Since - * asynchronous operations have a handler function object, these temporary - * objects can be said to be associated with the handler. - * - * Implement asio_handler_allocate and asio_handler_deallocate for your own - * handlers to provide custom allocation for these temporary objects. - * - * The default implementation of these allocation hooks uses <tt>::operator - * new</tt> and <tt>::operator delete</tt>. - * - * @note All temporary objects associated with a handler will be deallocated - * before the upcall to the handler is performed. This allows the same memory to - * be reused for a subsequent asynchronous operation initiated by the handler. - * - * @par Example - * @code - * class my_handler; - * - * void* asio_handler_allocate(std::size_t size, my_handler* context) - * { - * return ::operator new(size); - * } - * - * void asio_handler_deallocate(void* pointer, std::size_t size, - * my_handler* context) - * { - * ::operator delete(pointer); - * } - * @endcode - */ -ASIO_DECL asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, ...); - -/// Default deallocation function for handlers. -/** - * Implement asio_handler_allocate and asio_handler_deallocate for your own - * handlers to provide custom allocation for the associated temporary objects. - * - * The default implementation of these allocation hooks uses <tt>::operator - * new</tt> and <tt>::operator delete</tt>. - * - * @sa asio_handler_allocate. - */ -ASIO_DECL asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, ...); - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#if defined(ASIO_HEADER_ONLY) -# include "asio/impl/handler_alloc_hook.ipp" -#endif // defined(ASIO_HEADER_ONLY) - -#endif // ASIO_HANDLER_ALLOC_HOOK_HPP diff --git a/3rdparty/asio/include/asio/handler_continuation_hook.hpp b/3rdparty/asio/include/asio/handler_continuation_hook.hpp index 40199f45054..8c5c65243de 100644 --- a/3rdparty/asio/include/asio/handler_continuation_hook.hpp +++ b/3rdparty/asio/include/asio/handler_continuation_hook.hpp @@ -2,7 +2,7 @@ // handler_continuation_hook.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/handler_invoke_hook.hpp b/3rdparty/asio/include/asio/handler_invoke_hook.hpp deleted file mode 100644 index 238745218b2..00000000000 --- a/3rdparty/asio/include/asio/handler_invoke_hook.hpp +++ /dev/null @@ -1,111 +0,0 @@ -// -// handler_invoke_hook.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_HANDLER_INVOKE_HOOK_HPP -#define ASIO_HANDLER_INVOKE_HOOK_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { - -/** @defgroup asio_handler_invoke asio::asio_handler_invoke - * - * @brief (Deprecated: Use the associated_executor trait.) Default invoke - * function for handlers. - * - * Completion handlers for asynchronous operations are invoked by the - * 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_context object. - * Handlers may subsequently be invoked through other objects (such as - * 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 - * method as the final handler. This is required to ensure that user-defined - * objects are not accessed in a way that may violate the guarantees. This - * hooking function ensures that the invoked method used for the final handler - * is accessible at each intermediate step. - * - * Implement asio_handler_invoke for your own handlers to specify a custom - * invocation strategy. - * - * This default implementation invokes the function object like so: - * @code function(); @endcode - * If necessary, the default implementation makes a copy of the function object - * so that the non-const operator() can be used. - * - * @par Example - * @code - * class my_handler; - * - * template <typename Function> - * void asio_handler_invoke(Function function, my_handler* context) - * { - * context->strand_.dispatch(function); - * } - * @endcode - */ -/*@{*/ - -#if defined(ASIO_NO_DEPRECATED) - -// Places in asio that would have previously called the invocation hook to -// execute a handler, now call it only to check whether the result type is this -// type. If the result is not this type, it indicates that the user code still -// has the old hooks in place, and if so we want to trigger a compile error. -enum asio_handler_invoke_is_no_longer_used {}; - -typedef asio_handler_invoke_is_no_longer_used - asio_handler_invoke_is_deprecated; - -#else // defined(ASIO_NO_DEPRECATED) - -typedef void asio_handler_invoke_is_deprecated; - -#endif // defined(ASIO_NO_DEPRECATED) - -/// Default handler invocation hook used for non-const function objects. -template <typename Function> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, ...) -{ - function(); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -/// Default handler invocation hook used for const function objects. -template <typename Function> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, ...) -{ - Function tmp(function); - tmp(); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -/*@}*/ - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_HANDLER_INVOKE_HOOK_HPP diff --git a/3rdparty/asio/include/asio/high_resolution_timer.hpp b/3rdparty/asio/include/asio/high_resolution_timer.hpp index 2bbc1a1ead5..50e8030a225 100644 --- a/3rdparty/asio/include/asio/high_resolution_timer.hpp +++ b/3rdparty/asio/include/asio/high_resolution_timer.hpp @@ -2,7 +2,7 @@ // high_resolution_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) - #include "asio/basic_waitable_timer.hpp" #include "asio/detail/chrono.hpp" @@ -39,6 +36,4 @@ typedef basic_waitable_timer< } // namespace asio -#endif // defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) - #endif // ASIO_HIGH_RESOLUTION_TIMER_HPP diff --git a/3rdparty/asio/include/asio/impl/any_completion_executor.ipp b/3rdparty/asio/include/asio/impl/any_completion_executor.ipp new file mode 100644 index 00000000000..fdad007dab1 --- /dev/null +++ b/3rdparty/asio/include/asio/impl/any_completion_executor.ipp @@ -0,0 +1,126 @@ +// +// impl/any_completion_executor.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_ANY_COMPLETION_EXECUTOR_IPP +#define ASIO_IMPL_ANY_COMPLETION_EXECUTOR_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) + +#include "asio/any_completion_executor.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +any_completion_executor::any_completion_executor() noexcept + : base_type() +{ +} + +any_completion_executor::any_completion_executor(nullptr_t) noexcept + : base_type(nullptr_t()) +{ +} + +any_completion_executor::any_completion_executor( + const any_completion_executor& e) noexcept + : base_type(static_cast<const base_type&>(e)) +{ +} + +any_completion_executor::any_completion_executor(std::nothrow_t, + const any_completion_executor& e) noexcept + : base_type(static_cast<const base_type&>(e)) +{ +} + +any_completion_executor::any_completion_executor( + any_completion_executor&& e) noexcept + : base_type(static_cast<base_type&&>(e)) +{ +} + +any_completion_executor::any_completion_executor(std::nothrow_t, + any_completion_executor&& e) noexcept + : base_type(static_cast<base_type&&>(e)) +{ +} + +any_completion_executor& any_completion_executor::operator=( + const any_completion_executor& e) noexcept +{ + base_type::operator=(static_cast<const base_type&>(e)); + return *this; +} + +any_completion_executor& any_completion_executor::operator=( + any_completion_executor&& e) noexcept +{ + base_type::operator=(static_cast<base_type&&>(e)); + return *this; +} + +any_completion_executor& any_completion_executor::operator=(nullptr_t) +{ + base_type::operator=(nullptr_t()); + return *this; +} + +any_completion_executor::~any_completion_executor() +{ +} + +void any_completion_executor::swap( + any_completion_executor& other) noexcept +{ + static_cast<base_type&>(*this).swap(static_cast<base_type&>(other)); +} + +template <> +any_completion_executor any_completion_executor::prefer( + const execution::outstanding_work_t::tracked_t& p, int) const +{ + return static_cast<const base_type&>(*this).prefer(p); +} + +template <> +any_completion_executor any_completion_executor::prefer( + const execution::outstanding_work_t::untracked_t& p, int) const +{ + return static_cast<const base_type&>(*this).prefer(p); +} + +template <> +any_completion_executor any_completion_executor::prefer( + const execution::relationship_t::fork_t& p, int) const +{ + return static_cast<const base_type&>(*this).prefer(p); +} + +template <> +any_completion_executor any_completion_executor::prefer( + const execution::relationship_t::continuation_t& p, int) const +{ + return static_cast<const base_type&>(*this).prefer(p); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) + +#endif // ASIO_IMPL_ANY_COMPLETION_EXECUTOR_IPP diff --git a/3rdparty/asio/include/asio/impl/any_io_executor.ipp b/3rdparty/asio/include/asio/impl/any_io_executor.ipp new file mode 100644 index 00000000000..338ad4d3ae2 --- /dev/null +++ b/3rdparty/asio/include/asio/impl/any_io_executor.ipp @@ -0,0 +1,134 @@ +// +// impl/any_io_executor.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_ANY_IO_EXECUTOR_IPP +#define ASIO_IMPL_ANY_IO_EXECUTOR_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) + +#include "asio/any_io_executor.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +any_io_executor::any_io_executor() noexcept + : base_type() +{ +} + +any_io_executor::any_io_executor(nullptr_t) noexcept + : base_type(nullptr_t()) +{ +} + +any_io_executor::any_io_executor(const any_io_executor& e) noexcept + : base_type(static_cast<const base_type&>(e)) +{ +} + +any_io_executor::any_io_executor(std::nothrow_t, + const any_io_executor& e) noexcept + : base_type(static_cast<const base_type&>(e)) +{ +} + +any_io_executor::any_io_executor(any_io_executor&& e) noexcept + : base_type(static_cast<base_type&&>(e)) +{ +} + +any_io_executor::any_io_executor(std::nothrow_t, any_io_executor&& e) noexcept + : base_type(static_cast<base_type&&>(e)) +{ +} + +any_io_executor& any_io_executor::operator=(const any_io_executor& e) noexcept +{ + base_type::operator=(static_cast<const base_type&>(e)); + return *this; +} + +any_io_executor& any_io_executor::operator=(any_io_executor&& e) noexcept +{ + base_type::operator=(static_cast<base_type&&>(e)); + return *this; +} + +any_io_executor& any_io_executor::operator=(nullptr_t) +{ + base_type::operator=(nullptr_t()); + return *this; +} + +any_io_executor::~any_io_executor() +{ +} + +void any_io_executor::swap(any_io_executor& other) noexcept +{ + static_cast<base_type&>(*this).swap(static_cast<base_type&>(other)); +} + +template <> +any_io_executor any_io_executor::require( + const execution::blocking_t::never_t& p, int) const +{ + return static_cast<const base_type&>(*this).require(p); +} + +template <> +any_io_executor any_io_executor::prefer( + const execution::blocking_t::possibly_t& p, int) const +{ + return static_cast<const base_type&>(*this).prefer(p); +} + +template <> +any_io_executor any_io_executor::prefer( + const execution::outstanding_work_t::tracked_t& p, int) const +{ + return static_cast<const base_type&>(*this).prefer(p); +} + +template <> +any_io_executor any_io_executor::prefer( + const execution::outstanding_work_t::untracked_t& p, int) const +{ + return static_cast<const base_type&>(*this).prefer(p); +} + +template <> +any_io_executor any_io_executor::prefer( + const execution::relationship_t::fork_t& p, int) const +{ + return static_cast<const base_type&>(*this).prefer(p); +} + +template <> +any_io_executor any_io_executor::prefer( + const execution::relationship_t::continuation_t& p, int) const +{ + return static_cast<const base_type&>(*this).prefer(p); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) + +#endif // ASIO_IMPL_ANY_IO_EXECUTOR_IPP diff --git a/3rdparty/asio/include/asio/impl/append.hpp b/3rdparty/asio/include/asio/impl/append.hpp new file mode 100644 index 00000000000..cfa54191fcd --- /dev/null +++ b/3rdparty/asio/include/asio/impl/append.hpp @@ -0,0 +1,162 @@ +// +// impl/append.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_APPEND_HPP +#define ASIO_IMPL_APPEND_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/associator.hpp" +#include "asio/async_result.hpp" +#include "asio/detail/handler_cont_helpers.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/detail/utility.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Class to adapt an append_t as a completion handler. +template <typename Handler, typename... Values> +class append_handler +{ +public: + typedef void result_type; + + template <typename H> + append_handler(H&& handler, std::tuple<Values...> values) + : handler_(static_cast<H&&>(handler)), + values_(static_cast<std::tuple<Values...>&&>(values)) + { + } + + template <typename... Args> + void operator()(Args&&... args) + { + this->invoke( + index_sequence_for<Values...>{}, + static_cast<Args&&>(args)...); + } + + template <std::size_t... I, typename... Args> + void invoke(index_sequence<I...>, Args&&... args) + { + static_cast<Handler&&>(handler_)( + static_cast<Args&&>(args)..., + static_cast<Values&&>(std::get<I>(values_))...); + } + +//private: + Handler handler_; + std::tuple<Values...> values_; +}; + +template <typename Handler> +inline bool asio_handler_is_continuation( + append_handler<Handler>* this_handler) +{ + return asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Signature, typename... Values> +struct append_signature; + +template <typename R, typename... Args, typename... Values> +struct append_signature<R(Args...), Values...> +{ + typedef R type(decay_t<Args>..., Values...); +}; + +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename CompletionToken, typename... Values, typename Signature> +struct async_result<append_t<CompletionToken, Values...>, Signature> + : async_result<CompletionToken, + typename detail::append_signature< + Signature, Values...>::type> +{ + typedef typename detail::append_signature< + Signature, Values...>::type signature; + + template <typename Initiation> + struct init_wrapper + { + init_wrapper(Initiation init) + : initiation_(static_cast<Initiation&&>(init)) + { + } + + template <typename Handler, typename... Args> + void operator()(Handler&& handler, + std::tuple<Values...> values, Args&&... args) + { + static_cast<Initiation&&>(initiation_)( + detail::append_handler<decay_t<Handler>, Values...>( + static_cast<Handler&&>(handler), + static_cast<std::tuple<Values...>&&>(values)), + static_cast<Args&&>(args)...); + } + + Initiation initiation_; + }; + + template <typename Initiation, typename RawCompletionToken, typename... Args> + static auto initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) + -> decltype( + async_initiate<CompletionToken, signature>( + declval<init_wrapper<decay_t<Initiation>>>(), + token.token_, + static_cast<std::tuple<Values...>&&>(token.values_), + static_cast<Args&&>(args)...)) + { + return async_initiate<CompletionToken, signature>( + init_wrapper<decay_t<Initiation>>( + static_cast<Initiation&&>(initiation)), + token.token_, + static_cast<std::tuple<Values...>&&>(token.values_), + static_cast<Args&&>(args)...); + } +}; + +template <template <typename, typename> class Associator, + typename Handler, typename... Values, typename DefaultCandidate> +struct associator<Associator, + detail::append_handler<Handler, Values...>, DefaultCandidate> + : Associator<Handler, DefaultCandidate> +{ + static typename Associator<Handler, DefaultCandidate>::type get( + const detail::append_handler<Handler, Values...>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::append_handler<Handler, Values...>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) + { + return Associator<Handler, DefaultCandidate>::get(h.handler_, c); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_APPEND_HPP diff --git a/3rdparty/asio/include/asio/impl/as_tuple.hpp b/3rdparty/asio/include/asio/impl/as_tuple.hpp new file mode 100644 index 00000000000..6d47510b997 --- /dev/null +++ b/3rdparty/asio/include/asio/impl/as_tuple.hpp @@ -0,0 +1,245 @@ +// +// impl/as_tuple.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_AS_TUPLE_HPP +#define ASIO_IMPL_AS_TUPLE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <tuple> +#include "asio/associator.hpp" +#include "asio/async_result.hpp" +#include "asio/detail/handler_cont_helpers.hpp" +#include "asio/detail/type_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Class to adapt a as_tuple_t as a completion handler. +template <typename Handler> +class as_tuple_handler +{ +public: + typedef void result_type; + + template <typename CompletionToken> + as_tuple_handler(as_tuple_t<CompletionToken> e) + : handler_(static_cast<CompletionToken&&>(e.token_)) + { + } + + template <typename RedirectedHandler> + as_tuple_handler(RedirectedHandler&& h) + : handler_(static_cast<RedirectedHandler&&>(h)) + { + } + + template <typename... Args> + void operator()(Args&&... args) + { + static_cast<Handler&&>(handler_)( + std::make_tuple(static_cast<Args&&>(args)...)); + } + +//private: + Handler handler_; +}; + +template <typename Handler> +inline bool asio_handler_is_continuation( + as_tuple_handler<Handler>* this_handler) +{ + return asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Signature> +struct as_tuple_signature; + +template <typename R, typename... Args> +struct as_tuple_signature<R(Args...)> +{ + typedef R type(std::tuple<decay_t<Args>...>); +}; + +template <typename R, typename... Args> +struct as_tuple_signature<R(Args...) &> +{ + typedef R type(std::tuple<decay_t<Args>...>) &; +}; + +template <typename R, typename... Args> +struct as_tuple_signature<R(Args...) &&> +{ + typedef R type(std::tuple<decay_t<Args>...>) &&; +}; + +#if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) + +template <typename R, typename... Args> +struct as_tuple_signature<R(Args...) noexcept> +{ + typedef R type(std::tuple<decay_t<Args>...>) noexcept; +}; + +template <typename R, typename... Args> +struct as_tuple_signature<R(Args...) & noexcept> +{ + typedef R type(std::tuple<decay_t<Args>...>) & noexcept; +}; + +template <typename R, typename... Args> +struct as_tuple_signature<R(Args...) && noexcept> +{ + typedef R type(std::tuple<decay_t<Args>...>) && noexcept; +}; + +#endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) + +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename CompletionToken, typename... Signatures> +struct async_result<as_tuple_t<CompletionToken>, Signatures...> + : async_result<CompletionToken, + typename detail::as_tuple_signature<Signatures>::type...> +{ + template <typename Initiation> + struct init_wrapper + { + init_wrapper(Initiation init) + : initiation_(static_cast<Initiation&&>(init)) + { + } + + template <typename Handler, typename... Args> + void operator()(Handler&& handler, Args&&... args) + { + static_cast<Initiation&&>(initiation_)( + detail::as_tuple_handler<decay_t<Handler>>( + static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); + } + + Initiation initiation_; + }; + + template <typename Initiation, typename RawCompletionToken, typename... Args> + static auto initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) + -> decltype( + async_initiate< + conditional_t< + is_const<remove_reference_t<RawCompletionToken>>::value, + const CompletionToken, CompletionToken>, + typename detail::as_tuple_signature<Signatures>::type...>( + init_wrapper<decay_t<Initiation>>( + static_cast<Initiation&&>(initiation)), + token.token_, static_cast<Args&&>(args)...)) + { + return async_initiate< + conditional_t< + is_const<remove_reference_t<RawCompletionToken>>::value, + const CompletionToken, CompletionToken>, + typename detail::as_tuple_signature<Signatures>::type...>( + init_wrapper<decay_t<Initiation>>( + static_cast<Initiation&&>(initiation)), + token.token_, static_cast<Args&&>(args)...); + } +}; + +#if defined(ASIO_MSVC) + +// Workaround for MSVC internal compiler error. + +template <typename CompletionToken, typename Signature> +struct async_result<as_tuple_t<CompletionToken>, Signature> + : async_result<CompletionToken, + typename detail::as_tuple_signature<Signature>::type> +{ + template <typename Initiation> + struct init_wrapper + { + init_wrapper(Initiation init) + : initiation_(static_cast<Initiation&&>(init)) + { + } + + template <typename Handler, typename... Args> + void operator()(Handler&& handler, Args&&... args) + { + static_cast<Initiation&&>(initiation_)( + detail::as_tuple_handler<decay_t<Handler>>( + static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); + } + + Initiation initiation_; + }; + + template <typename Initiation, typename RawCompletionToken, typename... Args> + static auto initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) + -> decltype( + async_initiate< + conditional_t< + is_const<remove_reference_t<RawCompletionToken>>::value, + const CompletionToken, CompletionToken>, + typename detail::as_tuple_signature<Signature>::type>( + init_wrapper<decay_t<Initiation>>( + static_cast<Initiation&&>(initiation)), + token.token_, static_cast<Args&&>(args)...)) + { + return async_initiate< + conditional_t< + is_const<remove_reference_t<RawCompletionToken>>::value, + const CompletionToken, CompletionToken>, + typename detail::as_tuple_signature<Signature>::type>( + init_wrapper<decay_t<Initiation>>( + static_cast<Initiation&&>(initiation)), + token.token_, static_cast<Args&&>(args)...); + } +}; + +#endif // defined(ASIO_MSVC) + +template <template <typename, typename> class Associator, + typename Handler, typename DefaultCandidate> +struct associator<Associator, + detail::as_tuple_handler<Handler>, DefaultCandidate> + : Associator<Handler, DefaultCandidate> +{ + static typename Associator<Handler, DefaultCandidate>::type get( + const detail::as_tuple_handler<Handler>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::as_tuple_handler<Handler>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) + { + return Associator<Handler, DefaultCandidate>::get(h.handler_, c); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_AS_TUPLE_HPP diff --git a/3rdparty/asio/include/asio/impl/awaitable.hpp b/3rdparty/asio/include/asio/impl/awaitable.hpp index 598b00baf68..c5ea2649171 100644 --- a/3rdparty/asio/include/asio/impl/awaitable.hpp +++ b/3rdparty/asio/include/asio/impl/awaitable.hpp @@ -2,7 +2,7 @@ // impl/awaitable.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,7 +19,6 @@ #include <exception> #include <new> #include <tuple> -#include <utility> #include "asio/cancellation_signal.hpp" #include "asio/cancellation_state.hpp" #include "asio/detail/thread_context.hpp" @@ -31,12 +30,20 @@ #include "asio/system_error.hpp" #include "asio/this_coro.hpp" +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) +# include "asio/detail/source_location.hpp" +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + #include "asio/detail/push_options.hpp" namespace asio { namespace detail { struct awaitable_thread_has_context_switched {}; +template <typename, typename> class awaitable_async_op_handler; +template <typename, typename, typename> class awaitable_async_op; // An awaitable_thread represents a thread-of-execution that is composed of one // or more "stack frames", with each frame represented by an awaitable_frame. @@ -162,10 +169,35 @@ public: { if (attached_thread_->entry_point()->throw_if_cancelled_) if (!!attached_thread_->get_cancellation_state().cancelled()) - do_throw_error(asio::error::operation_aborted, "co_await"); + throw_error(asio::error::operation_aborted, "co_await"); return a; } + template <typename Op> + auto await_transform(Op&& op, + constraint_t<is_async_operation<Op>::value> = 0 +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + , detail::source_location location = detail::source_location::current() +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + ) + { + if (attached_thread_->entry_point()->throw_if_cancelled_) + if (!!attached_thread_->get_cancellation_state().cancelled()) + throw_error(asio::error::operation_aborted, "co_await"); + + return awaitable_async_op< + completion_signature_of_t<Op>, decay_t<Op>, Executor>{ + std::forward<Op>(op), this +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + , location +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + }; + } + // This await transformation obtains the associated executor of the thread of // execution. auto await_transform(this_coro::executor_t) noexcept @@ -265,11 +297,11 @@ public: auto await_resume() { return this_->attached_thread_->reset_cancellation_state( - ASIO_MOVE_CAST(Filter)(filter_)); + static_cast<Filter&&>(filter_)); } }; - return result{this, ASIO_MOVE_CAST(Filter)(reset.filter)}; + return result{this, static_cast<Filter&&>(reset.filter)}; } // This await transformation resets the associated cancellation state. @@ -296,14 +328,14 @@ public: auto await_resume() { return this_->attached_thread_->reset_cancellation_state( - ASIO_MOVE_CAST(InFilter)(in_filter_), - ASIO_MOVE_CAST(OutFilter)(out_filter_)); + static_cast<InFilter&&>(in_filter_), + static_cast<OutFilter&&>(out_filter_)); } }; return result{this, - ASIO_MOVE_CAST(InFilter)(reset.in_filter), - ASIO_MOVE_CAST(OutFilter)(reset.out_filter)}; + static_cast<InFilter&&>(reset.in_filter), + static_cast<OutFilter&&>(reset.out_filter)}; } // This await transformation determines whether cancellation is propagated as @@ -367,12 +399,12 @@ public: // race condition. template <typename Function> auto await_transform(Function f, - typename enable_if< + enable_if_t< is_convertible< - typename result_of<Function(awaitable_frame_base*)>::type, + result_of_t<Function(awaitable_frame_base*)>, awaitable_thread<Executor>* >::value - >::type* = 0) + >* = nullptr) { struct result { @@ -386,7 +418,12 @@ public: void await_suspend(coroutine_handle<void>) noexcept { - function_(this_); + this_->after_suspend( + [](void* arg) + { + result* r = static_cast<result*>(arg); + r->function_(r->this_); + }, this); } void await_resume() const noexcept @@ -450,9 +487,25 @@ public: caller_ = nullptr; } + struct resume_context + { + void (*after_suspend_fn_)(void*) = nullptr; + void *after_suspend_arg_ = nullptr; + }; + void resume() { + resume_context context; + resume_context_ = &context; coro_.resume(); + if (context.after_suspend_fn_) + context.after_suspend_fn_(context.after_suspend_arg_); + } + + void after_suspend(void (*fn)(void*), void* arg) + { + resume_context_->after_suspend_fn_ = fn; + resume_context_->after_suspend_arg_ = arg; } void destroy() @@ -465,6 +518,7 @@ protected: awaitable_thread<Executor>* attached_thread_ = nullptr; awaitable_frame_base<Executor>* caller_ = nullptr; std::exception_ptr pending_exception_ = nullptr; + resume_context* resume_context_ = nullptr; }; template <typename T, typename Executor> @@ -484,7 +538,7 @@ public: ~awaitable_frame() { if (has_result_) - static_cast<T*>(static_cast<void*>(result_))->~T(); + std::launder(static_cast<T*>(static_cast<void*>(result_)))->~T(); } awaitable<T, Executor> get_return_object() noexcept @@ -510,7 +564,8 @@ public: { this->caller_ = nullptr; this->rethrow_exception(); - return std::move(*static_cast<T*>(static_cast<void*>(result_))); + return std::move(*std::launder( + static_cast<T*>(static_cast<void*>(result_)))); } private: @@ -579,6 +634,7 @@ public: private: template <typename> friend class awaitable_frame_base; + template <typename, typename> friend class awaitable_async_op_handler; template <typename, typename> friend class awaitable_handler_base; template <typename> friend class awaitable_thread; @@ -663,21 +719,21 @@ public: } template <typename Filter> - void reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter) + void reset_cancellation_state(Filter&& filter) { bottom_of_stack_.frame_->cancellation_state_ = cancellation_state(bottom_of_stack_.frame_->parent_cancellation_slot_, - ASIO_MOVE_CAST(Filter)(filter)); + static_cast<Filter&&>(filter)); } template <typename InFilter, typename OutFilter> - void reset_cancellation_state(ASIO_MOVE_ARG(InFilter) in_filter, - ASIO_MOVE_ARG(OutFilter) out_filter) + void reset_cancellation_state(InFilter&& in_filter, + OutFilter&& out_filter) { bottom_of_stack_.frame_->cancellation_state_ = cancellation_state(bottom_of_stack_.frame_->parent_cancellation_slot_, - ASIO_MOVE_CAST(InFilter)(in_filter), - ASIO_MOVE_CAST(OutFilter)(out_filter)); + static_cast<InFilter&&>(in_filter), + static_cast<OutFilter&&>(out_filter)); } bool throw_if_cancelled() const @@ -724,6 +780,386 @@ protected: awaitable<awaitable_thread_entry_point, Executor> bottom_of_stack_; }; +template <typename Signature, typename Executor> +class awaitable_async_op_handler; + +template <typename R, typename Executor> +class awaitable_async_op_handler<R(), Executor> + : public awaitable_thread<Executor> +{ +public: + struct result_type {}; + + awaitable_async_op_handler( + awaitable_thread<Executor>* h, result_type&) + : awaitable_thread<Executor>(std::move(*h)) + { + } + + void operator()() + { + this->entry_point()->top_of_stack_->attach_thread(this); + this->entry_point()->top_of_stack_->clear_cancellation_slot(); + this->pump(); + } + + static void resume(result_type&) + { + } +}; + +template <typename R, typename Executor> +class awaitable_async_op_handler<R(asio::error_code), Executor> + : public awaitable_thread<Executor> +{ +public: + typedef asio::error_code* result_type; + + awaitable_async_op_handler( + awaitable_thread<Executor>* h, result_type& result) + : awaitable_thread<Executor>(std::move(*h)), + result_(result) + { + } + + void operator()(asio::error_code ec) + { + result_ = &ec; + this->entry_point()->top_of_stack_->attach_thread(this); + this->entry_point()->top_of_stack_->clear_cancellation_slot(); + this->pump(); + } + + static void resume(result_type& result) + { + throw_error(*result); + } + +private: + result_type& result_; +}; + +template <typename R, typename Executor> +class awaitable_async_op_handler<R(std::exception_ptr), Executor> + : public awaitable_thread<Executor> +{ +public: + typedef std::exception_ptr* result_type; + + awaitable_async_op_handler( + awaitable_thread<Executor>* h, result_type& result) + : awaitable_thread<Executor>(std::move(*h)), + result_(result) + { + } + + void operator()(std::exception_ptr ex) + { + result_ = &ex; + this->entry_point()->top_of_stack_->attach_thread(this); + this->entry_point()->top_of_stack_->clear_cancellation_slot(); + this->pump(); + } + + static void resume(result_type& result) + { + if (*result) + { + std::exception_ptr ex = std::exchange(*result, nullptr); + std::rethrow_exception(ex); + } + } + +private: + result_type& result_; +}; + +template <typename R, typename T, typename Executor> +class awaitable_async_op_handler<R(T), Executor> + : public awaitable_thread<Executor> +{ +public: + typedef T* result_type; + + awaitable_async_op_handler( + awaitable_thread<Executor>* h, result_type& result) + : awaitable_thread<Executor>(std::move(*h)), + result_(result) + { + } + + void operator()(T result) + { + result_ = &result; + this->entry_point()->top_of_stack_->attach_thread(this); + this->entry_point()->top_of_stack_->clear_cancellation_slot(); + this->pump(); + } + + static T resume(result_type& result) + { + return std::move(*result); + } + +private: + result_type& result_; +}; + +template <typename R, typename T, typename Executor> +class awaitable_async_op_handler<R(asio::error_code, T), Executor> + : public awaitable_thread<Executor> +{ +public: + struct result_type + { + asio::error_code* ec_; + T* value_; + }; + + awaitable_async_op_handler( + awaitable_thread<Executor>* h, result_type& result) + : awaitable_thread<Executor>(std::move(*h)), + result_(result) + { + } + + void operator()(asio::error_code ec, T value) + { + result_.ec_ = &ec; + result_.value_ = &value; + this->entry_point()->top_of_stack_->attach_thread(this); + this->entry_point()->top_of_stack_->clear_cancellation_slot(); + this->pump(); + } + + static T resume(result_type& result) + { + throw_error(*result.ec_); + return std::move(*result.value_); + } + +private: + result_type& result_; +}; + +template <typename R, typename T, typename Executor> +class awaitable_async_op_handler<R(std::exception_ptr, T), Executor> + : public awaitable_thread<Executor> +{ +public: + struct result_type + { + std::exception_ptr* ex_; + T* value_; + }; + + awaitable_async_op_handler( + awaitable_thread<Executor>* h, result_type& result) + : awaitable_thread<Executor>(std::move(*h)), + result_(result) + { + } + + void operator()(std::exception_ptr ex, T value) + { + result_.ex_ = &ex; + result_.value_ = &value; + this->entry_point()->top_of_stack_->attach_thread(this); + this->entry_point()->top_of_stack_->clear_cancellation_slot(); + this->pump(); + } + + static T resume(result_type& result) + { + if (*result.ex_) + { + std::exception_ptr ex = std::exchange(*result.ex_, nullptr); + std::rethrow_exception(ex); + } + return std::move(*result.value_); + } + +private: + result_type& result_; +}; + +template <typename R, typename... Ts, typename Executor> +class awaitable_async_op_handler<R(Ts...), Executor> + : public awaitable_thread<Executor> +{ +public: + typedef std::tuple<Ts...>* result_type; + + awaitable_async_op_handler( + awaitable_thread<Executor>* h, result_type& result) + : awaitable_thread<Executor>(std::move(*h)), + result_(result) + { + } + + template <typename... Args> + void operator()(Args&&... args) + { + std::tuple<Ts...> result(std::forward<Args>(args)...); + result_ = &result; + this->entry_point()->top_of_stack_->attach_thread(this); + this->entry_point()->top_of_stack_->clear_cancellation_slot(); + this->pump(); + } + + static std::tuple<Ts...> resume(result_type& result) + { + return std::move(*result); + } + +private: + result_type& result_; +}; + +template <typename R, typename... Ts, typename Executor> +class awaitable_async_op_handler<R(asio::error_code, Ts...), Executor> + : public awaitable_thread<Executor> +{ +public: + struct result_type + { + asio::error_code* ec_; + std::tuple<Ts...>* value_; + }; + + awaitable_async_op_handler( + awaitable_thread<Executor>* h, result_type& result) + : awaitable_thread<Executor>(std::move(*h)), + result_(result) + { + } + + template <typename... Args> + void operator()(asio::error_code ec, Args&&... args) + { + result_.ec_ = &ec; + std::tuple<Ts...> value(std::forward<Args>(args)...); + result_.value_ = &value; + this->entry_point()->top_of_stack_->attach_thread(this); + this->entry_point()->top_of_stack_->clear_cancellation_slot(); + this->pump(); + } + + static std::tuple<Ts...> resume(result_type& result) + { + throw_error(*result.ec_); + return std::move(*result.value_); + } + +private: + result_type& result_; +}; + +template <typename R, typename... Ts, typename Executor> +class awaitable_async_op_handler<R(std::exception_ptr, Ts...), Executor> + : public awaitable_thread<Executor> +{ +public: + struct result_type + { + std::exception_ptr* ex_; + std::tuple<Ts...>* value_; + }; + + awaitable_async_op_handler( + awaitable_thread<Executor>* h, result_type& result) + : awaitable_thread<Executor>(std::move(*h)), + result_(result) + { + } + + template <typename... Args> + void operator()(std::exception_ptr ex, Args&&... args) + { + result_.ex_ = &ex; + std::tuple<Ts...> value(std::forward<Args>(args)...); + result_.value_ = &value; + this->entry_point()->top_of_stack_->attach_thread(this); + this->entry_point()->top_of_stack_->clear_cancellation_slot(); + this->pump(); + } + + static std::tuple<Ts...> resume(result_type& result) + { + if (*result.ex_) + { + std::exception_ptr ex = std::exchange(*result.ex_, nullptr); + std::rethrow_exception(ex); + } + return std::move(*result.value_); + } + +private: + result_type& result_; +}; + +template <typename Signature, typename Op, typename Executor> +class awaitable_async_op +{ +public: + typedef awaitable_async_op_handler<Signature, Executor> handler_type; + + awaitable_async_op(Op&& o, awaitable_frame_base<Executor>* frame +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + , const detail::source_location& location +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + ) + : op_(std::forward<Op>(o)), + frame_(frame), + result_() +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + , location_(location) +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + { + } + + bool await_ready() const noexcept + { + return false; + } + + void await_suspend(coroutine_handle<void>) + { + frame_->after_suspend( + [](void* arg) + { + awaitable_async_op* self = static_cast<awaitable_async_op*>(arg); +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + ASIO_HANDLER_LOCATION((self->location_.file_name(), + self->location_.line(), self->location_.function_name())); +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) + std::forward<Op&&>(self->op_)( + handler_type(self->frame_->detach_thread(), self->result_)); + }, this); + } + + auto await_resume() + { + return handler_type::resume(result_); + } + +private: + Op&& op_; + awaitable_frame_base<Executor>* frame_; + typename handler_type::result_type result_; +#if defined(ASIO_ENABLE_HANDLER_TRACKING) +# if defined(ASIO_HAS_SOURCE_LOCATION) + detail::source_location location_; +# endif // defined(ASIO_HAS_SOURCE_LOCATION) +#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) +}; + } // namespace detail } // namespace asio diff --git a/3rdparty/asio/include/asio/impl/buffered_read_stream.hpp b/3rdparty/asio/include/asio/impl/buffered_read_stream.hpp index a25beeedce0..9a1d78b465e 100644 --- a/3rdparty/asio/include/asio/impl/buffered_read_stream.hpp +++ b/3rdparty/asio/include/asio/impl/buffered_read_stream.hpp @@ -2,7 +2,7 @@ // impl/buffered_read_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/associator.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/type_traits.hpp" @@ -66,11 +64,10 @@ namespace detail std::size_t previous_size, ReadHandler& handler) : storage_(storage), previous_size_(previous_size), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) buffered_fill_handler(const buffered_fill_handler& other) : storage_(other.storage_), previous_size_(other.previous_size_), @@ -81,16 +78,15 @@ namespace detail buffered_fill_handler(buffered_fill_handler&& other) : storage_(other.storage_), previous_size_(other.previous_size_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(const asio::error_code& ec, const std::size_t bytes_transferred) { storage_.resize(previous_size_ + bytes_transferred); - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(ec, bytes_transferred); + static_cast<ReadHandler&&>(handler_)(ec, bytes_transferred); } //private: @@ -100,32 +96,6 @@ namespace detail }; template <typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - buffered_fill_handler<ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - buffered_fill_handler<ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename ReadHandler> inline bool asio_handler_is_continuation( buffered_fill_handler<ReadHandler>* this_handler) { @@ -133,50 +103,26 @@ namespace detail this_handler->handler_); } - template <typename Function, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - buffered_fill_handler<ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - buffered_fill_handler<ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename Stream> class initiate_async_buffered_fill { public: - typedef typename remove_reference< - Stream>::type::lowest_layer_type::executor_type executor_type; + typedef typename remove_reference_t< + Stream>::lowest_layer_type::executor_type executor_type; explicit initiate_async_buffered_fill( - typename remove_reference<Stream>::type& next_layer) + remove_reference_t<Stream>& next_layer) : next_layer_(next_layer) { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return next_layer_.lowest_layer().get_executor(); } template <typename ReadHandler> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, buffered_stream_storage* storage) const { // If you get an error on the following line it means that your handler @@ -190,12 +136,12 @@ namespace detail buffer( storage->data() + previous_size, storage->size() - previous_size), - buffered_fill_handler<typename decay<ReadHandler>::type>( + buffered_fill_handler<decay_t<ReadHandler>>( *storage, previous_size, handler2.value)); } private: - typename remove_reference<Stream>::type& next_layer_; + remove_reference_t<Stream>& next_layer_; }; } // namespace detail @@ -209,8 +155,14 @@ struct associator<Associator, : Associator<ReadHandler, DefaultCandidate> { static typename Associator<ReadHandler, DefaultCandidate>::type get( - const detail::buffered_fill_handler<ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::buffered_fill_handler<ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::buffered_fill_handler<ReadHandler>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -222,10 +174,12 @@ template <typename Stream> template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) ReadHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -buffered_read_stream<Stream>::async_fill( - ASIO_MOVE_ARG(ReadHandler) handler) +inline auto buffered_read_stream<Stream>::async_fill(ReadHandler&& handler) + -> decltype( + async_initiate<ReadHandler, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_buffered_fill<Stream>>(), + handler, declval<detail::buffered_stream_storage*>())) { return async_initiate<ReadHandler, void (asio::error_code, std::size_t)>( @@ -275,39 +229,37 @@ namespace detail const MutableBufferSequence& buffers, ReadHandler& handler) : storage_(storage), buffers_(buffers), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) - buffered_read_some_handler(const buffered_read_some_handler& other) - : storage_(other.storage_), - buffers_(other.buffers_), - handler_(other.handler_) - { - } + buffered_read_some_handler(const buffered_read_some_handler& other) + : storage_(other.storage_), + buffers_(other.buffers_), + handler_(other.handler_) + { + } - buffered_read_some_handler(buffered_read_some_handler&& other) - : storage_(other.storage_), - buffers_(other.buffers_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) - { - } -#endif // defined(ASIO_HAS_MOVE) + buffered_read_some_handler(buffered_read_some_handler&& other) + : storage_(other.storage_), + buffers_(other.buffers_), + handler_(static_cast<ReadHandler&&>(other.handler_)) + { + } void operator()(const asio::error_code& ec, std::size_t) { if (ec || storage_.empty()) { const std::size_t length = 0; - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(ec, length); + static_cast<ReadHandler&&>(handler_)(ec, length); } else { const std::size_t bytes_copied = asio::buffer_copy( buffers_, storage_.data(), storage_.size()); storage_.consume(bytes_copied); - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(ec, bytes_copied); + static_cast<ReadHandler&&>(handler_)(ec, bytes_copied); } } @@ -318,34 +270,6 @@ namespace detail }; template <typename MutableBufferSequence, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - buffered_read_some_handler< - MutableBufferSequence, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename MutableBufferSequence, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - buffered_read_some_handler< - MutableBufferSequence, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename MutableBufferSequence, typename ReadHandler> inline bool asio_handler_is_continuation( buffered_read_some_handler< MutableBufferSequence, ReadHandler>* this_handler) @@ -354,54 +278,26 @@ namespace detail this_handler->handler_); } - template <typename Function, typename MutableBufferSequence, - typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - buffered_read_some_handler< - MutableBufferSequence, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename MutableBufferSequence, - typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - buffered_read_some_handler< - MutableBufferSequence, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename Stream> class initiate_async_buffered_read_some { public: - typedef typename remove_reference< - Stream>::type::lowest_layer_type::executor_type executor_type; + typedef typename remove_reference_t< + Stream>::lowest_layer_type::executor_type executor_type; explicit initiate_async_buffered_read_some( - typename remove_reference<Stream>::type& next_layer) + remove_reference_t<Stream>& next_layer) : next_layer_(next_layer) { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return next_layer_.lowest_layer().get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, buffered_stream_storage* storage, const MutableBufferSequence& buffers) const { @@ -415,21 +311,21 @@ namespace detail { next_layer_.async_read_some(ASIO_MUTABLE_BUFFER(0, 0), buffered_read_some_handler<MutableBufferSequence, - typename decay<ReadHandler>::type>( + decay_t<ReadHandler>>( *storage, buffers, handler2.value)); } else { initiate_async_buffered_fill<Stream>(this->next_layer_)( buffered_read_some_handler<MutableBufferSequence, - typename decay<ReadHandler>::type>( + decay_t<ReadHandler>>( *storage, buffers, handler2.value), storage); } } private: - typename remove_reference<Stream>::type& next_layer_; + remove_reference_t<Stream>& next_layer_; }; } // namespace detail @@ -445,8 +341,16 @@ struct associator<Associator, { static typename Associator<ReadHandler, DefaultCandidate>::type get( const detail::buffered_read_some_handler< + MutableBufferSequence, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::buffered_read_some_handler< MutableBufferSequence, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -458,11 +362,13 @@ template <typename Stream> template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) ReadHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -buffered_read_stream<Stream>::async_read_some( - const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler) +inline auto buffered_read_stream<Stream>::async_read_some( + const MutableBufferSequence& buffers, ReadHandler&& handler) + -> decltype( + async_initiate<ReadHandler, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_buffered_read_some<Stream>>(), + handler, declval<detail::buffered_stream_storage*>(), buffers)) { return async_initiate<ReadHandler, void (asio::error_code, std::size_t)>( diff --git a/3rdparty/asio/include/asio/impl/buffered_write_stream.hpp b/3rdparty/asio/include/asio/impl/buffered_write_stream.hpp index efb30a684c9..5bf58278ca6 100644 --- a/3rdparty/asio/include/asio/impl/buffered_write_stream.hpp +++ b/3rdparty/asio/include/asio/impl/buffered_write_stream.hpp @@ -2,7 +2,7 @@ // impl/buffered_write_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/associator.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/non_const_lvalue.hpp" @@ -54,11 +52,10 @@ namespace detail buffered_flush_handler(detail::buffered_stream_storage& storage, WriteHandler& handler) : storage_(storage), - handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + handler_(static_cast<WriteHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) buffered_flush_handler(const buffered_flush_handler& other) : storage_(other.storage_), handler_(other.handler_) @@ -67,16 +64,15 @@ namespace detail buffered_flush_handler(buffered_flush_handler&& other) : storage_(other.storage_), - handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + handler_(static_cast<WriteHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(const asio::error_code& ec, const std::size_t bytes_written) { storage_.consume(bytes_written); - ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_written); + static_cast<WriteHandler&&>(handler_)(ec, bytes_written); } //private: @@ -85,32 +81,6 @@ namespace detail }; template <typename WriteHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - buffered_flush_handler<WriteHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename WriteHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - buffered_flush_handler<WriteHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename WriteHandler> inline bool asio_handler_is_continuation( buffered_flush_handler<WriteHandler>* this_handler) { @@ -118,50 +88,26 @@ namespace detail this_handler->handler_); } - template <typename Function, typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - buffered_flush_handler<WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - buffered_flush_handler<WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename Stream> class initiate_async_buffered_flush { public: - typedef typename remove_reference< - Stream>::type::lowest_layer_type::executor_type executor_type; + typedef typename remove_reference_t< + Stream>::lowest_layer_type::executor_type executor_type; explicit initiate_async_buffered_flush( - typename remove_reference<Stream>::type& next_layer) + remove_reference_t<Stream>& next_layer) : next_layer_(next_layer) { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return next_layer_.lowest_layer().get_executor(); } template <typename WriteHandler> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, buffered_stream_storage* storage) const { // If you get an error on the following line it means that your handler @@ -170,12 +116,12 @@ namespace detail non_const_lvalue<WriteHandler> handler2(handler); async_write(next_layer_, buffer(storage->data(), storage->size()), - buffered_flush_handler<typename decay<WriteHandler>::type>( + buffered_flush_handler<decay_t<WriteHandler>>( *storage, handler2.value)); } private: - typename remove_reference<Stream>::type& next_layer_; + remove_reference_t<Stream>& next_layer_; }; } // namespace detail @@ -189,8 +135,14 @@ struct associator<Associator, : Associator<WriteHandler, DefaultCandidate> { static typename Associator<WriteHandler, DefaultCandidate>::type get( - const detail::buffered_flush_handler<WriteHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::buffered_flush_handler<WriteHandler>& h) noexcept + { + return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::buffered_flush_handler<WriteHandler>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } @@ -202,10 +154,12 @@ template <typename Stream> template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) WriteHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -buffered_write_stream<Stream>::async_flush( - ASIO_MOVE_ARG(WriteHandler) handler) +inline auto buffered_write_stream<Stream>::async_flush(WriteHandler&& handler) + -> decltype( + async_initiate<WriteHandler, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_buffered_flush<Stream>>(), + handler, declval<detail::buffered_stream_storage*>())) { return async_initiate<WriteHandler, void (asio::error_code, std::size_t)>( @@ -255,32 +209,30 @@ namespace detail const ConstBufferSequence& buffers, WriteHandler& handler) : storage_(storage), buffers_(buffers), - handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + handler_(static_cast<WriteHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) - buffered_write_some_handler(const buffered_write_some_handler& other) - : storage_(other.storage_), - buffers_(other.buffers_), - handler_(other.handler_) - { - } + buffered_write_some_handler(const buffered_write_some_handler& other) + : storage_(other.storage_), + buffers_(other.buffers_), + handler_(other.handler_) + { + } - buffered_write_some_handler(buffered_write_some_handler&& other) - : storage_(other.storage_), - buffers_(other.buffers_), - handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) - { - } -#endif // defined(ASIO_HAS_MOVE) + buffered_write_some_handler(buffered_write_some_handler&& other) + : storage_(other.storage_), + buffers_(other.buffers_), + handler_(static_cast<WriteHandler&&>(other.handler_)) + { + } void operator()(const asio::error_code& ec, std::size_t) { if (ec) { const std::size_t length = 0; - ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, length); + static_cast<WriteHandler&&>(handler_)(ec, length); } else { @@ -293,7 +245,7 @@ namespace detail storage_.resize(orig_size + length); const std::size_t bytes_copied = asio::buffer_copy( storage_.data() + orig_size, buffers_, length); - ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_copied); + static_cast<WriteHandler&&>(handler_)(ec, bytes_copied); } } @@ -304,34 +256,6 @@ namespace detail }; template <typename ConstBufferSequence, typename WriteHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - buffered_write_some_handler< - ConstBufferSequence, WriteHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename ConstBufferSequence, typename WriteHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - buffered_write_some_handler< - ConstBufferSequence, WriteHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename ConstBufferSequence, typename WriteHandler> inline bool asio_handler_is_continuation( buffered_write_some_handler< ConstBufferSequence, WriteHandler>* this_handler) @@ -340,54 +264,26 @@ namespace detail this_handler->handler_); } - template <typename Function, typename ConstBufferSequence, - typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - buffered_write_some_handler< - ConstBufferSequence, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename ConstBufferSequence, - typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - buffered_write_some_handler< - ConstBufferSequence, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename Stream> class initiate_async_buffered_write_some { public: - typedef typename remove_reference< - Stream>::type::lowest_layer_type::executor_type executor_type; + typedef typename remove_reference_t< + Stream>::lowest_layer_type::executor_type executor_type; explicit initiate_async_buffered_write_some( - typename remove_reference<Stream>::type& next_layer) + remove_reference_t<Stream>& next_layer) : next_layer_(next_layer) { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return next_layer_.lowest_layer().get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, buffered_stream_storage* storage, const ConstBufferSequence& buffers) const { @@ -401,21 +297,21 @@ namespace detail { next_layer_.async_write_some(ASIO_CONST_BUFFER(0, 0), buffered_write_some_handler<ConstBufferSequence, - typename decay<WriteHandler>::type>( + decay_t<WriteHandler>>( *storage, buffers, handler2.value)); } else { initiate_async_buffered_flush<Stream>(this->next_layer_)( buffered_write_some_handler<ConstBufferSequence, - typename decay<WriteHandler>::type>( + decay_t<WriteHandler>>( *storage, buffers, handler2.value), storage); } } private: - typename remove_reference<Stream>::type& next_layer_; + remove_reference_t<Stream>& next_layer_; }; } // namespace detail @@ -431,8 +327,16 @@ struct associator<Associator, { static typename Associator<WriteHandler, DefaultCandidate>::type get( const detail::buffered_write_some_handler< + ConstBufferSequence, WriteHandler>& h) noexcept + { + return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::buffered_write_some_handler< ConstBufferSequence, WriteHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } @@ -444,11 +348,13 @@ template <typename Stream> template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, std::size_t)) WriteHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -buffered_write_stream<Stream>::async_write_some( - const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler) +inline auto buffered_write_stream<Stream>::async_write_some( + const ConstBufferSequence& buffers, WriteHandler&& handler) + -> decltype( + async_initiate<WriteHandler, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_buffered_write_some<Stream>>(), + handler, declval<detail::buffered_stream_storage*>(), buffers)) { return async_initiate<WriteHandler, void (asio::error_code, std::size_t)>( diff --git a/3rdparty/asio/include/asio/impl/cancellation_signal.ipp b/3rdparty/asio/include/asio/impl/cancellation_signal.ipp new file mode 100644 index 00000000000..f63ab8de0f3 --- /dev/null +++ b/3rdparty/asio/include/asio/impl/cancellation_signal.ipp @@ -0,0 +1,96 @@ +// +// impl/cancellation_signal.ipp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_CANCELLATION_SIGNAL_IPP +#define ASIO_IMPL_CANCELLATION_SIGNAL_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/cancellation_signal.hpp" +#include "asio/detail/thread_context.hpp" +#include "asio/detail/thread_info_base.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +cancellation_signal::~cancellation_signal() +{ + if (handler_) + { + std::pair<void*, std::size_t> mem = handler_->destroy(); + detail::thread_info_base::deallocate( + detail::thread_info_base::cancellation_signal_tag(), + detail::thread_context::top_of_thread_call_stack(), + mem.first, mem.second); + } +} + +void cancellation_slot::clear() +{ + if (handler_ != 0 && *handler_ != 0) + { + std::pair<void*, std::size_t> mem = (*handler_)->destroy(); + detail::thread_info_base::deallocate( + detail::thread_info_base::cancellation_signal_tag(), + detail::thread_context::top_of_thread_call_stack(), + mem.first, mem.second); + *handler_ = 0; + } +} + +std::pair<void*, std::size_t> cancellation_slot::prepare_memory( + std::size_t size, std::size_t align) +{ + assert(handler_); + std::pair<void*, std::size_t> mem; + if (*handler_) + { + mem = (*handler_)->destroy(); + *handler_ = 0; + } + if (size > mem.second + || reinterpret_cast<std::size_t>(mem.first) % align != 0) + { + if (mem.first) + { + detail::thread_info_base::deallocate( + detail::thread_info_base::cancellation_signal_tag(), + detail::thread_context::top_of_thread_call_stack(), + mem.first, mem.second); + } + mem.first = detail::thread_info_base::allocate( + detail::thread_info_base::cancellation_signal_tag(), + detail::thread_context::top_of_thread_call_stack(), + size, align); + mem.second = size; + } + return mem; +} + +cancellation_slot::auto_delete_helper::~auto_delete_helper() +{ + if (mem.first) + { + detail::thread_info_base::deallocate( + detail::thread_info_base::cancellation_signal_tag(), + detail::thread_context::top_of_thread_call_stack(), + mem.first, mem.second); + } +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_CANCELLATION_SIGNAL_IPP diff --git a/3rdparty/asio/include/asio/impl/co_spawn.hpp b/3rdparty/asio/include/asio/impl/co_spawn.hpp index b235e5c4495..3eba7d86db8 100644 --- a/3rdparty/asio/include/asio/impl/co_spawn.hpp +++ b/3rdparty/asio/include/asio/impl/co_spawn.hpp @@ -2,7 +2,7 @@ // impl/co_spawn.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,6 +18,8 @@ #include "asio/detail/config.hpp" #include "asio/associated_cancellation_slot.hpp" #include "asio/awaitable.hpp" +#include "asio/detail/memory.hpp" +#include "asio/detail/recycling_allocator.hpp" #include "asio/dispatch.hpp" #include "asio/execution/outstanding_work.hpp" #include "asio/post.hpp" @@ -33,18 +35,18 @@ template <typename Executor, typename = void> class co_spawn_work_guard { public: - typedef typename decay< - typename prefer_result<Executor, + typedef decay_t< + prefer_result_t<Executor, execution::outstanding_work_t::tracked_t - >::type - >::type executor_type; + > + > executor_type; co_spawn_work_guard(const Executor& ex) : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return executor_; } @@ -57,9 +59,9 @@ private: template <typename Executor> struct co_spawn_work_guard<Executor, - typename enable_if< + enable_if_t< !execution::is_executor<Executor>::value - >::type> : executor_work_guard<Executor> + >> : executor_work_guard<Executor> { co_spawn_work_guard(const Executor& ex) : executor_work_guard<Executor>(ex) @@ -69,50 +71,96 @@ struct co_spawn_work_guard<Executor, #endif // !defined(ASIO_NO_TS_EXECUTORS) -template <typename Executor> -inline co_spawn_work_guard<Executor> -make_co_spawn_work_guard(const Executor& ex) +template <typename Handler, typename Executor, + typename Function, typename = void> +struct co_spawn_state { - return co_spawn_work_guard<Executor>(ex); -} + template <typename H, typename F> + co_spawn_state(H&& h, const Executor& ex, F&& f) + : handler(std::forward<H>(h)), + spawn_work(ex), + handler_work(asio::get_associated_executor(handler, ex)), + function(std::forward<F>(f)) + { + } -template <typename T, typename Executor, typename F, typename Handler> -awaitable<awaitable_thread_entry_point, Executor> co_spawn_entry_point( - awaitable<T, Executor>*, Executor ex, F f, Handler handler) + Handler handler; + co_spawn_work_guard<Executor> spawn_work; + co_spawn_work_guard<associated_executor_t<Handler, Executor>> handler_work; + Function function; +}; + +template <typename Handler, typename Executor, typename Function> +struct co_spawn_state<Handler, Executor, Function, + enable_if_t< + is_same< + typename associated_executor<Handler, + Executor>::asio_associated_executor_is_unspecialised, + void + >::value + >> { - auto spawn_work = make_co_spawn_work_guard(ex); - auto handler_work = make_co_spawn_work_guard( - asio::get_associated_executor(handler, ex)); + template <typename H, typename F> + co_spawn_state(H&& h, const Executor& ex, F&& f) + : handler(std::forward<H>(h)), + handler_work(ex), + function(std::forward<F>(f)) + { + } - (void) co_await (dispatch)( - use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"}); + Handler handler; + co_spawn_work_guard<Executor> handler_work; + Function function; +}; + +struct co_spawn_dispatch +{ + template <typename CompletionToken> + auto operator()(CompletionToken&& token) const + -> decltype(asio::dispatch(std::forward<CompletionToken>(token))) + { + return asio::dispatch(std::forward<CompletionToken>(token)); + } +}; + +struct co_spawn_post +{ + template <typename CompletionToken> + auto operator()(CompletionToken&& token) const + -> decltype(asio::post(std::forward<CompletionToken>(token))) + { + return asio::post(std::forward<CompletionToken>(token)); + } +}; + +template <typename T, typename Handler, typename Executor, typename Function> +awaitable<awaitable_thread_entry_point, Executor> co_spawn_entry_point( + awaitable<T, Executor>*, co_spawn_state<Handler, Executor, Function> s) +{ + (void) co_await co_spawn_dispatch{}; (co_await awaitable_thread_has_context_switched{}) = false; std::exception_ptr e = nullptr; bool done = false; try { - T t = co_await f(); + T t = co_await s.function(); done = true; - if (co_await awaitable_thread_has_context_switched{}) + bool switched = (co_await awaitable_thread_has_context_switched{}); + if (!switched) { - (dispatch)(handler_work.get_executor(), - [handler = std::move(handler), t = std::move(t)]() mutable - { - std::move(handler)(std::exception_ptr(), std::move(t)); - }); - } - else - { - (post)(handler_work.get_executor(), - [handler = std::move(handler), t = std::move(t)]() mutable - { - std::move(handler)(std::exception_ptr(), std::move(t)); - }); + co_await this_coro::throw_if_cancelled(false); + (void) co_await co_spawn_post(); } + (dispatch)(s.handler_work.get_executor(), + [handler = std::move(s.handler), t = std::move(t)]() mutable + { + std::move(handler)(std::exception_ptr(), std::move(t)); + }); + co_return; } catch (...) @@ -123,62 +171,49 @@ awaitable<awaitable_thread_entry_point, Executor> co_spawn_entry_point( e = std::current_exception(); } - if (co_await awaitable_thread_has_context_switched{}) + bool switched = (co_await awaitable_thread_has_context_switched{}); + if (!switched) { - (dispatch)(handler_work.get_executor(), - [handler = std::move(handler), e]() mutable - { - std::move(handler)(e, T()); - }); - } - else - { - (post)(handler_work.get_executor(), - [handler = std::move(handler), e]() mutable - { - std::move(handler)(e, T()); - }); + co_await this_coro::throw_if_cancelled(false); + (void) co_await co_spawn_post(); } + + (dispatch)(s.handler_work.get_executor(), + [handler = std::move(s.handler), e]() mutable + { + std::move(handler)(e, T()); + }); } -template <typename Executor, typename F, typename Handler> +template <typename Handler, typename Executor, typename Function> awaitable<awaitable_thread_entry_point, Executor> co_spawn_entry_point( - awaitable<void, Executor>*, Executor ex, F f, Handler handler) + awaitable<void, Executor>*, co_spawn_state<Handler, Executor, Function> s) { - auto spawn_work = make_co_spawn_work_guard(ex); - auto handler_work = make_co_spawn_work_guard( - asio::get_associated_executor(handler, ex)); - - (void) co_await (dispatch)( - use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"}); + (void) co_await co_spawn_dispatch{}; (co_await awaitable_thread_has_context_switched{}) = false; std::exception_ptr e = nullptr; try { - co_await f(); + co_await s.function(); } catch (...) { e = std::current_exception(); } - if (co_await awaitable_thread_has_context_switched{}) + bool switched = (co_await awaitable_thread_has_context_switched{}); + if (!switched) { - (dispatch)(handler_work.get_executor(), - [handler = std::move(handler), e]() mutable - { - std::move(handler)(e); - }); - } - else - { - (post)(handler_work.get_executor(), - [handler = std::move(handler), e]() mutable - { - std::move(handler)(e); - }); + co_await this_coro::throw_if_cancelled(false); + (void) co_await co_spawn_post(); } + + (dispatch)(s.handler_work.get_executor(), + [handler = std::move(s.handler), e]() mutable + { + std::move(handler)(e); + }); } template <typename T, typename Executor> @@ -199,6 +234,63 @@ private: awaitable<T, Executor> awaitable_; }; +template <typename Handler, typename Executor, typename = void> +class co_spawn_cancellation_handler +{ +public: + co_spawn_cancellation_handler(const Handler&, const Executor& ex) + : signal_(detail::allocate_shared<cancellation_signal>( + detail::recycling_allocator<cancellation_signal, + detail::thread_info_base::cancellation_signal_tag>())), + ex_(ex) + { + } + + cancellation_slot slot() + { + return signal_->slot(); + } + + void operator()(cancellation_type_t type) + { + shared_ptr<cancellation_signal> sig = signal_; + asio::dispatch(ex_, [sig, type]{ sig->emit(type); }); + } + +private: + shared_ptr<cancellation_signal> signal_; + Executor ex_; +}; + +template <typename Handler, typename Executor> +class co_spawn_cancellation_handler<Handler, Executor, + enable_if_t< + is_same< + typename associated_executor<Handler, + Executor>::asio_associated_executor_is_unspecialised, + void + >::value + >> +{ +public: + co_spawn_cancellation_handler(const Handler&, const Executor&) + { + } + + cancellation_slot slot() + { + return signal_.slot(); + } + + void operator()(cancellation_type_t type) + { + signal_.emit(type); + } + +private: + cancellation_signal signal_; +}; + template <typename Executor> class initiate_co_spawn { @@ -211,7 +303,7 @@ public: { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return ex_; } @@ -219,18 +311,29 @@ public: template <typename Handler, typename F> void operator()(Handler&& handler, F&& f) const { - typedef typename result_of<F()>::type awaitable_type; + typedef result_of_t<F()> awaitable_type; + typedef decay_t<Handler> handler_type; + typedef decay_t<F> function_type; + typedef co_spawn_cancellation_handler< + handler_type, Executor> cancel_handler_type; + + auto slot = asio::get_associated_cancellation_slot(handler); + cancel_handler_type* cancel_handler = slot.is_connected() + ? &slot.template emplace<cancel_handler_type>(handler, ex_) + : nullptr; - cancellation_state proxy_cancel_state( - asio::get_associated_cancellation_slot(handler), - enable_total_cancellation()); + cancellation_slot proxy_slot( + cancel_handler + ? cancel_handler->slot() + : cancellation_slot()); - cancellation_state cancel_state(proxy_cancel_state.slot()); + cancellation_state cancel_state(proxy_slot); auto a = (co_spawn_entry_point)(static_cast<awaitable_type*>(nullptr), - ex_, std::forward<F>(f), std::forward<Handler>(handler)); - awaitable_handler<executor_type, void>(std::move(a), ex_, - proxy_cancel_state.slot(), cancel_state).launch(); + co_spawn_state<handler_type, Executor, function_type>( + std::forward<Handler>(handler), ex_, std::forward<F>(f))); + awaitable_handler<executor_type, void>(std::move(a), + ex_, proxy_slot, cancel_state).launch(); } private: @@ -246,10 +349,10 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE( CompletionToken, void(std::exception_ptr, T)) co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a, CompletionToken&& token, - typename constraint< + constraint_t< (is_executor<Executor>::value || execution::is_executor<Executor>::value) && is_convertible<Executor, AwaitableExecutor>::value - >::type) + >) { return async_initiate<CompletionToken, void(std::exception_ptr, T)>( detail::initiate_co_spawn<AwaitableExecutor>(AwaitableExecutor(ex)), @@ -263,10 +366,10 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE( CompletionToken, void(std::exception_ptr)) co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a, CompletionToken&& token, - typename constraint< + constraint_t< (is_executor<Executor>::value || execution::is_executor<Executor>::value) && is_convertible<Executor, AwaitableExecutor>::value - >::type) + >) { return async_initiate<CompletionToken, void(std::exception_ptr)>( detail::initiate_co_spawn<AwaitableExecutor>(AwaitableExecutor(ex)), @@ -281,11 +384,11 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE( CompletionToken, void(std::exception_ptr, T)) co_spawn(ExecutionContext& ctx, awaitable<T, AwaitableExecutor> a, CompletionToken&& token, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value && is_convertible<typename ExecutionContext::executor_type, AwaitableExecutor>::value - >::type) + >) { return (co_spawn)(ctx.get_executor(), std::move(a), std::forward<CompletionToken>(token)); @@ -298,11 +401,11 @@ inline ASIO_INITFN_AUTO_RESULT_TYPE( CompletionToken, void(std::exception_ptr)) co_spawn(ExecutionContext& ctx, awaitable<void, AwaitableExecutor> a, CompletionToken&& token, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value && is_convertible<typename ExecutionContext::executor_type, AwaitableExecutor>::value - >::type) + >) { return (co_spawn)(ctx.get_executor(), std::move(a), std::forward<CompletionToken>(token)); @@ -310,30 +413,30 @@ co_spawn(ExecutionContext& ctx, template <typename Executor, typename F, ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature< - typename result_of<F()>::type>::type) CompletionToken> + result_of_t<F()>>::type) CompletionToken> inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, - typename detail::awaitable_signature<typename result_of<F()>::type>::type) + typename detail::awaitable_signature<result_of_t<F()>>::type) co_spawn(const Executor& ex, F&& f, CompletionToken&& token, - typename constraint< + constraint_t< is_executor<Executor>::value || execution::is_executor<Executor>::value - >::type) + >) { return async_initiate<CompletionToken, - typename detail::awaitable_signature<typename result_of<F()>::type>::type>( + typename detail::awaitable_signature<result_of_t<F()>>::type>( detail::initiate_co_spawn< - typename result_of<F()>::type::executor_type>(ex), + typename result_of_t<F()>::executor_type>(ex), token, std::forward<F>(f)); } template <typename ExecutionContext, typename F, ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature< - typename result_of<F()>::type>::type) CompletionToken> + result_of_t<F()>>::type) CompletionToken> inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, - typename detail::awaitable_signature<typename result_of<F()>::type>::type) + typename detail::awaitable_signature<result_of_t<F()>>::type) co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type) + >) { return (co_spawn)(ctx.get_executor(), std::forward<F>(f), std::forward<CompletionToken>(token)); diff --git a/3rdparty/asio/include/asio/impl/compose.hpp b/3rdparty/asio/include/asio/impl/compose.hpp deleted file mode 100644 index 586911ea708..00000000000 --- a/3rdparty/asio/include/asio/impl/compose.hpp +++ /dev/null @@ -1,687 +0,0 @@ -// -// impl/compose.hpp -// ~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IMPL_COMPOSE_HPP -#define ASIO_IMPL_COMPOSE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/associated_executor.hpp" -#include "asio/detail/base_from_cancellation_state.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" -#include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" -#include "asio/execution/executor.hpp" -#include "asio/execution/outstanding_work.hpp" -#include "asio/executor_work_guard.hpp" -#include "asio/is_executor.hpp" -#include "asio/system_executor.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { - -namespace detail -{ - template <typename Executor, typename = void> - class composed_work_guard - { - public: - typedef typename decay< - typename prefer_result<Executor, - execution::outstanding_work_t::tracked_t - >::type - >::type executor_type; - - composed_work_guard(const Executor& ex) - : executor_(asio::prefer(ex, execution::outstanding_work.tracked)) - { - } - - void reset() - { - } - - executor_type get_executor() const ASIO_NOEXCEPT - { - return executor_; - } - - private: - executor_type executor_; - }; - -#if !defined(ASIO_NO_TS_EXECUTORS) - - template <typename Executor> - struct composed_work_guard<Executor, - typename enable_if< - !execution::is_executor<Executor>::value - >::type> : executor_work_guard<Executor> - { - composed_work_guard(const Executor& ex) - : executor_work_guard<Executor>(ex) - { - } - }; - -#endif // !defined(ASIO_NO_TS_EXECUTORS) - - template <typename> - struct composed_io_executors; - - template <> - struct composed_io_executors<void()> - { - composed_io_executors() ASIO_NOEXCEPT - : head_(system_executor()) - { - } - - typedef system_executor head_type; - system_executor head_; - }; - - inline composed_io_executors<void()> make_composed_io_executors() - { - return composed_io_executors<void()>(); - } - - template <typename Head> - struct composed_io_executors<void(Head)> - { - explicit composed_io_executors(const Head& ex) ASIO_NOEXCEPT - : head_(ex) - { - } - - typedef Head head_type; - Head head_; - }; - - template <typename Head> - inline composed_io_executors<void(Head)> - make_composed_io_executors(const Head& head) - { - return composed_io_executors<void(Head)>(head); - } - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Head, typename... Tail> - struct composed_io_executors<void(Head, Tail...)> - { - explicit composed_io_executors(const Head& head, - const Tail&... tail) ASIO_NOEXCEPT - : head_(head), - tail_(tail...) - { - } - - void reset() - { - head_.reset(); - tail_.reset(); - } - - typedef Head head_type; - Head head_; - composed_io_executors<void(Tail...)> tail_; - }; - - template <typename Head, typename... Tail> - inline composed_io_executors<void(Head, Tail...)> - make_composed_io_executors(const Head& head, const Tail&... tail) - { - return composed_io_executors<void(Head, Tail...)>(head, tail...); - } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#define ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF(n) \ - template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \ - struct composed_io_executors<void(Head, ASIO_VARIADIC_TARGS(n))> \ - { \ - explicit composed_io_executors(const Head& head, \ - ASIO_VARIADIC_CONSTREF_PARAMS(n)) ASIO_NOEXCEPT \ - : head_(head), \ - tail_(ASIO_VARIADIC_BYVAL_ARGS(n)) \ - { \ - } \ - \ - void reset() \ - { \ - head_.reset(); \ - tail_.reset(); \ - } \ - \ - typedef Head head_type; \ - Head head_; \ - composed_io_executors<void(ASIO_VARIADIC_TARGS(n))> tail_; \ - }; \ - \ - template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \ - inline composed_io_executors<void(Head, ASIO_VARIADIC_TARGS(n))> \ - make_composed_io_executors(const Head& head, \ - ASIO_VARIADIC_CONSTREF_PARAMS(n)) \ - { \ - return composed_io_executors< \ - void(Head, ASIO_VARIADIC_TARGS(n))>( \ - head, ASIO_VARIADIC_BYVAL_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF) -#undef ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename> - struct composed_work; - - template <> - struct composed_work<void()> - { - typedef composed_io_executors<void()> executors_type; - - composed_work(const executors_type&) ASIO_NOEXCEPT - : head_(system_executor()) - { - } - - void reset() - { - head_.reset(); - } - - typedef system_executor head_type; - composed_work_guard<system_executor> head_; - }; - - template <typename Head> - struct composed_work<void(Head)> - { - typedef composed_io_executors<void(Head)> executors_type; - - explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT - : head_(ex.head_) - { - } - - void reset() - { - head_.reset(); - } - - typedef Head head_type; - composed_work_guard<Head> head_; - }; - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Head, typename... Tail> - struct composed_work<void(Head, Tail...)> - { - typedef composed_io_executors<void(Head, Tail...)> executors_type; - - explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT - : head_(ex.head_), - tail_(ex.tail_) - { - } - - void reset() - { - head_.reset(); - tail_.reset(); - } - - typedef Head head_type; - composed_work_guard<Head> head_; - composed_work<void(Tail...)> tail_; - }; - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#define ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \ - template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \ - struct composed_work<void(Head, ASIO_VARIADIC_TARGS(n))> \ - { \ - typedef composed_io_executors<void(Head, \ - ASIO_VARIADIC_TARGS(n))> executors_type; \ - \ - explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT \ - : head_(ex.head_), \ - tail_(ex.tail_) \ - { \ - } \ - \ - void reset() \ - { \ - head_.reset(); \ - tail_.reset(); \ - } \ - \ - typedef Head head_type; \ - composed_work_guard<Head> head_; \ - composed_work<void(ASIO_VARIADIC_TARGS(n))> tail_; \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_WORK_DEF) -#undef ASIO_PRIVATE_COMPOSED_WORK_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Impl, typename Work, typename Handler, typename Signature> - class composed_op; - - template <typename Impl, typename Work, typename Handler, - typename R, typename... Args> - class composed_op<Impl, Work, Handler, R(Args...)> -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Impl, typename Work, typename Handler, typename Signature> - class composed_op -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - : public base_from_cancellation_state<Handler> - { - public: - template <typename I, typename W, typename H> - composed_op(ASIO_MOVE_ARG(I) impl, - ASIO_MOVE_ARG(W) work, - ASIO_MOVE_ARG(H) handler) - : base_from_cancellation_state<Handler>( - handler, enable_terminal_cancellation()), - impl_(ASIO_MOVE_CAST(I)(impl)), - work_(ASIO_MOVE_CAST(W)(work)), - handler_(ASIO_MOVE_CAST(H)(handler)), - invocations_(0) - { - } - -#if defined(ASIO_HAS_MOVE) - composed_op(composed_op&& other) - : base_from_cancellation_state<Handler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - Handler>)(other)), - impl_(ASIO_MOVE_CAST(Impl)(other.impl_)), - work_(ASIO_MOVE_CAST(Work)(other.work_)), - handler_(ASIO_MOVE_CAST(Handler)(other.handler_)), - invocations_(other.invocations_) - { - } -#endif // defined(ASIO_HAS_MOVE) - - typedef typename associated_executor<Handler, - typename composed_work_guard< - typename Work::head_type - >::executor_type - >::type executor_type; - - executor_type get_executor() const ASIO_NOEXCEPT - { - return (get_associated_executor)(handler_, work_.head_.get_executor()); - } - - typedef typename associated_allocator<Handler, - std::allocator<void> >::type allocator_type; - - allocator_type get_allocator() const ASIO_NOEXCEPT - { - return (get_associated_allocator)(handler_, std::allocator<void>()); - } - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template<typename... T> - void operator()(ASIO_MOVE_ARG(T)... t) - { - if (invocations_ < ~0u) - ++invocations_; - this->get_cancellation_state().slot().clear(); - impl_(*this, ASIO_MOVE_CAST(T)(t)...); - } - - void complete(Args... args) - { - this->work_.reset(); - ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)( - ASIO_MOVE_CAST(Args)(args)...); - } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - void operator()() - { - if (invocations_ < ~0u) - ++invocations_; - this->get_cancellation_state().slot().clear(); - impl_(*this); - } - - void complete() - { - this->work_.reset(); - ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)(); - } - -#define ASIO_PRIVATE_COMPOSED_OP_DEF(n) \ - template<ASIO_VARIADIC_TPARAMS(n)> \ - void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - if (invocations_ < ~0u) \ - ++invocations_; \ - this->get_cancellation_state().slot().clear(); \ - impl_(*this, ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template<ASIO_VARIADIC_TPARAMS(n)> \ - void complete(ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - this->work_.reset(); \ - ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)( \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_OP_DEF) -#undef ASIO_PRIVATE_COMPOSED_OP_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - void reset_cancellation_state() - { - base_from_cancellation_state<Handler>::reset_cancellation_state(handler_); - } - - template <typename Filter> - void reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter) - { - base_from_cancellation_state<Handler>::reset_cancellation_state(handler_, - ASIO_MOVE_CAST(Filter)(filter)); - } - - template <typename InFilter, typename OutFilter> - void reset_cancellation_state(ASIO_MOVE_ARG(InFilter) in_filter, - ASIO_MOVE_ARG(OutFilter) out_filter) - { - base_from_cancellation_state<Handler>::reset_cancellation_state(handler_, - ASIO_MOVE_CAST(InFilter)(in_filter), - ASIO_MOVE_CAST(OutFilter)(out_filter)); - } - - //private: - Impl impl_; - Work work_; - Handler handler_; - unsigned invocations_; - }; - - template <typename Impl, typename Work, typename Handler, typename Signature> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - composed_op<Impl, Work, Handler, Signature>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Impl, typename Work, typename Handler, typename Signature> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - composed_op<Impl, Work, Handler, Signature>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Impl, typename Work, typename Handler, typename Signature> - inline bool asio_handler_is_continuation( - composed_op<Impl, Work, Handler, Signature>* this_handler) - { - return this_handler->invocations_ > 1 ? true - : asio_handler_cont_helpers::is_continuation( - this_handler->handler_); - } - - template <typename Function, typename Impl, - typename Work, typename Handler, typename Signature> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - composed_op<Impl, Work, Handler, Signature>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename Impl, - typename Work, typename Handler, typename Signature> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - composed_op<Impl, Work, Handler, Signature>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Signature, typename Executors> - class initiate_composed_op - { - public: - typedef typename composed_io_executors<Executors>::head_type executor_type; - - template <typename T> - explicit initiate_composed_op(int, ASIO_MOVE_ARG(T) executors) - : executors_(ASIO_MOVE_CAST(T)(executors)) - { - } - - executor_type get_executor() const ASIO_NOEXCEPT - { - return executors_.head_; - } - - template <typename Handler, typename Impl> - void operator()(ASIO_MOVE_ARG(Handler) handler, - ASIO_MOVE_ARG(Impl) impl) const - { - composed_op<typename decay<Impl>::type, composed_work<Executors>, - typename decay<Handler>::type, Signature>( - ASIO_MOVE_CAST(Impl)(impl), - composed_work<Executors>(executors_), - ASIO_MOVE_CAST(Handler)(handler))(); - } - - private: - composed_io_executors<Executors> executors_; - }; - - template <typename Signature, typename Executors> - inline initiate_composed_op<Signature, Executors> make_initiate_composed_op( - ASIO_MOVE_ARG(composed_io_executors<Executors>) executors) - { - return initiate_composed_op<Signature, Executors>(0, - ASIO_MOVE_CAST(composed_io_executors<Executors>)(executors)); - } - - template <typename IoObject> - inline typename IoObject::executor_type - get_composed_io_executor(IoObject& io_object, - typename enable_if< - !is_executor<IoObject>::value - >::type* = 0, - typename enable_if< - !execution::is_executor<IoObject>::value - >::type* = 0) - { - return io_object.get_executor(); - } - - template <typename Executor> - inline const Executor& get_composed_io_executor(const Executor& ex, - typename enable_if< - is_executor<Executor>::value - || execution::is_executor<Executor>::value - >::type* = 0) - { - return ex; - } -} // namespace detail - -#if !defined(GENERATING_DOCUMENTATION) - -template <template <typename, typename> class Associator, - typename Impl, typename Work, typename Handler, - typename Signature, typename DefaultCandidate> -struct associator<Associator, - detail::composed_op<Impl, Work, Handler, Signature>, - DefaultCandidate> - : Associator<Handler, DefaultCandidate> -{ - static typename Associator<Handler, DefaultCandidate>::type get( - const detail::composed_op<Impl, Work, Handler, Signature>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT - { - return Associator<Handler, DefaultCandidate>::get(h.handler_, c); - } -}; - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename CompletionToken, typename Signature, - typename Implementation, typename... IoObjectsOrExecutors> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) -async_compose(ASIO_MOVE_ARG(Implementation) implementation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, - ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors) -{ - return async_initiate<CompletionToken, Signature>( - detail::make_initiate_composed_op<Signature>( - detail::make_composed_io_executors( - detail::get_composed_io_executor( - ASIO_MOVE_CAST(IoObjectsOrExecutors)( - io_objects_or_executors))...)), - token, ASIO_MOVE_CAST(Implementation)(implementation)); -} - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename CompletionToken, typename Signature, typename Implementation> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) -async_compose(ASIO_MOVE_ARG(Implementation) implementation, - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token) -{ - return async_initiate<CompletionToken, Signature>( - detail::make_initiate_composed_op<Signature>( - detail::make_composed_io_executors()), - token, ASIO_MOVE_CAST(Implementation)(implementation)); -} - -# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \ - ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n - -# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)) -# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)) -# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)) -# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)) -# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)) -# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6 \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6)) -# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7 \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T7)(x7)) -# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8 \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T7)(x7)), \ - detail::get_composed_io_executor(ASIO_MOVE_CAST(T8)(x8)) - -#define ASIO_PRIVATE_ASYNC_COMPOSE_DEF(n) \ - template <typename CompletionToken, typename Signature, \ - typename Implementation, ASIO_VARIADIC_TPARAMS(n)> \ - ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature) \ - async_compose(ASIO_MOVE_ARG(Implementation) implementation, \ - ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - return async_initiate<CompletionToken, Signature>( \ - detail::make_initiate_composed_op<Signature>( \ - detail::make_composed_io_executors( \ - ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))), \ - token, ASIO_MOVE_CAST(Implementation)(implementation)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_COMPOSE_DEF) -#undef ASIO_PRIVATE_ASYNC_COMPOSE_DEF - -#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR -#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 -#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 -#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 -#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 -#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 -#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6 -#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7 -#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8 - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) -#endif // !defined(GENERATING_DOCUMENTATION) - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IMPL_COMPOSE_HPP diff --git a/3rdparty/asio/include/asio/impl/connect.hpp b/3rdparty/asio/include/asio/impl/connect.hpp index 31ec4e165b4..ac74ae0a782 100644 --- a/3rdparty/asio/include/asio/impl/connect.hpp +++ b/3rdparty/asio/include/asio/impl/connect.hpp @@ -2,7 +2,7 @@ // impl/connect.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,13 +19,12 @@ #include "asio/associator.hpp" #include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/bind_handler.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_tracking.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/non_const_lvalue.hpp" #include "asio/detail/throw_error.hpp" +#include "asio/detail/type_traits.hpp" #include "asio/error.hpp" #include "asio/post.hpp" @@ -73,16 +72,16 @@ namespace detail static const bool value = sizeof(asio_connect_condition_check( - (*static_cast<legacy_connect_condition_helper<T, Iterator>*>(0))( - *static_cast<const asio::error_code*>(0), - *static_cast<const Iterator*>(0)))) != 1; + (declval<legacy_connect_condition_helper<T, Iterator>>())( + declval<const asio::error_code>(), + declval<const Iterator>()))) != 1; }; template <typename ConnectCondition, typename Iterator> inline Iterator call_connect_condition(ConnectCondition& connect_condition, const asio::error_code& ec, Iterator next, Iterator end, - typename enable_if<is_legacy_connect_condition< - ConnectCondition, Iterator>::value>::type* = 0) + enable_if_t<is_legacy_connect_condition< + ConnectCondition, Iterator>::value>* = 0) { if (next != end) return connect_condition(ec, next); @@ -92,8 +91,8 @@ namespace detail template <typename ConnectCondition, typename Iterator> inline Iterator call_connect_condition(ConnectCondition& connect_condition, const asio::error_code& ec, Iterator next, Iterator end, - typename enable_if<!is_legacy_connect_condition< - ConnectCondition, Iterator>::value>::type* = 0) + enable_if_t<!is_legacy_connect_condition< + ConnectCondition, Iterator>::value>* = 0) { for (;next != end; ++next) if (connect_condition(ec, *next)) @@ -105,8 +104,7 @@ namespace detail template <typename Protocol, typename Executor, typename EndpointSequence> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type) + constraint_t<is_endpoint_sequence<EndpointSequence>::value>) { asio::error_code ec; typename Protocol::endpoint result = connect(s, endpoints, ec); @@ -117,8 +115,7 @@ typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, template <typename Protocol, typename Executor, typename EndpointSequence> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, asio::error_code& ec, - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type) + constraint_t<is_endpoint_sequence<EndpointSequence>::value>) { return detail::deref_connect_result<Protocol>( connect(s, endpoints.begin(), endpoints.end(), @@ -128,7 +125,7 @@ typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, #if !defined(ASIO_NO_DEPRECATED) template <typename Protocol, typename Executor, typename Iterator> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, - typename constraint<!is_endpoint_sequence<Iterator>::value>::type) + constraint_t<!is_endpoint_sequence<Iterator>::value>) { asio::error_code ec; Iterator result = connect(s, begin, ec); @@ -139,7 +136,7 @@ Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, template <typename Protocol, typename Executor, typename Iterator> inline Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, asio::error_code& ec, - typename constraint<!is_endpoint_sequence<Iterator>::value>::type) + constraint_t<!is_endpoint_sequence<Iterator>::value>) { return connect(s, begin, Iterator(), detail::default_connect_condition(), ec); } @@ -166,8 +163,7 @@ template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition> typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type) + constraint_t<is_endpoint_sequence<EndpointSequence>::value>) { asio::error_code ec; typename Protocol::endpoint result = connect( @@ -181,8 +177,7 @@ template <typename Protocol, typename Executor, typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, asio::error_code& ec, - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type) + constraint_t<is_endpoint_sequence<EndpointSequence>::value>) { return detail::deref_connect_result<Protocol>( connect(s, endpoints.begin(), endpoints.end(), @@ -194,7 +189,7 @@ template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition> Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition, - typename constraint<!is_endpoint_sequence<Iterator>::value>::type) + constraint_t<!is_endpoint_sequence<Iterator>::value>) { asio::error_code ec; Iterator result = connect(s, begin, connect_condition, ec); @@ -207,7 +202,7 @@ template <typename Protocol, typename Executor, inline Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin, ConnectCondition connect_condition, asio::error_code& ec, - typename constraint<!is_endpoint_sequence<Iterator>::value>::type) + constraint_t<!is_endpoint_sequence<Iterator>::value>) { return connect(s, begin, Iterator(), connect_condition, ec); } @@ -310,11 +305,10 @@ namespace detail endpoints_(endpoints), index_(0), start_(0), - handler_(ASIO_MOVE_CAST(RangeConnectHandler)(handler)) + handler_(static_cast<RangeConnectHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) range_connect_op(const range_connect_op& other) : base_from_cancellation_state<RangeConnectHandler>(other), base_from_connect_condition<ConnectCondition>(other), @@ -328,17 +322,16 @@ namespace detail range_connect_op(range_connect_op&& other) : base_from_cancellation_state<RangeConnectHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - RangeConnectHandler>)(other)), + static_cast<base_from_cancellation_state<RangeConnectHandler>&&>( + other)), base_from_connect_condition<ConnectCondition>(other), socket_(other.socket_), endpoints_(other.endpoints_), index_(other.index_), start_(other.start_), - handler_(ASIO_MOVE_CAST(RangeConnectHandler)(other.handler_)) + handler_(static_cast<RangeConnectHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, int start = 0) { @@ -368,7 +361,7 @@ namespace detail socket_.close(ec); ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect")); socket_.async_connect(*iter, - ASIO_MOVE_CAST(range_connect_op)(*this)); + static_cast<range_connect_op&&>(*this)); return; } @@ -378,7 +371,7 @@ namespace detail ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect")); asio::post(socket_.get_executor(), detail::bind_handler( - ASIO_MOVE_CAST(range_connect_op)(*this), ec)); + static_cast<range_connect_op&&>(*this), ec)); return; } @@ -406,7 +399,7 @@ namespace detail ++index_; } - ASIO_MOVE_OR_LVALUE(RangeConnectHandler)(handler_)( + static_cast<RangeConnectHandler&&>(handler_)( static_cast<const asio::error_code&>(ec), static_cast<const typename Protocol::endpoint&>( ec || iter == end ? typename Protocol::endpoint() : *iter)); @@ -422,36 +415,6 @@ namespace detail template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition, typename RangeConnectHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - range_connect_op<Protocol, Executor, EndpointSequence, - ConnectCondition, RangeConnectHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Protocol, typename Executor, typename EndpointSequence, - typename ConnectCondition, typename RangeConnectHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - range_connect_op<Protocol, Executor, EndpointSequence, - ConnectCondition, RangeConnectHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Protocol, typename Executor, typename EndpointSequence, - typename ConnectCondition, typename RangeConnectHandler> inline bool asio_handler_is_continuation( range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition, RangeConnectHandler>* this_handler) @@ -460,36 +423,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename Executor, typename Protocol, - typename EndpointSequence, typename ConnectCondition, - typename RangeConnectHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - range_connect_op<Protocol, Executor, EndpointSequence, - ConnectCondition, RangeConnectHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename Executor, typename Protocol, - typename EndpointSequence, typename ConnectCondition, - typename RangeConnectHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - range_connect_op<Protocol, Executor, EndpointSequence, - ConnectCondition, RangeConnectHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename Protocol, typename Executor> class initiate_async_range_connect { @@ -501,14 +434,14 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return socket_.get_executor(); } template <typename RangeConnectHandler, typename EndpointSequence, typename ConnectCondition> - void operator()(ASIO_MOVE_ARG(RangeConnectHandler) handler, + void operator()(RangeConnectHandler&& handler, const EndpointSequence& endpoints, const ConnectCondition& connect_condition) const { @@ -520,7 +453,7 @@ namespace detail non_const_lvalue<RangeConnectHandler> handler2(handler); range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition, - typename decay<RangeConnectHandler>::type>(socket_, endpoints, + decay_t<RangeConnectHandler>>(socket_, endpoints, connect_condition, handler2.value)(asio::error_code(), 1); } @@ -546,11 +479,10 @@ namespace detail iter_(begin), end_(end), start_(0), - handler_(ASIO_MOVE_CAST(IteratorConnectHandler)(handler)) + handler_(static_cast<IteratorConnectHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) iterator_connect_op(const iterator_connect_op& other) : base_from_cancellation_state<IteratorConnectHandler>(other), base_from_connect_condition<ConnectCondition>(other), @@ -564,17 +496,16 @@ namespace detail iterator_connect_op(iterator_connect_op&& other) : base_from_cancellation_state<IteratorConnectHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - IteratorConnectHandler>)(other)), + static_cast<base_from_cancellation_state<IteratorConnectHandler>&&>( + other)), base_from_connect_condition<ConnectCondition>(other), socket_(other.socket_), iter_(other.iter_), end_(other.end_), start_(other.start_), - handler_(ASIO_MOVE_CAST(IteratorConnectHandler)(other.handler_)) + handler_(static_cast<IteratorConnectHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, int start = 0) { @@ -590,7 +521,7 @@ namespace detail socket_.close(ec); ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect")); socket_.async_connect(*iter_, - ASIO_MOVE_CAST(iterator_connect_op)(*this)); + static_cast<iterator_connect_op&&>(*this)); return; } @@ -600,7 +531,7 @@ namespace detail ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect")); asio::post(socket_.get_executor(), detail::bind_handler( - ASIO_MOVE_CAST(iterator_connect_op)(*this), ec)); + static_cast<iterator_connect_op&&>(*this), ec)); return; } @@ -627,7 +558,7 @@ namespace detail ++iter_; } - ASIO_MOVE_OR_LVALUE(IteratorConnectHandler)(handler_)( + static_cast<IteratorConnectHandler&&>(handler_)( static_cast<const asio::error_code&>(ec), static_cast<const Iterator&>(iter_)); } @@ -643,36 +574,6 @@ namespace detail template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, typename IteratorConnectHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - iterator_connect_op<Protocol, Executor, Iterator, - ConnectCondition, IteratorConnectHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Protocol, typename Executor, typename Iterator, - typename ConnectCondition, typename IteratorConnectHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - iterator_connect_op<Protocol, Executor, Iterator, - ConnectCondition, IteratorConnectHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Protocol, typename Executor, typename Iterator, - typename ConnectCondition, typename IteratorConnectHandler> inline bool asio_handler_is_continuation( iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, IteratorConnectHandler>* this_handler) @@ -681,36 +582,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename Executor, typename Protocol, - typename Iterator, typename ConnectCondition, - typename IteratorConnectHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - iterator_connect_op<Protocol, Executor, Iterator, - ConnectCondition, IteratorConnectHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename Executor, typename Protocol, - typename Iterator, typename ConnectCondition, - typename IteratorConnectHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - iterator_connect_op<Protocol, Executor, Iterator, - ConnectCondition, IteratorConnectHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename Protocol, typename Executor> class initiate_async_iterator_connect { @@ -723,14 +594,14 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return socket_.get_executor(); } template <typename IteratorConnectHandler, typename Iterator, typename ConnectCondition> - void operator()(ASIO_MOVE_ARG(IteratorConnectHandler) handler, + void operator()(IteratorConnectHandler&& handler, Iterator begin, Iterator end, const ConnectCondition& connect_condition) const { @@ -742,7 +613,7 @@ namespace detail non_const_lvalue<IteratorConnectHandler> handler2(handler); iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, - typename decay<IteratorConnectHandler>::type>(socket_, begin, end, + decay_t<IteratorConnectHandler>>(socket_, begin, end, connect_condition, handler2.value)(asio::error_code(), 1); } @@ -764,9 +635,19 @@ struct associator<Associator, : Associator<RangeConnectHandler, DefaultCandidate> { static typename Associator<RangeConnectHandler, DefaultCandidate>::type get( + const detail::range_connect_op<Protocol, Executor, EndpointSequence, + ConnectCondition, RangeConnectHandler>& h) noexcept + { + return Associator<RangeConnectHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( const detail::range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition, RangeConnectHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype( + Associator<RangeConnectHandler, DefaultCandidate>::get( + h.handler_, c)) { return Associator<RangeConnectHandler, DefaultCandidate>::get( h.handler_, c); @@ -784,10 +665,20 @@ struct associator<Associator, : Associator<IteratorConnectHandler, DefaultCandidate> { static typename Associator<IteratorConnectHandler, DefaultCandidate>::type - get( + get(const detail::iterator_connect_op<Protocol, Executor, Iterator, + ConnectCondition, IteratorConnectHandler>& h) noexcept + { + return Associator<IteratorConnectHandler, DefaultCandidate>::get( + h.handler_); + } + + static auto get( const detail::iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition, IteratorConnectHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype( + Associator<IteratorConnectHandler, DefaultCandidate>::get( + h.handler_, c)) { return Associator<IteratorConnectHandler, DefaultCandidate>::get( h.handler_, c); @@ -798,103 +689,117 @@ struct associator<Associator, template <typename Protocol, typename Executor, typename EndpointSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - typename Protocol::endpoint)) RangeConnectHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler, - void (asio::error_code, typename Protocol::endpoint)) -async_connect(basic_socket<Protocol, Executor>& s, - const EndpointSequence& endpoints, - ASIO_MOVE_ARG(RangeConnectHandler) handler, - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type) + typename Protocol::endpoint)) RangeConnectToken> +inline auto async_connect(basic_socket<Protocol, Executor>& s, + const EndpointSequence& endpoints, RangeConnectToken&& token, + constraint_t<is_endpoint_sequence<EndpointSequence>::value>) + -> decltype( + async_initiate<RangeConnectToken, + void (asio::error_code, typename Protocol::endpoint)>( + declval<detail::initiate_async_range_connect<Protocol, Executor>>(), + token, endpoints, declval<detail::default_connect_condition>())) { - return async_initiate<RangeConnectHandler, + return async_initiate<RangeConnectToken, void (asio::error_code, typename Protocol::endpoint)>( detail::initiate_async_range_connect<Protocol, Executor>(s), - handler, endpoints, detail::default_connect_condition()); + token, endpoints, detail::default_connect_condition()); } #if !defined(ASIO_NO_DEPRECATED) template <typename Protocol, typename Executor, typename Iterator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - Iterator)) IteratorConnectHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, - void (asio::error_code, Iterator)) -async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, - ASIO_MOVE_ARG(IteratorConnectHandler) handler, - typename constraint<!is_endpoint_sequence<Iterator>::value>::type) + Iterator)) IteratorConnectToken> +inline auto async_connect(basic_socket<Protocol, Executor>& s, + Iterator begin, IteratorConnectToken&& token, + constraint_t<!is_endpoint_sequence<Iterator>::value>) + -> decltype( + async_initiate<IteratorConnectToken, + void (asio::error_code, Iterator)>( + declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), + token, begin, Iterator(), declval<detail::default_connect_condition>())) { - return async_initiate<IteratorConnectHandler, + return async_initiate<IteratorConnectToken, void (asio::error_code, Iterator)>( detail::initiate_async_iterator_connect<Protocol, Executor>(s), - handler, begin, Iterator(), detail::default_connect_condition()); + token, begin, Iterator(), detail::default_connect_condition()); } #endif // !defined(ASIO_NO_DEPRECATED) template <typename Protocol, typename Executor, typename Iterator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - Iterator)) IteratorConnectHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, - void (asio::error_code, Iterator)) -async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end, - ASIO_MOVE_ARG(IteratorConnectHandler) handler) + Iterator)) IteratorConnectToken> +inline auto async_connect(basic_socket<Protocol, Executor>& s, + Iterator begin, Iterator end, IteratorConnectToken&& token) + -> decltype( + async_initiate<IteratorConnectToken, + void (asio::error_code, Iterator)>( + declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), + token, begin, end, declval<detail::default_connect_condition>())) { - return async_initiate<IteratorConnectHandler, + return async_initiate<IteratorConnectToken, void (asio::error_code, Iterator)>( detail::initiate_async_iterator_connect<Protocol, Executor>(s), - handler, begin, end, detail::default_connect_condition()); + token, begin, end, detail::default_connect_condition()); } template <typename Protocol, typename Executor, typename EndpointSequence, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - typename Protocol::endpoint)) RangeConnectHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler, - void (asio::error_code, typename Protocol::endpoint)) -async_connect(basic_socket<Protocol, Executor>& s, + typename Protocol::endpoint)) RangeConnectToken> +inline auto async_connect(basic_socket<Protocol, Executor>& s, const EndpointSequence& endpoints, ConnectCondition connect_condition, - ASIO_MOVE_ARG(RangeConnectHandler) handler, - typename constraint<is_endpoint_sequence< - EndpointSequence>::value>::type) + RangeConnectToken&& token, + constraint_t<is_endpoint_sequence<EndpointSequence>::value>) + -> decltype( + async_initiate<RangeConnectToken, + void (asio::error_code, typename Protocol::endpoint)>( + declval<detail::initiate_async_range_connect<Protocol, Executor>>(), + token, endpoints, connect_condition)) { - return async_initiate<RangeConnectHandler, + return async_initiate<RangeConnectToken, void (asio::error_code, typename Protocol::endpoint)>( detail::initiate_async_range_connect<Protocol, Executor>(s), - handler, endpoints, connect_condition); + token, endpoints, connect_condition); } #if !defined(ASIO_NO_DEPRECATED) template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - Iterator)) IteratorConnectHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, - void (asio::error_code, Iterator)) -async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, - ConnectCondition connect_condition, - ASIO_MOVE_ARG(IteratorConnectHandler) handler, - typename constraint<!is_endpoint_sequence<Iterator>::value>::type) + Iterator)) IteratorConnectToken> +inline auto async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, + ConnectCondition connect_condition, IteratorConnectToken&& token, + constraint_t<!is_endpoint_sequence<Iterator>::value>) + -> decltype( + async_initiate<IteratorConnectToken, + void (asio::error_code, Iterator)>( + declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), + token, begin, Iterator(), connect_condition)) { - return async_initiate<IteratorConnectHandler, + return async_initiate<IteratorConnectToken, void (asio::error_code, Iterator)>( detail::initiate_async_iterator_connect<Protocol, Executor>(s), - handler, begin, Iterator(), connect_condition); + token, begin, Iterator(), connect_condition); } #endif // !defined(ASIO_NO_DEPRECATED) template <typename Protocol, typename Executor, typename Iterator, typename ConnectCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - Iterator)) IteratorConnectHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler, - void (asio::error_code, Iterator)) -async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, - Iterator end, ConnectCondition connect_condition, - ASIO_MOVE_ARG(IteratorConnectHandler) handler) + Iterator)) IteratorConnectToken> +inline auto async_connect(basic_socket<Protocol, Executor>& s, + Iterator begin, Iterator end, ConnectCondition connect_condition, + IteratorConnectToken&& token) + -> decltype( + async_initiate<IteratorConnectToken, + void (asio::error_code, Iterator)>( + declval<detail::initiate_async_iterator_connect<Protocol, Executor>>(), + token, begin, end, connect_condition)) { - return async_initiate<IteratorConnectHandler, + return async_initiate<IteratorConnectToken, void (asio::error_code, Iterator)>( detail::initiate_async_iterator_connect<Protocol, Executor>(s), - handler, begin, end, connect_condition); + token, begin, end, connect_condition); } } // namespace asio diff --git a/3rdparty/asio/include/asio/impl/connect_pipe.hpp b/3rdparty/asio/include/asio/impl/connect_pipe.hpp new file mode 100644 index 00000000000..e40b3c9433c --- /dev/null +++ b/3rdparty/asio/include/asio/impl/connect_pipe.hpp @@ -0,0 +1,73 @@ +// +// impl/connect_pipe.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_CONNECT_PIPE_HPP +#define ASIO_IMPL_CONNECT_PIPE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PIPE) + +#include "asio/connect_pipe.hpp" +#include "asio/detail/throw_error.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +template <typename Executor1, typename Executor2> +void connect_pipe(basic_readable_pipe<Executor1>& read_end, + basic_writable_pipe<Executor2>& write_end) +{ + asio::error_code ec; + asio::connect_pipe(read_end, write_end, ec); + asio::detail::throw_error(ec, "connect_pipe"); +} + +template <typename Executor1, typename Executor2> +ASIO_SYNC_OP_VOID connect_pipe(basic_readable_pipe<Executor1>& read_end, + basic_writable_pipe<Executor2>& write_end, asio::error_code& ec) +{ + detail::native_pipe_handle p[2]; + detail::create_pipe(p, ec); + if (ec) + ASIO_SYNC_OP_VOID_RETURN(ec); + + read_end.assign(p[0], ec); + if (ec) + { + detail::close_pipe(p[0]); + detail::close_pipe(p[1]); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + write_end.assign(p[1], ec); + if (ec) + { + asio::error_code temp_ec; + read_end.close(temp_ec); + detail::close_pipe(p[1]); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + ASIO_SYNC_OP_VOID_RETURN(ec); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_PIPE) + +#endif // ASIO_IMPL_CONNECT_PIPE_HPP diff --git a/3rdparty/asio/include/asio/impl/connect_pipe.ipp b/3rdparty/asio/include/asio/impl/connect_pipe.ipp new file mode 100644 index 00000000000..6efe790d713 --- /dev/null +++ b/3rdparty/asio/include/asio/impl/connect_pipe.ipp @@ -0,0 +1,149 @@ +// +// impl/connect_pipe.ipp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2021 Klemens D. Morgenstern +// (klemens dot morgenstern at gmx dot net) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_CONNECT_PIPE_IPP +#define ASIO_IMPL_CONNECT_PIPE_IPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PIPE) + +#include "asio/connect_pipe.hpp" + +#if defined(ASIO_HAS_IOCP) +# include <cstdio> +# if _WIN32_WINNT >= 0x601 +# include <bcrypt.h> +# if !defined(ASIO_NO_DEFAULT_LINKED_LIBS) +# if defined(_MSC_VER) +# pragma comment(lib, "bcrypt.lib") +# endif // defined(_MSC_VER) +# endif // !defined(ASIO_NO_DEFAULT_LINKED_LIBS) +# endif // _WIN32_WINNT >= 0x601 +#else // defined(ASIO_HAS_IOCP) +# include "asio/detail/descriptor_ops.hpp" +#endif // defined(ASIO_HAS_IOCP) + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +void create_pipe(native_pipe_handle p[2], asio::error_code& ec) +{ +#if defined(ASIO_HAS_IOCP) + using namespace std; // For sprintf and memcmp. + + static long counter1 = 0; + static long counter2 = 0; + + long n1 = ::InterlockedIncrement(&counter1); + long n2 = (static_cast<unsigned long>(n1) % 0x10000000) == 0 + ? ::InterlockedIncrement(&counter2) + : ::InterlockedExchangeAdd(&counter2, 0); + + wchar_t pipe_name[128]; +#if defined(ASIO_HAS_SECURE_RTL) + swprintf_s( +#else // defined(ASIO_HAS_SECURE_RTL) + _snwprintf( +#endif // defined(ASIO_HAS_SECURE_RTL) + pipe_name, 128, + L"\\\\.\\pipe\\asio-A0812896-741A-484D-AF23-BE51BF620E22-%u-%ld-%ld", + static_cast<unsigned int>(::GetCurrentProcessId()), n1, n2); + + p[0] = ::CreateNamedPipeW(pipe_name, + PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, + 0, 1, 8192, 8192, 0, 0); + + if (p[0] == INVALID_HANDLE_VALUE) + { + DWORD last_error = ::GetLastError(); + ec.assign(last_error, asio::error::get_system_category()); + return; + } + + p[1] = ::CreateFileW(pipe_name, GENERIC_WRITE, 0, + 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + + if (p[1] == INVALID_HANDLE_VALUE) + { + DWORD last_error = ::GetLastError(); + ::CloseHandle(p[0]); + ec.assign(last_error, asio::error::get_system_category()); + return; + } + +# if _WIN32_WINNT >= 0x601 + unsigned char nonce[16]; + if (::BCryptGenRandom(0, nonce, sizeof(nonce), + BCRYPT_USE_SYSTEM_PREFERRED_RNG) != 0) + { + ec = asio::error::connection_aborted; + ::CloseHandle(p[0]); + ::CloseHandle(p[1]); + return; + } + + DWORD bytes_written = 0; + BOOL ok = ::WriteFile(p[1], nonce, sizeof(nonce), &bytes_written, 0); + if (!ok || bytes_written != sizeof(nonce)) + { + ec = asio::error::connection_aborted; + ::CloseHandle(p[0]); + ::CloseHandle(p[1]); + return; + } + + unsigned char nonce_check[sizeof(nonce)]; + DWORD bytes_read = 0; + ok = ::ReadFile(p[0], nonce_check, sizeof(nonce), &bytes_read, 0); + if (!ok || bytes_read != sizeof(nonce) + || memcmp(nonce, nonce_check, sizeof(nonce)) != 0) + { + ec = asio::error::connection_aborted; + ::CloseHandle(p[0]); + ::CloseHandle(p[1]); + return; + } +#endif // _WIN32_WINNT >= 0x601 + + asio::error::clear(ec); +#else // defined(ASIO_HAS_IOCP) + int result = ::pipe(p); + detail::descriptor_ops::get_last_error(ec, result != 0); +#endif // defined(ASIO_HAS_IOCP) +} + +void close_pipe(native_pipe_handle p) +{ +#if defined(ASIO_HAS_IOCP) + ::CloseHandle(p); +#else // defined(ASIO_HAS_IOCP) + asio::error_code ignored_ec; + detail::descriptor_ops::state_type state = 0; + detail::descriptor_ops::close(p, state, ignored_ec); +#endif // defined(ASIO_HAS_IOCP) +} + +} // namespace detail +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_PIPE) + +#endif // ASIO_IMPL_CONNECT_PIPE_IPP diff --git a/3rdparty/asio/include/asio/impl/consign.hpp b/3rdparty/asio/include/asio/impl/consign.hpp new file mode 100644 index 00000000000..3b753c10fd0 --- /dev/null +++ b/3rdparty/asio/include/asio/impl/consign.hpp @@ -0,0 +1,137 @@ +// +// impl/consign.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_CONSIGN_HPP +#define ASIO_IMPL_CONSIGN_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/associator.hpp" +#include "asio/async_result.hpp" +#include "asio/detail/handler_cont_helpers.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/detail/utility.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Class to adapt a consign_t as a completion handler. +template <typename Handler, typename... Values> +class consign_handler +{ +public: + typedef void result_type; + + template <typename H> + consign_handler(H&& handler, std::tuple<Values...> values) + : handler_(static_cast<H&&>(handler)), + values_(static_cast<std::tuple<Values...>&&>(values)) + { + } + + template <typename... Args> + void operator()(Args&&... args) + { + static_cast<Handler&&>(handler_)(static_cast<Args&&>(args)...); + } + +//private: + Handler handler_; + std::tuple<Values...> values_; +}; + +template <typename Handler> +inline bool asio_handler_is_continuation( + consign_handler<Handler>* this_handler) +{ + return asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename CompletionToken, typename... Values, typename... Signatures> +struct async_result<consign_t<CompletionToken, Values...>, Signatures...> + : async_result<CompletionToken, Signatures...> +{ + template <typename Initiation> + struct init_wrapper + { + init_wrapper(Initiation init) + : initiation_(static_cast<Initiation&&>(init)) + { + } + + template <typename Handler, typename... Args> + void operator()(Handler&& handler, + std::tuple<Values...> values, Args&&... args) + { + static_cast<Initiation&&>(initiation_)( + detail::consign_handler<decay_t<Handler>, Values...>( + static_cast<Handler&&>(handler), + static_cast<std::tuple<Values...>&&>(values)), + static_cast<Args&&>(args)...); + } + + Initiation initiation_; + }; + + template <typename Initiation, typename RawCompletionToken, typename... Args> + static auto initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) + -> decltype( + async_initiate<CompletionToken, Signatures...>( + init_wrapper<decay_t<Initiation>>( + static_cast<Initiation&&>(initiation)), + token.token_, static_cast<std::tuple<Values...>&&>(token.values_), + static_cast<Args&&>(args)...)) + { + return async_initiate<CompletionToken, Signatures...>( + init_wrapper<decay_t<Initiation>>( + static_cast<Initiation&&>(initiation)), + token.token_, static_cast<std::tuple<Values...>&&>(token.values_), + static_cast<Args&&>(args)...); + } +}; + +template <template <typename, typename> class Associator, + typename Handler, typename... Values, typename DefaultCandidate> +struct associator<Associator, + detail::consign_handler<Handler, Values...>, DefaultCandidate> + : Associator<Handler, DefaultCandidate> +{ + static typename Associator<Handler, DefaultCandidate>::type get( + const detail::consign_handler<Handler, Values...>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::consign_handler<Handler, Values...>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) + { + return Associator<Handler, DefaultCandidate>::get(h.handler_, c); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_CONSIGN_HPP diff --git a/3rdparty/asio/include/asio/impl/defer.hpp b/3rdparty/asio/include/asio/impl/defer.hpp deleted file mode 100644 index 129d8684a94..00000000000 --- a/3rdparty/asio/include/asio/impl/defer.hpp +++ /dev/null @@ -1,256 +0,0 @@ -// -// impl/defer.hpp -// ~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IMPL_DEFER_HPP -#define ASIO_IMPL_DEFER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/associated_allocator.hpp" -#include "asio/associated_executor.hpp" -#include "asio/detail/work_dispatcher.hpp" -#include "asio/execution/allocator.hpp" -#include "asio/execution/blocking.hpp" -#include "asio/execution/relationship.hpp" -#include "asio/prefer.hpp" -#include "asio/require.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class initiate_defer -{ -public: - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - execution::is_executor< - typename associated_executor< - typename decay<CompletionHandler>::type - >::type - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_executor<handler_t>::type ex( - (get_associated_executor)(handler)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - execution::execute( - asio::prefer( - asio::require(ex, execution::blocking.never), - execution::relationship.continuation, - execution::allocator(alloc)), - asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler))); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - !execution::is_executor< - typename associated_executor< - typename decay<CompletionHandler>::type - >::type - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_executor<handler_t>::type ex( - (get_associated_executor)(handler)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - ex.defer(asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); - } -}; - -template <typename Executor> -class initiate_defer_with_executor -{ -public: - typedef Executor executor_type; - - explicit initiate_defer_with_executor(const Executor& ex) - : ex_(ex) - { - } - - executor_type get_executor() const ASIO_NOEXCEPT - { - return ex_; - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - !detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - execution::execute( - asio::prefer( - asio::require(ex_, execution::blocking.never), - execution::relationship.continuation, - execution::allocator(alloc)), - asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler))); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typedef typename associated_executor< - handler_t, Executor>::type handler_ex_t; - handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - execution::execute( - asio::prefer( - asio::require(ex_, execution::blocking.never), - execution::relationship.continuation, - execution::allocator(alloc)), - detail::work_dispatcher<handler_t, handler_ex_t>( - ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex)); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - !execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - !detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - ex_.defer(asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - !execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typedef typename associated_executor< - handler_t, Executor>::type handler_ex_t; - handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - ex_.defer(detail::work_dispatcher<handler_t, handler_ex_t>( - ASIO_MOVE_CAST(CompletionHandler)(handler), - handler_ex), alloc); - } - -private: - Executor ex_; -}; - -} // namespace detail - -template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( - ASIO_MOVE_ARG(CompletionToken) token) -{ - return async_initiate<CompletionToken, void()>( - detail::initiate_defer(), token); -} - -template <typename Executor, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( - const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token, - typename constraint< - execution::is_executor<Executor>::value || is_executor<Executor>::value - >::type) -{ - return async_initiate<CompletionToken, void()>( - detail::initiate_defer_with_executor<Executor>(ex), token); -} - -template <typename ExecutionContext, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer( - ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token, - typename constraint<is_convertible< - ExecutionContext&, execution_context&>::value>::type) -{ - return async_initiate<CompletionToken, void()>( - detail::initiate_defer_with_executor< - typename ExecutionContext::executor_type>( - ctx.get_executor()), token); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IMPL_DEFER_HPP diff --git a/3rdparty/asio/include/asio/impl/deferred.hpp b/3rdparty/asio/include/asio/impl/deferred.hpp new file mode 100644 index 00000000000..defc34fb3e7 --- /dev/null +++ b/3rdparty/asio/include/asio/impl/deferred.hpp @@ -0,0 +1,147 @@ +// +// impl/deferred.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_DEFERRED_HPP +#define ASIO_IMPL_DEFERRED_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/push_options.hpp" + +namespace asio { + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename Signature> +class async_result<deferred_t, Signature> +{ +public: + template <typename Initiation, typename... InitArgs> + static deferred_async_operation<Signature, Initiation, InitArgs...> + initiate(Initiation&& initiation, deferred_t, InitArgs&&... args) + { + return deferred_async_operation<Signature, Initiation, InitArgs...>( + deferred_init_tag{}, + static_cast<Initiation&&>(initiation), + static_cast<InitArgs&&>(args)...); + } +}; + +template <typename... Signatures> +class async_result<deferred_t, Signatures...> +{ +public: + template <typename Initiation, typename... InitArgs> + static deferred_async_operation< + deferred_signatures<Signatures...>, Initiation, InitArgs...> + initiate(Initiation&& initiation, deferred_t, InitArgs&&... args) + { + return deferred_async_operation< + deferred_signatures<Signatures...>, Initiation, InitArgs...>( + deferred_init_tag{}, + static_cast<Initiation&&>(initiation), + static_cast<InitArgs&&>(args)...); + } +}; + +template <typename Function, typename Signature> +class async_result<deferred_function<Function>, Signature> +{ +public: + template <typename Initiation, typename... InitArgs> + static auto initiate(Initiation&& initiation, + deferred_function<Function> token, InitArgs&&... init_args) + -> decltype( + deferred_sequence< + deferred_async_operation< + Signature, Initiation, InitArgs...>, + Function>(deferred_init_tag{}, + deferred_async_operation< + Signature, Initiation, InitArgs...>( + deferred_init_tag{}, + static_cast<Initiation&&>(initiation), + static_cast<InitArgs&&>(init_args)...), + static_cast<Function&&>(token.function_))) + { + return deferred_sequence< + deferred_async_operation< + Signature, Initiation, InitArgs...>, + Function>(deferred_init_tag{}, + deferred_async_operation< + Signature, Initiation, InitArgs...>( + deferred_init_tag{}, + static_cast<Initiation&&>(initiation), + static_cast<InitArgs&&>(init_args)...), + static_cast<Function&&>(token.function_)); + } +}; + +template <typename Function, typename... Signatures> +class async_result<deferred_function<Function>, Signatures...> +{ +public: + template <typename Initiation, typename... InitArgs> + static auto initiate(Initiation&& initiation, + deferred_function<Function> token, InitArgs&&... init_args) + -> decltype( + deferred_sequence< + deferred_async_operation< + deferred_signatures<Signatures...>, Initiation, InitArgs...>, + Function>(deferred_init_tag{}, + deferred_async_operation< + deferred_signatures<Signatures...>, Initiation, InitArgs...>( + deferred_init_tag{}, + static_cast<Initiation&&>(initiation), + static_cast<InitArgs&&>(init_args)...), + static_cast<Function&&>(token.function_))) + { + return deferred_sequence< + deferred_async_operation< + deferred_signatures<Signatures...>, Initiation, InitArgs...>, + Function>(deferred_init_tag{}, + deferred_async_operation< + deferred_signatures<Signatures...>, Initiation, InitArgs...>( + deferred_init_tag{}, + static_cast<Initiation&&>(initiation), + static_cast<InitArgs&&>(init_args)...), + static_cast<Function&&>(token.function_)); + } +}; + +template <template <typename, typename> class Associator, + typename Handler, typename Tail, typename DefaultCandidate> +struct associator<Associator, + detail::deferred_sequence_handler<Handler, Tail>, + DefaultCandidate> + : Associator<Handler, DefaultCandidate> +{ + static typename Associator<Handler, DefaultCandidate>::type get( + const detail::deferred_sequence_handler<Handler, Tail>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::deferred_sequence_handler<Handler, Tail>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) + { + return Associator<Handler, DefaultCandidate>::get(h.handler_, c); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_DEFERRED_HPP diff --git a/3rdparty/asio/include/asio/impl/detached.hpp b/3rdparty/asio/include/asio/impl/detached.hpp index f159b1ffbaa..774e52b1e01 100644 --- a/3rdparty/asio/include/asio/impl/detached.hpp +++ b/3rdparty/asio/include/asio/impl/detached.hpp @@ -2,7 +2,7 @@ // impl/detached.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,7 +17,6 @@ #include "asio/detail/config.hpp" #include "asio/async_result.hpp" -#include "asio/detail/variadic_templates.hpp" #include "asio/detail/push_options.hpp" @@ -34,29 +33,10 @@ namespace detail { { } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename... Args> void operator()(Args...) { } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - void operator()() - { - } - -#define ASIO_PRIVATE_DETACHED_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - void operator()(ASIO_VARIADIC_TARGS(n)) \ - { \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_DETACHED_DEF) -#undef ASIO_PRIVATE_DETACHED_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) }; } // namespace detail @@ -78,47 +58,14 @@ struct async_result<detached_t, Signature> { } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Initiation, typename RawCompletionToken, typename... Args> - static return_type initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken), - ASIO_MOVE_ARG(Args)... args) + static return_type initiate(Initiation&& initiation, + RawCompletionToken&&, Args&&... args) { - ASIO_MOVE_CAST(Initiation)(initiation)( + static_cast<Initiation&&>(initiation)( detail::detached_handler(detached_t()), - ASIO_MOVE_CAST(Args)(args)...); - } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Initiation, typename RawCompletionToken> - static return_type initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken)) - { - ASIO_MOVE_CAST(Initiation)(initiation)( - detail::detached_handler(detached_t())); + static_cast<Args&&>(args)...); } - -#define ASIO_PRIVATE_INITIATE_DEF(n) \ - template <typename Initiation, typename RawCompletionToken, \ - ASIO_VARIADIC_TPARAMS(n)> \ - static return_type initiate( \ - ASIO_MOVE_ARG(Initiation) initiation, \ - ASIO_MOVE_ARG(RawCompletionToken), \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - ASIO_MOVE_CAST(Initiation)(initiation)( \ - detail::detached_handler(detached_t()), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF) -#undef ASIO_PRIVATE_INITIATE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) }; #endif // !defined(GENERATING_DOCUMENTATION) diff --git a/3rdparty/asio/include/asio/impl/dispatch.hpp b/3rdparty/asio/include/asio/impl/dispatch.hpp deleted file mode 100644 index b602f6fcf41..00000000000 --- a/3rdparty/asio/include/asio/impl/dispatch.hpp +++ /dev/null @@ -1,251 +0,0 @@ -// -// impl/dispatch.hpp -// ~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IMPL_DISPATCH_HPP -#define ASIO_IMPL_DISPATCH_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/associated_allocator.hpp" -#include "asio/associated_executor.hpp" -#include "asio/detail/work_dispatcher.hpp" -#include "asio/execution/allocator.hpp" -#include "asio/execution/blocking.hpp" -#include "asio/prefer.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class initiate_dispatch -{ -public: - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - execution::is_executor< - typename associated_executor< - typename decay<CompletionHandler>::type - >::type - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_executor<handler_t>::type ex( - (get_associated_executor)(handler)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - execution::execute( - asio::prefer(ex, - execution::blocking.possibly, - execution::allocator(alloc)), - asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler))); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - !execution::is_executor< - typename associated_executor< - typename decay<CompletionHandler>::type - >::type - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_executor<handler_t>::type ex( - (get_associated_executor)(handler)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - ex.dispatch(asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); - } -}; - -template <typename Executor> -class initiate_dispatch_with_executor -{ -public: - typedef Executor executor_type; - - explicit initiate_dispatch_with_executor(const Executor& ex) - : ex_(ex) - { - } - - executor_type get_executor() const ASIO_NOEXCEPT - { - return ex_; - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - !detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - execution::execute( - asio::prefer(ex_, - execution::blocking.possibly, - execution::allocator(alloc)), - asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler))); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typedef typename associated_executor< - handler_t, Executor>::type handler_ex_t; - handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - execution::execute( - asio::prefer(ex_, - execution::blocking.possibly, - execution::allocator(alloc)), - detail::work_dispatcher<handler_t, handler_ex_t>( - ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex)); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - !execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - !detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - ex_.dispatch(asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - !execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typedef typename associated_executor< - handler_t, Executor>::type handler_ex_t; - handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - ex_.dispatch(detail::work_dispatcher<handler_t, handler_ex_t>( - ASIO_MOVE_CAST(CompletionHandler)(handler), - handler_ex), alloc); - } - -private: - Executor ex_; -}; - -} // namespace detail - -template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( - ASIO_MOVE_ARG(CompletionToken) token) -{ - return async_initiate<CompletionToken, void()>( - detail::initiate_dispatch(), token); -} - -template <typename Executor, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( - const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token, - typename constraint< - execution::is_executor<Executor>::value || is_executor<Executor>::value - >::type) -{ - return async_initiate<CompletionToken, void()>( - detail::initiate_dispatch_with_executor<Executor>(ex), token); -} - -template <typename ExecutionContext, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch( - ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token, - typename constraint<is_convertible< - ExecutionContext&, execution_context&>::value>::type) -{ - return async_initiate<CompletionToken, void()>( - detail::initiate_dispatch_with_executor< - typename ExecutionContext::executor_type>( - ctx.get_executor()), token); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IMPL_DISPATCH_HPP diff --git a/3rdparty/asio/include/asio/impl/error.ipp b/3rdparty/asio/include/asio/impl/error.ipp index 1dbb408f240..b564a8c68e2 100644 --- a/3rdparty/asio/include/asio/impl/error.ipp +++ b/3rdparty/asio/include/asio/impl/error.ipp @@ -2,7 +2,7 @@ // impl/error.ipp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -31,7 +31,7 @@ namespace detail { class netdb_category : public asio::error_category { public: - const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT + const char* name() const noexcept { return "asio.netdb"; } @@ -63,7 +63,7 @@ namespace detail { class addrinfo_category : public asio::error_category { public: - const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT + const char* name() const noexcept { return "asio.addrinfo"; } @@ -93,7 +93,7 @@ namespace detail { class misc_category : public asio::error_category { public: - const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT + const char* name() const noexcept { return "asio.misc"; } diff --git a/3rdparty/asio/include/asio/impl/error_code.ipp b/3rdparty/asio/include/asio/impl/error_code.ipp index 8c2253051dd..caeb1967caa 100644 --- a/3rdparty/asio/include/asio/impl/error_code.ipp +++ b/3rdparty/asio/include/asio/impl/error_code.ipp @@ -2,7 +2,7 @@ // impl/error_code.ipp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -37,7 +37,7 @@ namespace detail { class system_category : public error_category { public: - const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT + const char* name() const noexcept { return "asio.system"; } @@ -108,7 +108,7 @@ public: #if defined(ASIO_HAS_STD_ERROR_CODE) std::error_condition default_error_condition( - int ev) const ASIO_ERROR_CATEGORY_NOEXCEPT + int ev) const noexcept { switch (ev) { diff --git a/3rdparty/asio/include/asio/impl/execution_context.hpp b/3rdparty/asio/include/asio/impl/execution_context.hpp index ddbb99deba3..35dda80417f 100644 --- a/3rdparty/asio/include/asio/impl/execution_context.hpp +++ b/3rdparty/asio/include/asio/impl/execution_context.hpp @@ -2,7 +2,7 @@ // impl/execution_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -34,49 +34,17 @@ inline Service& use_service(execution_context& e) return e.service_registry_->template use_service<Service>(); } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Service, typename... Args> -Service& make_service(execution_context& e, ASIO_MOVE_ARG(Args)... args) +Service& make_service(execution_context& e, Args&&... args) { detail::scoped_ptr<Service> svc( - new Service(e, ASIO_MOVE_CAST(Args)(args)...)); + new Service(e, static_cast<Args&&>(args)...)); e.service_registry_->template add_service<Service>(svc.get()); Service& result = *svc; svc.release(); return result; } -#else // defined(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 ASIO_PRIVATE_MAKE_SERVICE_DEF(n) \ - template <typename Service, ASIO_VARIADIC_TPARAMS(n)> \ - Service& make_service(execution_context& e, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - detail::scoped_ptr<Service> svc( \ - new Service(e, ASIO_VARIADIC_MOVE_ARGS(n))); \ - e.service_registry_->template add_service<Service>(svc.get()); \ - Service& result = *svc; \ - svc.release(); \ - return result; \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_MAKE_SERVICE_DEF) -#undef ASIO_PRIVATE_MAKE_SERVICE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Service> inline void add_service(execution_context& e, Service* svc) { diff --git a/3rdparty/asio/include/asio/impl/execution_context.ipp b/3rdparty/asio/include/asio/impl/execution_context.ipp index 21adf8ef6ff..ed2603c9011 100644 --- a/3rdparty/asio/include/asio/impl/execution_context.ipp +++ b/3rdparty/asio/include/asio/impl/execution_context.ipp @@ -2,7 +2,7 @@ // impl/execution_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/impl/executor.hpp b/3rdparty/asio/include/asio/impl/executor.hpp index 3b473f32c1c..8bf76ccd183 100644 --- a/3rdparty/asio/include/asio/impl/executor.hpp +++ b/3rdparty/asio/include/asio/impl/executor.hpp @@ -2,7 +2,7 @@ // impl/executor.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,6 +19,7 @@ #if !defined(ASIO_NO_TS_EXECUTORS) +#include <new> #include "asio/detail/atomic_count.hpp" #include "asio/detail/global.hpp" #include "asio/detail/memory.hpp" @@ -47,7 +48,12 @@ public: return p; } - impl(const Executor& e, const Allocator& a) ASIO_NOEXCEPT + static impl_base* create(std::nothrow_t, const Executor& e) noexcept + { + return new (std::nothrow) impl(e, std::allocator<void>()); + } + + impl(const Executor& e, const Allocator& a) noexcept : impl_base(false), ref_count_(1), executor_(e), @@ -55,13 +61,13 @@ public: { } - impl_base* clone() const ASIO_NOEXCEPT + impl_base* clone() const noexcept { detail::ref_count_up(ref_count_); return const_cast<impl_base*>(static_cast<const impl_base*>(this)); } - void destroy() ASIO_NOEXCEPT + void destroy() noexcept { if (detail::ref_count_down(ref_count_)) { @@ -72,52 +78,52 @@ public: } } - void on_work_started() ASIO_NOEXCEPT + void on_work_started() noexcept { executor_.on_work_started(); } - void on_work_finished() ASIO_NOEXCEPT + void on_work_finished() noexcept { executor_.on_work_finished(); } - execution_context& context() ASIO_NOEXCEPT + execution_context& context() noexcept { return executor_.context(); } - void dispatch(ASIO_MOVE_ARG(function) f) + void dispatch(function&& f) { - executor_.dispatch(ASIO_MOVE_CAST(function)(f), allocator_); + executor_.dispatch(static_cast<function&&>(f), allocator_); } - void post(ASIO_MOVE_ARG(function) f) + void post(function&& f) { - executor_.post(ASIO_MOVE_CAST(function)(f), allocator_); + executor_.post(static_cast<function&&>(f), allocator_); } - void defer(ASIO_MOVE_ARG(function) f) + void defer(function&& f) { - executor_.defer(ASIO_MOVE_CAST(function)(f), allocator_); + executor_.defer(static_cast<function&&>(f), allocator_); } - type_id_result_type target_type() const ASIO_NOEXCEPT + type_id_result_type target_type() const noexcept { return type_id<Executor>(); } - void* target() ASIO_NOEXCEPT + void* target() noexcept { return &executor_; } - const void* target() const ASIO_NOEXCEPT + const void* target() const noexcept { return &executor_; } - bool equals(const impl_base* e) const ASIO_NOEXCEPT + bool equals(const impl_base* e) const noexcept { if (this == e) return true; @@ -164,7 +170,12 @@ public: static impl_base* create(const system_executor&, const Allocator& = Allocator()) { - return &detail::global<impl<system_executor, std::allocator<void> > >(); + return &detail::global<impl<system_executor, std::allocator<void>> >(); + } + + static impl_base* create(std::nothrow_t, const system_executor&) noexcept + { + return &detail::global<impl<system_executor, std::allocator<void>> >(); } impl() @@ -172,64 +183,64 @@ public: { } - impl_base* clone() const ASIO_NOEXCEPT + impl_base* clone() const noexcept { return const_cast<impl_base*>(static_cast<const impl_base*>(this)); } - void destroy() ASIO_NOEXCEPT + void destroy() noexcept { } - void on_work_started() ASIO_NOEXCEPT + void on_work_started() noexcept { executor_.on_work_started(); } - void on_work_finished() ASIO_NOEXCEPT + void on_work_finished() noexcept { executor_.on_work_finished(); } - execution_context& context() ASIO_NOEXCEPT + execution_context& context() noexcept { return executor_.context(); } - void dispatch(ASIO_MOVE_ARG(function) f) + void dispatch(function&& f) { - executor_.dispatch(ASIO_MOVE_CAST(function)(f), + executor_.dispatch(static_cast<function&&>(f), std::allocator<void>()); } - void post(ASIO_MOVE_ARG(function) f) + void post(function&& f) { - executor_.post(ASIO_MOVE_CAST(function)(f), + executor_.post(static_cast<function&&>(f), std::allocator<void>()); } - void defer(ASIO_MOVE_ARG(function) f) + void defer(function&& f) { - executor_.defer(ASIO_MOVE_CAST(function)(f), + executor_.defer(static_cast<function&&>(f), std::allocator<void>()); } - type_id_result_type target_type() const ASIO_NOEXCEPT + type_id_result_type target_type() const noexcept { return type_id<system_executor>(); } - void* target() ASIO_NOEXCEPT + void* target() noexcept { return &executor_; } - const void* target() const ASIO_NOEXCEPT + const void* target() const noexcept { return &executor_; } - bool equals(const impl_base* e) const ASIO_NOEXCEPT + bool equals(const impl_base* e) const noexcept { return this == e; } @@ -240,7 +251,13 @@ private: template <typename Executor> executor::executor(Executor e) - : impl_(impl<Executor, std::allocator<void> >::create(e)) + : impl_(impl<Executor, std::allocator<void>>::create(e)) +{ +} + +template <typename Executor> +executor::executor(std::nothrow_t, Executor e) noexcept + : impl_(impl<Executor, std::allocator<void>>::create(std::nothrow, e)) { } @@ -251,39 +268,39 @@ executor::executor(allocator_arg_t, const Allocator& a, Executor e) } template <typename Function, typename Allocator> -void executor::dispatch(ASIO_MOVE_ARG(Function) f, +void executor::dispatch(Function&& f, const Allocator& a) const { impl_base* i = get_impl(); if (i->fast_dispatch_) - system_executor().dispatch(ASIO_MOVE_CAST(Function)(f), a); + system_executor().dispatch(static_cast<Function&&>(f), a); else - i->dispatch(function(ASIO_MOVE_CAST(Function)(f), a)); + i->dispatch(function(static_cast<Function&&>(f), a)); } template <typename Function, typename Allocator> -void executor::post(ASIO_MOVE_ARG(Function) f, +void executor::post(Function&& f, const Allocator& a) const { - get_impl()->post(function(ASIO_MOVE_CAST(Function)(f), a)); + get_impl()->post(function(static_cast<Function&&>(f), a)); } template <typename Function, typename Allocator> -void executor::defer(ASIO_MOVE_ARG(Function) f, +void executor::defer(Function&& f, const Allocator& a) const { - get_impl()->defer(function(ASIO_MOVE_CAST(Function)(f), a)); + get_impl()->defer(function(static_cast<Function&&>(f), a)); } template <typename Executor> -Executor* executor::target() ASIO_NOEXCEPT +Executor* executor::target() noexcept { return impl_ && impl_->target_type() == type_id<Executor>() ? static_cast<Executor*>(impl_->target()) : 0; } template <typename Executor> -const Executor* executor::target() const ASIO_NOEXCEPT +const Executor* executor::target() const noexcept { return impl_ && impl_->target_type() == type_id<Executor>() ? static_cast<Executor*>(impl_->target()) : 0; diff --git a/3rdparty/asio/include/asio/impl/executor.ipp b/3rdparty/asio/include/asio/impl/executor.ipp index 393f79249c5..4153a171e09 100644 --- a/3rdparty/asio/include/asio/impl/executor.ipp +++ b/3rdparty/asio/include/asio/impl/executor.ipp @@ -2,7 +2,7 @@ // impl/executor.ipp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -25,11 +25,11 @@ namespace asio { -bad_executor::bad_executor() ASIO_NOEXCEPT +bad_executor::bad_executor() noexcept { } -const char* bad_executor::what() const ASIO_NOEXCEPT_OR_NOTHROW +const char* bad_executor::what() const noexcept { return "bad executor"; } diff --git a/3rdparty/asio/include/asio/impl/handler_alloc_hook.ipp b/3rdparty/asio/include/asio/impl/handler_alloc_hook.ipp deleted file mode 100644 index 531002b318e..00000000000 --- a/3rdparty/asio/include/asio/impl/handler_alloc_hook.ipp +++ /dev/null @@ -1,62 +0,0 @@ -// -// impl/handler_alloc_hook.ipp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IMPL_HANDLER_ALLOC_HOOK_IPP -#define ASIO_IMPL_HANDLER_ALLOC_HOOK_IPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/memory.hpp" -#include "asio/detail/thread_context.hpp" -#include "asio/detail/thread_info_base.hpp" -#include "asio/handler_alloc_hook.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { - -asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, ...) -{ -#if defined(ASIO_NO_DEPRECATED) - (void)size; - return asio_handler_allocate_is_no_longer_used(); -#elif !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) - return detail::thread_info_base::allocate( - detail::thread_context::top_of_thread_call_stack(), size); -#else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) - return aligned_new(ASIO_DEFAULT_ALIGN, size); -#endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) -} - -asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, ...) -{ -#if defined(ASIO_NO_DEPRECATED) - (void)pointer; - (void)size; - return asio_handler_deallocate_is_no_longer_used(); -#elif !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) - detail::thread_info_base::deallocate( - detail::thread_context::top_of_thread_call_stack(), pointer, size); -#else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) - (void)size; - aligned_delete(pointer) -#endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IMPL_HANDLER_ALLOC_HOOK_IPP diff --git a/3rdparty/asio/include/asio/impl/io_context.hpp b/3rdparty/asio/include/asio/impl/io_context.hpp index 7e624844aa8..002b585502d 100644 --- a/3rdparty/asio/include/asio/impl/io_context.hpp +++ b/3rdparty/asio/include/asio/impl/io_context.hpp @@ -2,7 +2,7 @@ // impl/io_context.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -50,13 +50,11 @@ inline detail::io_context_impl& use_service<detail::io_context_impl>( #endif // !defined(GENERATING_DOCUMENTATION) inline io_context::executor_type -io_context::get_executor() ASIO_NOEXCEPT +io_context::get_executor() noexcept { return executor_type(*this); } -#if defined(ASIO_HAS_CHRONO) - template <typename Rep, typename Period> std::size_t io_context::run_for( const chrono::duration<Rep, Period>& rel_time) @@ -108,8 +106,6 @@ std::size_t io_context::run_one_until( return 0; } -#endif // defined(ASIO_HAS_CHRONO) - #if !defined(ASIO_NO_DEPRECATED) inline void io_context::reset() @@ -120,7 +116,7 @@ inline void io_context::reset() struct io_context::initiate_dispatch { template <typename LegacyCompletionHandler> - void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler, + void operator()(LegacyCompletionHandler&& handler, io_context* self) const { // If you get an error on the following line it means that your handler does @@ -132,14 +128,13 @@ struct io_context::initiate_dispatch if (self->impl_.can_dispatch()) { detail::fenced_block b(detail::fenced_block::full); - asio_handler_invoke_helpers::invoke( - handler2.value, handler2.value); + static_cast<decay_t<LegacyCompletionHandler>&&>(handler2.value)(); } else { // Allocate and construct an operation to wrap the handler. typedef detail::completion_handler< - typename decay<LegacyCompletionHandler>::type, executor_type> op; + decay_t<LegacyCompletionHandler>, executor_type> op; typename op::ptr p = { detail::addressof(handler2.value), op::ptr::allocate(handler2.value), 0 }; p.p = new (p.v) op(handler2.value, self->get_executor()); @@ -154,8 +149,10 @@ struct io_context::initiate_dispatch }; template <typename LegacyCompletionHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ()) -io_context::dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler) +auto io_context::dispatch(LegacyCompletionHandler&& handler) + -> decltype( + async_initiate<LegacyCompletionHandler, void ()>( + declval<initiate_dispatch>(), handler, this)) { return async_initiate<LegacyCompletionHandler, void ()>( initiate_dispatch(), handler, this); @@ -164,7 +161,7 @@ io_context::dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler) struct io_context::initiate_post { template <typename LegacyCompletionHandler> - void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler, + void operator()(LegacyCompletionHandler&& handler, io_context* self) const { // If you get an error on the following line it means that your handler does @@ -179,7 +176,7 @@ struct io_context::initiate_post // Allocate and construct an operation to wrap the handler. typedef detail::completion_handler< - typename decay<LegacyCompletionHandler>::type, executor_type> op; + decay_t<LegacyCompletionHandler>, executor_type> op; typename op::ptr p = { detail::addressof(handler2.value), op::ptr::allocate(handler2.value), 0 }; p.p = new (p.v) op(handler2.value, self->get_executor()); @@ -193,8 +190,10 @@ struct io_context::initiate_post }; template <typename LegacyCompletionHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ()) -io_context::post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler) +auto io_context::post(LegacyCompletionHandler&& handler) + -> decltype( + async_initiate<LegacyCompletionHandler, void ()>( + declval<initiate_post>(), handler, this)) { return async_initiate<LegacyCompletionHandler, void ()>( initiate_post(), handler, this); @@ -213,21 +212,20 @@ io_context::wrap(Handler handler) #endif // !defined(ASIO_NO_DEPRECATED) -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> io_context::basic_executor_type<Allocator, Bits>& io_context::basic_executor_type<Allocator, Bits>::operator=( - const basic_executor_type& other) ASIO_NOEXCEPT + const basic_executor_type& other) noexcept { if (this != &other) { - io_context* old_io_context = io_context_; - io_context_ = other.io_context_; - allocator_ = other.allocator_; - bits_ = other.bits_; + static_cast<Allocator&>(*this) = static_cast<const Allocator&>(other); + io_context* old_io_context = context_ptr(); + target_ = other.target_; if (Bits & outstanding_work_tracked) { - if (io_context_) - io_context_->impl_.work_started(); + if (context_ptr()) + context_ptr()->impl_.work_started(); if (old_io_context) old_io_context->impl_.work_finished(); } @@ -235,122 +233,117 @@ io_context::basic_executor_type<Allocator, Bits>::operator=( return *this; } -#if defined(ASIO_HAS_MOVE) -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> io_context::basic_executor_type<Allocator, Bits>& io_context::basic_executor_type<Allocator, Bits>::operator=( - basic_executor_type&& other) ASIO_NOEXCEPT + basic_executor_type&& other) noexcept { if (this != &other) { - io_context* old_io_context = io_context_; - io_context_ = other.io_context_; - allocator_ = std::move(other.allocator_); - bits_ = other.bits_; + static_cast<Allocator&>(*this) = static_cast<Allocator&&>(other); + io_context* old_io_context = context_ptr(); + target_ = other.target_; if (Bits & outstanding_work_tracked) { - other.io_context_ = 0; + other.target_ = 0; if (old_io_context) old_io_context->impl_.work_finished(); } } return *this; } -#endif // defined(ASIO_HAS_MOVE) -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> inline bool io_context::basic_executor_type<Allocator, - Bits>::running_in_this_thread() const ASIO_NOEXCEPT + Bits>::running_in_this_thread() const noexcept { - return io_context_->impl_.can_dispatch(); + return context_ptr()->impl_.can_dispatch(); } -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> template <typename Function> void io_context::basic_executor_type<Allocator, Bits>::execute( - ASIO_MOVE_ARG(Function) f) const + Function&& f) const { - typedef typename decay<Function>::type function_type; + typedef decay_t<Function> function_type; // Invoke immediately if the blocking.possibly property is enabled and we are // already inside the thread pool. - if ((bits_ & blocking_never) == 0 && io_context_->impl_.can_dispatch()) + if ((bits() & blocking_never) == 0 && context_ptr()->impl_.can_dispatch()) { // Make a local, non-const copy of the function. - function_type tmp(ASIO_MOVE_CAST(Function)(f)); + function_type tmp(static_cast<Function&&>(f)); -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \ - && !defined(ASIO_NO_EXCEPTIONS) +#if !defined(ASIO_NO_EXCEPTIONS) try { -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - // && !defined(ASIO_NO_EXCEPTIONS) +#endif // !defined(ASIO_NO_EXCEPTIONS) detail::fenced_block b(detail::fenced_block::full); - asio_handler_invoke_helpers::invoke(tmp, tmp); + static_cast<function_type&&>(tmp)(); return; -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \ - && !defined(ASIO_NO_EXCEPTIONS) +#if !defined(ASIO_NO_EXCEPTIONS) } catch (...) { - io_context_->impl_.capture_current_exception(); + context_ptr()->impl_.capture_current_exception(); return; } -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - // && !defined(ASIO_NO_EXCEPTIONS) +#endif // !defined(ASIO_NO_EXCEPTIONS) } // Allocate and construct an operation to wrap the function. typedef detail::executor_op<function_type, Allocator, detail::operation> op; - typename op::ptr p = { detail::addressof(allocator_), - op::ptr::allocate(allocator_), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), allocator_); + typename op::ptr p = { + detail::addressof(static_cast<const Allocator&>(*this)), + op::ptr::allocate(static_cast<const Allocator&>(*this)), 0 }; + p.p = new (p.v) op(static_cast<Function&&>(f), + static_cast<const Allocator&>(*this)); - ASIO_HANDLER_CREATION((*io_context_, *p.p, - "io_context", io_context_, 0, "execute")); + ASIO_HANDLER_CREATION((*context_ptr(), *p.p, + "io_context", context_ptr(), 0, "execute")); - io_context_->impl_.post_immediate_completion(p.p, - (bits_ & relationship_continuation) != 0); + context_ptr()->impl_.post_immediate_completion(p.p, + (bits() & relationship_continuation) != 0); p.v = p.p = 0; } #if !defined(ASIO_NO_TS_EXECUTORS) -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> inline io_context& io_context::basic_executor_type< - Allocator, Bits>::context() const ASIO_NOEXCEPT + Allocator, Bits>::context() const noexcept { - return *io_context_; + return *context_ptr(); } -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> inline void io_context::basic_executor_type<Allocator, - Bits>::on_work_started() const ASIO_NOEXCEPT + Bits>::on_work_started() const noexcept { - io_context_->impl_.work_started(); + context_ptr()->impl_.work_started(); } -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> inline void io_context::basic_executor_type<Allocator, - Bits>::on_work_finished() const ASIO_NOEXCEPT + Bits>::on_work_finished() const noexcept { - io_context_->impl_.work_finished(); + context_ptr()->impl_.work_finished(); } -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> template <typename Function, typename OtherAllocator> void io_context::basic_executor_type<Allocator, Bits>::dispatch( - ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const + Function&& f, const OtherAllocator& a) const { - typedef typename decay<Function>::type function_type; + typedef decay_t<Function> function_type; // Invoke immediately if we are already inside the thread pool. - if (io_context_->impl_.can_dispatch()) + if (context_ptr()->impl_.can_dispatch()) { // Make a local, non-const copy of the function. - function_type tmp(ASIO_MOVE_CAST(Function)(f)); + function_type tmp(static_cast<Function&&>(f)); detail::fenced_block b(detail::fenced_block::full); - asio_handler_invoke_helpers::invoke(tmp, tmp); + static_cast<function_type&&>(tmp)(); return; } @@ -358,52 +351,48 @@ void io_context::basic_executor_type<Allocator, Bits>::dispatch( typedef detail::executor_op<function_type, OtherAllocator, detail::operation> op; typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a); + p.p = new (p.v) op(static_cast<Function&&>(f), a); - ASIO_HANDLER_CREATION((*io_context_, *p.p, - "io_context", io_context_, 0, "dispatch")); + ASIO_HANDLER_CREATION((*context_ptr(), *p.p, + "io_context", context_ptr(), 0, "dispatch")); - io_context_->impl_.post_immediate_completion(p.p, false); + context_ptr()->impl_.post_immediate_completion(p.p, false); p.v = p.p = 0; } -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> template <typename Function, typename OtherAllocator> void io_context::basic_executor_type<Allocator, Bits>::post( - ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const + Function&& f, const OtherAllocator& a) const { - typedef typename decay<Function>::type function_type; - // Allocate and construct an operation to wrap the function. - typedef detail::executor_op<function_type, + typedef detail::executor_op<decay_t<Function>, OtherAllocator, detail::operation> op; typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a); + p.p = new (p.v) op(static_cast<Function&&>(f), a); - ASIO_HANDLER_CREATION((*io_context_, *p.p, - "io_context", io_context_, 0, "post")); + ASIO_HANDLER_CREATION((*context_ptr(), *p.p, + "io_context", context_ptr(), 0, "post")); - io_context_->impl_.post_immediate_completion(p.p, false); + context_ptr()->impl_.post_immediate_completion(p.p, false); p.v = p.p = 0; } -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> template <typename Function, typename OtherAllocator> void io_context::basic_executor_type<Allocator, Bits>::defer( - ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const + Function&& f, const OtherAllocator& a) const { - typedef typename decay<Function>::type function_type; - // Allocate and construct an operation to wrap the function. - typedef detail::executor_op<function_type, + typedef detail::executor_op<decay_t<Function>, OtherAllocator, detail::operation> op; typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a); + p.p = new (p.v) op(static_cast<Function&&>(f), a); - ASIO_HANDLER_CREATION((*io_context_, *p.p, - "io_context", io_context_, 0, "defer")); + ASIO_HANDLER_CREATION((*context_ptr(), *p.p, + "io_context", context_ptr(), 0, "defer")); - io_context_->impl_.post_immediate_completion(p.p, true); + context_ptr()->impl_.post_immediate_completion(p.p, true); p.v = p.p = 0; } #endif // !defined(ASIO_NO_TS_EXECUTORS) diff --git a/3rdparty/asio/include/asio/impl/io_context.ipp b/3rdparty/asio/include/asio/impl/io_context.ipp index 3eb2b4576e5..14c8736c7b2 100644 --- a/3rdparty/asio/include/asio/impl/io_context.ipp +++ b/3rdparty/asio/include/asio/impl/io_context.ipp @@ -2,7 +2,7 @@ // impl/io_context.ipp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -54,6 +54,7 @@ io_context::impl_type& io_context::add_impl(io_context::impl_type* impl) io_context::~io_context() { + shutdown(); } io_context::count_type io_context::run() diff --git a/3rdparty/asio/include/asio/impl/multiple_exceptions.ipp b/3rdparty/asio/include/asio/impl/multiple_exceptions.ipp index fd2177f1f07..c922c27a055 100644 --- a/3rdparty/asio/include/asio/impl/multiple_exceptions.ipp +++ b/3rdparty/asio/include/asio/impl/multiple_exceptions.ipp @@ -2,7 +2,7 @@ // impl/multiple_exceptions.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,15 +22,13 @@ namespace asio { -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) - multiple_exceptions::multiple_exceptions( - std::exception_ptr first) ASIO_NOEXCEPT - : first_(ASIO_MOVE_CAST(std::exception_ptr)(first)) + std::exception_ptr first) noexcept + : first_(static_cast<std::exception_ptr&&>(first)) { } -const char* multiple_exceptions::what() const ASIO_NOEXCEPT_OR_NOTHROW +const char* multiple_exceptions::what() const noexcept { return "multiple exceptions"; } @@ -40,8 +38,6 @@ std::exception_ptr multiple_exceptions::first_exception() const return first_; } -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/impl/post.hpp b/3rdparty/asio/include/asio/impl/post.hpp deleted file mode 100644 index ec96a6cb903..00000000000 --- a/3rdparty/asio/include/asio/impl/post.hpp +++ /dev/null @@ -1,256 +0,0 @@ -// -// impl/post.hpp -// ~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_IMPL_POST_HPP -#define ASIO_IMPL_POST_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/associated_allocator.hpp" -#include "asio/associated_executor.hpp" -#include "asio/detail/work_dispatcher.hpp" -#include "asio/execution/allocator.hpp" -#include "asio/execution/blocking.hpp" -#include "asio/execution/relationship.hpp" -#include "asio/prefer.hpp" -#include "asio/require.hpp" - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace detail { - -class initiate_post -{ -public: - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - execution::is_executor< - typename associated_executor< - typename decay<CompletionHandler>::type - >::type - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_executor<handler_t>::type ex( - (get_associated_executor)(handler)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - execution::execute( - asio::prefer( - asio::require(ex, execution::blocking.never), - execution::relationship.fork, - execution::allocator(alloc)), - asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler))); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - !execution::is_executor< - typename associated_executor< - typename decay<CompletionHandler>::type - >::type - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_executor<handler_t>::type ex( - (get_associated_executor)(handler)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - ex.post(asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); - } -}; - -template <typename Executor> -class initiate_post_with_executor -{ -public: - typedef Executor executor_type; - - explicit initiate_post_with_executor(const Executor& ex) - : ex_(ex) - { - } - - executor_type get_executor() const ASIO_NOEXCEPT - { - return ex_; - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - !detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - execution::execute( - asio::prefer( - asio::require(ex_, execution::blocking.never), - execution::relationship.fork, - execution::allocator(alloc)), - asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler))); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typedef typename associated_executor< - handler_t, Executor>::type handler_ex_t; - handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - execution::execute( - asio::prefer( - asio::require(ex_, execution::blocking.never), - execution::relationship.fork, - execution::allocator(alloc)), - detail::work_dispatcher<handler_t, handler_ex_t>( - ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex)); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - !execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - !detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - ex_.post(asio::detail::bind_handler( - ASIO_MOVE_CAST(CompletionHandler)(handler)), alloc); - } - - template <typename CompletionHandler> - void operator()(ASIO_MOVE_ARG(CompletionHandler) handler, - typename enable_if< - !execution::is_executor< - typename conditional<true, executor_type, CompletionHandler>::type - >::value - >::type* = 0, - typename enable_if< - detail::is_work_dispatcher_required< - typename decay<CompletionHandler>::type, - Executor - >::value - >::type* = 0) const - { - typedef typename decay<CompletionHandler>::type handler_t; - - typedef typename associated_executor< - handler_t, Executor>::type handler_ex_t; - handler_ex_t handler_ex((get_associated_executor)(handler, ex_)); - - typename associated_allocator<handler_t>::type alloc( - (get_associated_allocator)(handler)); - - ex_.post(detail::work_dispatcher<handler_t, handler_ex_t>( - ASIO_MOVE_CAST(CompletionHandler)(handler), - handler_ex), alloc); - } - -private: - Executor ex_; -}; - -} // namespace detail - -template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( - ASIO_MOVE_ARG(CompletionToken) token) -{ - return async_initiate<CompletionToken, void()>( - detail::initiate_post(), token); -} - -template <typename Executor, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( - const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token, - typename constraint< - execution::is_executor<Executor>::value || is_executor<Executor>::value - >::type) -{ - return async_initiate<CompletionToken, void()>( - detail::initiate_post_with_executor<Executor>(ex), token); -} - -template <typename ExecutionContext, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( - ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token, - typename constraint<is_convertible< - ExecutionContext&, execution_context&>::value>::type) -{ - return async_initiate<CompletionToken, void()>( - detail::initiate_post_with_executor< - typename ExecutionContext::executor_type>( - ctx.get_executor()), token); -} - -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_IMPL_POST_HPP diff --git a/3rdparty/asio/include/asio/impl/prepend.hpp b/3rdparty/asio/include/asio/impl/prepend.hpp new file mode 100644 index 00000000000..f336d55d825 --- /dev/null +++ b/3rdparty/asio/include/asio/impl/prepend.hpp @@ -0,0 +1,163 @@ +// +// impl/prepend.hpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IMPL_PREPEND_HPP +#define ASIO_IMPL_PREPEND_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/associator.hpp" +#include "asio/async_result.hpp" +#include "asio/detail/handler_cont_helpers.hpp" +#include "asio/detail/type_traits.hpp" +#include "asio/detail/utility.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +// Class to adapt a prepend_t as a completion handler. +template <typename Handler, typename... Values> +class prepend_handler +{ +public: + typedef void result_type; + + template <typename H> + prepend_handler(H&& handler, std::tuple<Values...> values) + : handler_(static_cast<H&&>(handler)), + values_(static_cast<std::tuple<Values...>&&>(values)) + { + } + + template <typename... Args> + void operator()(Args&&... args) + { + this->invoke( + index_sequence_for<Values...>{}, + static_cast<Args&&>(args)...); + } + + template <std::size_t... I, typename... Args> + void invoke(index_sequence<I...>, Args&&... args) + { + static_cast<Handler&&>(handler_)( + static_cast<Values&&>(std::get<I>(values_))..., + static_cast<Args&&>(args)...); + } + +//private: + Handler handler_; + std::tuple<Values...> values_; +}; + +template <typename Handler> +inline bool asio_handler_is_continuation( + prepend_handler<Handler>* this_handler) +{ + return asio_handler_cont_helpers::is_continuation( + this_handler->handler_); +} + +template <typename Signature, typename... Values> +struct prepend_signature; + +template <typename R, typename... Args, typename... Values> +struct prepend_signature<R(Args...), Values...> +{ + typedef R type(Values..., decay_t<Args>...); +}; + +} // namespace detail + +#if !defined(GENERATING_DOCUMENTATION) + +template <typename CompletionToken, typename... Values, typename Signature> +struct async_result< + prepend_t<CompletionToken, Values...>, Signature> + : async_result<CompletionToken, + typename detail::prepend_signature< + Signature, Values...>::type> +{ + typedef typename detail::prepend_signature< + Signature, Values...>::type signature; + + template <typename Initiation> + struct init_wrapper + { + init_wrapper(Initiation init) + : initiation_(static_cast<Initiation&&>(init)) + { + } + + template <typename Handler, typename... Args> + void operator()(Handler&& handler, + std::tuple<Values...> values, Args&&... args) + { + static_cast<Initiation&&>(initiation_)( + detail::prepend_handler<decay_t<Handler>, Values...>( + static_cast<Handler&&>(handler), + static_cast<std::tuple<Values...>&&>(values)), + static_cast<Args&&>(args)...); + } + + Initiation initiation_; + }; + + template <typename Initiation, typename RawCompletionToken, typename... Args> + static auto initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) + -> decltype( + async_initiate<CompletionToken, signature>( + declval<init_wrapper<decay_t<Initiation>>>(), + token.token_, + static_cast<std::tuple<Values...>&&>(token.values_), + static_cast<Args&&>(args)...)) + { + return async_initiate<CompletionToken, signature>( + init_wrapper<decay_t<Initiation>>( + static_cast<Initiation&&>(initiation)), + token.token_, + static_cast<std::tuple<Values...>&&>(token.values_), + static_cast<Args&&>(args)...); + } +}; + +template <template <typename, typename> class Associator, + typename Handler, typename... Values, typename DefaultCandidate> +struct associator<Associator, + detail::prepend_handler<Handler, Values...>, DefaultCandidate> + : Associator<Handler, DefaultCandidate> +{ + static typename Associator<Handler, DefaultCandidate>::type get( + const detail::prepend_handler<Handler, Values...>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::prepend_handler<Handler, Values...>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) + { + return Associator<Handler, DefaultCandidate>::get(h.handler_, c); + } +}; + +#endif // !defined(GENERATING_DOCUMENTATION) + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IMPL_PREPEND_HPP diff --git a/3rdparty/asio/include/asio/impl/read.hpp b/3rdparty/asio/include/asio/impl/read.hpp index fb176d4343c..d86fb6467b1 100644 --- a/3rdparty/asio/include/asio/impl/read.hpp +++ b/3rdparty/asio/include/asio/impl/read.hpp @@ -2,7 +2,7 @@ // impl/read.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,16 +18,13 @@ #include <algorithm> #include "asio/associator.hpp" #include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp" #include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp" #include "asio/detail/dependent_type.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_tracking.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/non_const_lvalue.hpp" @@ -42,7 +39,7 @@ namespace detail { template <typename SyncReadStream, typename MutableBufferSequence, typename MutableBufferIterator, typename CompletionCondition> - std::size_t read_buffer_sequence(SyncReadStream& s, + std::size_t read_buffer_seq(SyncReadStream& s, const MutableBufferSequence& buffers, const MutableBufferIterator&, CompletionCondition completion_condition, asio::error_code& ec) { @@ -65,20 +62,20 @@ template <typename SyncReadStream, typename MutableBufferSequence, typename CompletionCondition> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type) + >) { - return detail::read_buffer_sequence(s, buffers, + return detail::read_buffer_seq(s, buffers, asio::buffer_sequence_begin(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); } template <typename SyncReadStream, typename MutableBufferSequence> inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, - typename constraint< + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec); @@ -89,9 +86,9 @@ 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, asio::error_code& ec, - typename constraint< + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type) + >) { return read(s, buffers, transfer_all(), ec); } @@ -100,13 +97,13 @@ template <typename SyncReadStream, typename MutableBufferSequence, typename CompletionCondition> inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition, - typename constraint< + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = read(s, buffers, - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); asio::detail::throw_error(ec, "read"); return bytes_transferred; } @@ -116,17 +113,17 @@ inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, template <typename SyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t read(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { - typename decay<DynamicBuffer_v1>::type b( - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); + decay_t<DynamicBuffer_v1> b( + static_cast<DynamicBuffer_v1&&>(buffers)); ec = asio::error_code(); std::size_t total_transferred = 0; @@ -151,52 +148,52 @@ std::size_t read(SyncReadStream& s, template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + DynamicBuffer_v1&& buffers, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { asio::error_code ec; std::size_t bytes_transferred = read(s, - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec); + static_cast<DynamicBuffer_v1&&>(buffers), transfer_all(), ec); asio::detail::throw_error(ec, "read"); return bytes_transferred; } template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { - return read(s, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + return read(s, static_cast<DynamicBuffer_v1&&>(buffers), transfer_all(), ec); } template <typename SyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition> inline std::size_t read(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, CompletionCondition completion_condition, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { asio::error_code ec; std::size_t bytes_transferred = read(s, - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<DynamicBuffer_v1&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition), ec); asio::detail::throw_error(ec, "read"); return bytes_transferred; } @@ -211,7 +208,7 @@ inline std::size_t read(SyncReadStream& s, CompletionCondition completion_condition, asio::error_code& ec) { return read(s, basic_streambuf_ref<Allocator>(b), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); } template <typename SyncReadStream, typename Allocator> @@ -236,7 +233,7 @@ inline std::size_t read(SyncReadStream& s, CompletionCondition completion_condition) { return read(s, basic_streambuf_ref<Allocator>(b), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + static_cast<CompletionCondition&&>(completion_condition)); } #endif // !defined(ASIO_NO_IOSTREAM) @@ -247,9 +244,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2, typename CompletionCondition> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { DynamicBuffer_v2& b = buffers; @@ -279,13 +276,13 @@ std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = read(s, - ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), transfer_all(), ec); + static_cast<DynamicBuffer_v2&&>(buffers), transfer_all(), ec); asio::detail::throw_error(ec, "read"); return bytes_transferred; } @@ -293,11 +290,11 @@ inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { - return read(s, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + return read(s, static_cast<DynamicBuffer_v2&&>(buffers), transfer_all(), ec); } @@ -305,14 +302,14 @@ template <typename SyncReadStream, typename DynamicBuffer_v2, typename CompletionCondition> inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = read(s, - ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<DynamicBuffer_v2&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition), ec); asio::detail::throw_error(ec, "read"); return bytes_transferred; } @@ -335,11 +332,10 @@ namespace detail stream_(stream), buffers_(buffers), start_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_op(const read_op& other) : base_from_cancellation_state<ReadHandler>(other), base_from_completion_cond<CompletionCondition>(other), @@ -352,18 +348,15 @@ namespace detail read_op(read_op&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), base_from_completion_cond<CompletionCondition>( - ASIO_MOVE_CAST(base_from_completion_cond< - CompletionCondition>)(other)), + static_cast<base_from_completion_cond<CompletionCondition>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)), + buffers_(static_cast<buffers_type&&>(other.buffers_)), start_(other.start_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -378,7 +371,7 @@ namespace detail { ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read")); stream_.async_read_some(buffers_.prepare(max_size), - ASIO_MOVE_CAST(read_op)(*this)); + static_cast<read_op&&>(*this)); } return; default: buffers_.consume(bytes_transferred); @@ -394,7 +387,7 @@ namespace detail } } - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)( + static_cast<ReadHandler&&>(handler_)( static_cast<const asio::error_code&>(ec), static_cast<const std::size_t&>(buffers_.total_consumed())); } @@ -413,38 +406,6 @@ namespace detail template <typename AsyncReadStream, typename MutableBufferSequence, typename MutableBufferIterator, typename CompletionCondition, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, - CompletionCondition, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename MutableBufferSequence, - typename MutableBufferIterator, typename CompletionCondition, - typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename MutableBufferSequence, - typename MutableBufferIterator, typename CompletionCondition, - typename ReadHandler> inline bool asio_handler_is_continuation( read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler) @@ -454,70 +415,40 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncReadStream, - typename MutableBufferSequence, typename MutableBufferIterator, - typename CompletionCondition, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncReadStream, - typename MutableBufferSequence, typename MutableBufferIterator, - typename CompletionCondition, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncReadStream, typename MutableBufferSequence, typename MutableBufferIterator, typename CompletionCondition, typename ReadHandler> - inline void start_read_buffer_sequence_op(AsyncReadStream& stream, + inline void start_read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers, const MutableBufferIterator&, CompletionCondition& completion_condition, ReadHandler& handler) { - detail::read_op<AsyncReadStream, MutableBufferSequence, + read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, CompletionCondition, ReadHandler>( stream, buffers, completion_condition, handler)( asio::error_code(), 0, 1); } template <typename AsyncReadStream> - class initiate_async_read_buffer_sequence + class initiate_async_read { public: typedef typename AsyncReadStream::executor_type executor_type; - explicit initiate_async_read_buffer_sequence(AsyncReadStream& stream) + explicit initiate_async_read(AsyncReadStream& stream) : stream_(stream) { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename ReadHandler, typename MutableBufferSequence, typename CompletionCondition> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(CompletionCondition) completion_cond) const + CompletionCondition&& completion_cond) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a ReadHandler. @@ -525,7 +456,7 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); - start_read_buffer_sequence_op(stream_, buffers, + start_read_op(stream_, buffers, asio::buffer_sequence_begin(buffers), completion_cond2.value, handler2.value); } @@ -549,8 +480,16 @@ struct associator<Associator, { static typename Associator<ReadHandler, DefaultCandidate>::type get( const detail::read_op<AsyncReadStream, MutableBufferSequence, + MutableBufferIterator, CompletionCondition, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator, CompletionCondition, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -561,37 +500,42 @@ struct associator<Associator, template <typename AsyncReadStream, typename MutableBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< + std::size_t)) ReadToken> +inline auto async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, + CompletionCondition completion_condition, ReadToken&& token, + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type) + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read<AsyncReadStream>>(), token, buffers, + static_cast<CompletionCondition&&>(completion_condition))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s), handler, - buffers, ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + detail::initiate_async_read<AsyncReadStream>(s), token, buffers, + static_cast<CompletionCondition&&>(completion_condition)); } template <typename AsyncReadStream, typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< + std::size_t)) ReadToken> +inline auto async_read(AsyncReadStream& s, + const MutableBufferSequence& buffers, ReadToken&& token, + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type) + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read<AsyncReadStream>>(), + token, buffers, transfer_all())) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s), - handler, buffers, transfer_all()); + detail::initiate_async_read<AsyncReadStream>(s), + token, buffers, transfer_all()); } #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -607,20 +551,19 @@ namespace detail public: template <typename BufferSequence> read_dynbuf_v1_op(AsyncReadStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, + BufferSequence&& buffers, CompletionCondition& completion_condition, ReadHandler& handler) : base_from_cancellation_state<ReadHandler>( handler, enable_partial_cancellation()), base_from_completion_cond<CompletionCondition>(completion_condition), stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), start_(0), total_transferred_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_dynbuf_v1_op(const read_dynbuf_v1_op& other) : base_from_cancellation_state<ReadHandler>(other), base_from_completion_cond<CompletionCondition>(other), @@ -634,19 +577,16 @@ namespace detail read_dynbuf_v1_op(read_dynbuf_v1_op&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), base_from_completion_cond<CompletionCondition>( - ASIO_MOVE_CAST(base_from_completion_cond< - CompletionCondition>)(other)), + static_cast<base_from_completion_cond<CompletionCondition>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), + buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)), start_(other.start_), total_transferred_(other.total_transferred_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -666,7 +606,7 @@ namespace detail { ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read")); stream_.async_read_some(buffers_.prepare(bytes_available), - ASIO_MOVE_CAST(read_dynbuf_v1_op)(*this)); + static_cast<read_dynbuf_v1_op&&>(*this)); } return; default: total_transferred_ += bytes_transferred; @@ -686,7 +626,7 @@ namespace detail } } - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)( + static_cast<ReadHandler&&>(handler_)( static_cast<const asio::error_code&>(ec), static_cast<const std::size_t&>(total_transferred_)); } @@ -702,36 +642,6 @@ namespace detail template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, - CompletionCondition, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v1, - typename CompletionCondition, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v1, - typename CompletionCondition, typename ReadHandler> inline bool asio_handler_is_continuation( read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, CompletionCondition, ReadHandler>* this_handler) @@ -741,36 +651,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v1, typename CompletionCondition, - typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v1, typename CompletionCondition, - typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncReadStream> class initiate_async_read_dynbuf_v1 { @@ -782,16 +662,16 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename ReadHandler, typename DynamicBuffer_v1, typename CompletionCondition> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - ASIO_MOVE_ARG(CompletionCondition) completion_cond) const + void operator()(ReadHandler&& handler, + DynamicBuffer_v1&& buffers, + CompletionCondition&& completion_cond) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a ReadHandler. @@ -799,9 +679,9 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); - read_dynbuf_v1_op<AsyncReadStream, typename decay<DynamicBuffer_v1>::type, - CompletionCondition, typename decay<ReadHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + read_dynbuf_v1_op<AsyncReadStream, decay_t<DynamicBuffer_v1>, + CompletionCondition, decay_t<ReadHandler>>( + stream_, static_cast<DynamicBuffer_v1&&>(buffers), completion_cond2.value, handler2.value)( asio::error_code(), 0, 1); } @@ -824,9 +704,17 @@ struct associator<Associator, : Associator<ReadHandler, DefaultCandidate> { static typename Associator<ReadHandler, DefaultCandidate>::type get( + const detail::read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, + CompletionCondition, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( const detail::read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1, CompletionCondition, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -836,46 +724,51 @@ struct associator<Associator, template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + std::size_t)) ReadToken> +inline auto async_read(AsyncReadStream& s, + DynamicBuffer_v1&& buffers, ReadToken&& token, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), transfer_all())) { - return async_read(s, - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), - transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler)); + return async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s), + token, static_cast<DynamicBuffer_v1&&>(buffers), transfer_all()); } template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + std::size_t)) ReadToken> +inline auto async_read(AsyncReadStream& s, DynamicBuffer_v1&& buffers, + CompletionCondition completion_condition, ReadToken&& token, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s), - handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + token, static_cast<DynamicBuffer_v1&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition)); } #if !defined(ASIO_NO_EXTENSIONS) @@ -883,29 +776,39 @@ async_read(AsyncReadStream& s, template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, - ASIO_MOVE_ARG(ReadHandler) handler) + std::size_t)) ReadToken> +inline auto async_read(AsyncReadStream& s, + basic_streambuf<Allocator>& b, ReadToken&& token) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), transfer_all())) { - return async_read(s, basic_streambuf_ref<Allocator>(b), - ASIO_MOVE_CAST(ReadHandler)(handler)); + return async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s), + token, basic_streambuf_ref<Allocator>(b), transfer_all()); } template <typename AsyncReadStream, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler) + std::size_t)) ReadToken> +inline auto async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, + CompletionCondition completion_condition, ReadToken&& token) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), + static_cast<CompletionCondition&&>(completion_condition))) { - return async_read(s, basic_streambuf_ref<Allocator>(b), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), - ASIO_MOVE_CAST(ReadHandler)(handler)); + return async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s), + token, basic_streambuf_ref<Allocator>(b), + static_cast<CompletionCondition&&>(completion_condition)); } #endif // !defined(ASIO_NO_IOSTREAM) @@ -923,21 +826,20 @@ namespace detail public: template <typename BufferSequence> read_dynbuf_v2_op(AsyncReadStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, + BufferSequence&& buffers, CompletionCondition& completion_condition, ReadHandler& handler) : base_from_cancellation_state<ReadHandler>( handler, enable_partial_cancellation()), base_from_completion_cond<CompletionCondition>(completion_condition), stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), start_(0), total_transferred_(0), bytes_available_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_dynbuf_v2_op(const read_dynbuf_v2_op& other) : base_from_cancellation_state<ReadHandler>(other), base_from_completion_cond<CompletionCondition>(other), @@ -952,20 +854,17 @@ namespace detail read_dynbuf_v2_op(read_dynbuf_v2_op&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), base_from_completion_cond<CompletionCondition>( - ASIO_MOVE_CAST(base_from_completion_cond< - CompletionCondition>)(other)), + static_cast<base_from_completion_cond<CompletionCondition>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), + buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)), start_(other.start_), total_transferred_(other.total_transferred_), bytes_available_(other.bytes_available_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -987,7 +886,7 @@ namespace detail { ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read")); stream_.async_read_some(buffers_.data(pos, bytes_available_), - ASIO_MOVE_CAST(read_dynbuf_v2_op)(*this)); + static_cast<read_dynbuf_v2_op&&>(*this)); } return; default: total_transferred_ += bytes_transferred; @@ -1007,7 +906,7 @@ namespace detail } } - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)( + static_cast<ReadHandler&&>(handler_)( static_cast<const asio::error_code&>(ec), static_cast<const std::size_t&>(total_transferred_)); } @@ -1024,36 +923,6 @@ namespace detail template <typename AsyncReadStream, typename DynamicBuffer_v2, typename CompletionCondition, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, - CompletionCondition, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v2, - typename CompletionCondition, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v2, - typename CompletionCondition, typename ReadHandler> inline bool asio_handler_is_continuation( read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, CompletionCondition, ReadHandler>* this_handler) @@ -1063,36 +932,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v2, typename CompletionCondition, - typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v2, typename CompletionCondition, - typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncReadStream> class initiate_async_read_dynbuf_v2 { @@ -1104,16 +943,16 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename ReadHandler, typename DynamicBuffer_v2, typename CompletionCondition> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, - ASIO_MOVE_ARG(CompletionCondition) completion_cond) const + void operator()(ReadHandler&& handler, + DynamicBuffer_v2&& buffers, + CompletionCondition&& completion_cond) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a ReadHandler. @@ -1121,9 +960,9 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); - read_dynbuf_v2_op<AsyncReadStream, typename decay<DynamicBuffer_v2>::type, - CompletionCondition, typename decay<ReadHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + read_dynbuf_v2_op<AsyncReadStream, decay_t<DynamicBuffer_v2>, + CompletionCondition, decay_t<ReadHandler>>( + stream_, static_cast<DynamicBuffer_v2&&>(buffers), completion_cond2.value, handler2.value)( asio::error_code(), 0, 1); } @@ -1146,9 +985,17 @@ struct associator<Associator, : Associator<ReadHandler, DefaultCandidate> { static typename Associator<ReadHandler, DefaultCandidate>::type get( + const detail::read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, + CompletionCondition, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( const detail::read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2, CompletionCondition, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -1158,38 +1005,45 @@ struct associator<Associator, template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, - ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< + std::size_t)) ReadToken> +inline auto async_read(AsyncReadStream& s, + DynamicBuffer_v2 buffers, ReadToken&& token, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), transfer_all())) { - return async_read(s, - ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), - transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler)); + return async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s), + token, static_cast<DynamicBuffer_v2&&>(buffers), transfer_all()); } template <typename AsyncReadStream, typename DynamicBuffer_v2, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< + std::size_t)) ReadToken> +inline auto async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, ReadToken&& token, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s), - handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + token, static_cast<DynamicBuffer_v2&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition)); } } // namespace asio diff --git a/3rdparty/asio/include/asio/impl/read_at.hpp b/3rdparty/asio/include/asio/impl/read_at.hpp index 7d37c4ddfa4..7c668a03f46 100644 --- a/3rdparty/asio/include/asio/impl/read_at.hpp +++ b/3rdparty/asio/include/asio/impl/read_at.hpp @@ -2,7 +2,7 @@ // impl/read_at.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,16 +18,13 @@ #include <algorithm> #include "asio/associator.hpp" #include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp" #include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp" #include "asio/detail/dependent_type.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_tracking.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/non_const_lvalue.hpp" @@ -73,7 +70,7 @@ std::size_t read_at(SyncRandomAccessReadDevice& d, { return detail::read_at_buffer_sequence(d, offset, buffers, asio::buffer_sequence_begin(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); } template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence> @@ -103,7 +100,7 @@ inline std::size_t read_at(SyncRandomAccessReadDevice& d, { asio::error_code ec; std::size_t bytes_transferred = read_at(d, offset, buffers, - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); asio::detail::throw_error(ec, "read_at"); return bytes_transferred; } @@ -162,7 +159,7 @@ inline std::size_t read_at(SyncRandomAccessReadDevice& d, { asio::error_code ec; std::size_t bytes_transferred = read_at(d, offset, b, - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); asio::detail::throw_error(ec, "read_at"); return bytes_transferred; } @@ -190,11 +187,10 @@ namespace detail offset_(offset), buffers_(buffers), start_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_at_op(const read_at_op& other) : base_from_cancellation_state<ReadHandler>(other), base_from_completion_cond<CompletionCondition>(other), @@ -208,19 +204,16 @@ namespace detail read_at_op(read_at_op&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), base_from_completion_cond<CompletionCondition>( - ASIO_MOVE_CAST(base_from_completion_cond< - CompletionCondition>)(other)), + static_cast<base_from_completion_cond<CompletionCondition>&&>(other)), device_(other.device_), offset_(other.offset_), - buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)), + buffers_(static_cast<buffers_type&&>(other.buffers_)), start_(other.start_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -236,7 +229,7 @@ namespace detail ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at")); device_.async_read_some_at( offset_ + buffers_.total_consumed(), buffers_.prepare(max_size), - ASIO_MOVE_CAST(read_at_op)(*this)); + static_cast<read_at_op&&>(*this)); } return; default: buffers_.consume(bytes_transferred); @@ -252,7 +245,7 @@ namespace detail } } - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)( + static_cast<ReadHandler&&>(handler_)( static_cast<const asio::error_code&>(ec), static_cast<const std::size_t&>(buffers_.total_consumed())); } @@ -272,38 +265,6 @@ namespace detail template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, typename MutableBufferIterator, typename CompletionCondition, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, - MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncRandomAccessReadDevice, - typename MutableBufferSequence, typename MutableBufferIterator, - typename CompletionCondition, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, - MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncRandomAccessReadDevice, - typename MutableBufferSequence, typename MutableBufferIterator, - typename CompletionCondition, typename ReadHandler> inline bool asio_handler_is_continuation( read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler) @@ -313,40 +274,10 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncRandomAccessReadDevice, - typename MutableBufferSequence, typename MutableBufferIterator, - typename CompletionCondition, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, - MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncRandomAccessReadDevice, - typename MutableBufferSequence, typename MutableBufferIterator, - typename CompletionCondition, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, - MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, typename MutableBufferIterator, typename CompletionCondition, typename ReadHandler> - inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d, + inline void start_read_at_op(AsyncRandomAccessReadDevice& d, uint64_t offset, const MutableBufferSequence& buffers, const MutableBufferIterator&, CompletionCondition& completion_condition, ReadHandler& handler) @@ -358,27 +289,26 @@ namespace detail } template <typename AsyncRandomAccessReadDevice> - class initiate_async_read_at_buffer_sequence + class initiate_async_read_at { public: typedef typename AsyncRandomAccessReadDevice::executor_type executor_type; - explicit initiate_async_read_at_buffer_sequence( - AsyncRandomAccessReadDevice& device) + explicit initiate_async_read_at(AsyncRandomAccessReadDevice& device) : device_(device) { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return device_.get_executor(); } template <typename ReadHandler, typename MutableBufferSequence, typename CompletionCondition> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, uint64_t offset, const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(CompletionCondition) completion_cond) const + CompletionCondition&& completion_cond) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a ReadHandler. @@ -386,7 +316,7 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); - start_read_at_buffer_sequence_op(device_, offset, buffers, + start_read_at_op(device_, offset, buffers, asio::buffer_sequence_begin(buffers), completion_cond2.value, handler2.value); } @@ -411,8 +341,17 @@ struct associator<Associator, static typename Associator<ReadHandler, DefaultCandidate>::type get( const detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence, MutableBufferIterator, + CompletionCondition, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::read_at_op<AsyncRandomAccessReadDevice, + MutableBufferSequence, MutableBufferIterator, CompletionCondition, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -423,36 +362,39 @@ struct associator<Associator, template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_at(AsyncRandomAccessReadDevice& d, + std::size_t)) ReadToken> +inline auto async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, const MutableBufferSequence& buffers, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler) + CompletionCondition completion_condition, ReadToken&& token) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice>>(), + token, offset, buffers, + static_cast<CompletionCondition&&>(completion_condition))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - detail::initiate_async_read_at_buffer_sequence< - AsyncRandomAccessReadDevice>(d), - handler, offset, buffers, - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d), + token, offset, buffers, + static_cast<CompletionCondition&&>(completion_condition)); } template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_at(AsyncRandomAccessReadDevice& d, - uint64_t offset, const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler) + std::size_t)) ReadToken> +inline auto async_read_at(AsyncRandomAccessReadDevice& d, + uint64_t offset, const MutableBufferSequence& buffers, ReadToken&& token) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice>>(), + token, offset, buffers, transfer_all())) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - detail::initiate_async_read_at_buffer_sequence< - AsyncRandomAccessReadDevice>(d), - handler, offset, buffers, transfer_all()); + detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d), + token, offset, buffers, transfer_all()); } #if !defined(ASIO_NO_EXTENSIONS) @@ -478,11 +420,10 @@ namespace detail streambuf_(streambuf), start_(0), total_transferred_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_at_streambuf_op(const read_at_streambuf_op& other) : base_from_cancellation_state<ReadHandler>(other), base_from_completion_cond<CompletionCondition>(other), @@ -497,20 +438,17 @@ namespace detail read_at_streambuf_op(read_at_streambuf_op&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), base_from_completion_cond<CompletionCondition>( - ASIO_MOVE_CAST(base_from_completion_cond< - CompletionCondition>)(other)), + static_cast<base_from_completion_cond<CompletionCondition>&&>(other)), device_(other.device_), offset_(other.offset_), streambuf_(other.streambuf_), start_(other.start_), total_transferred_(other.total_transferred_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -527,7 +465,7 @@ namespace detail ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at")); device_.async_read_some_at(offset_ + total_transferred_, streambuf_.prepare(bytes_available), - ASIO_MOVE_CAST(read_at_streambuf_op)(*this)); + static_cast<read_at_streambuf_op&&>(*this)); } return; default: total_transferred_ += bytes_transferred; @@ -543,7 +481,7 @@ namespace detail } } - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)( + static_cast<ReadHandler&&>(handler_)( static_cast<const asio::error_code&>(ec), static_cast<const std::size_t&>(total_transferred_)); } @@ -560,36 +498,6 @@ namespace detail template <typename AsyncRandomAccessReadDevice, typename Allocator, typename CompletionCondition, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, - CompletionCondition, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncRandomAccessReadDevice, typename Allocator, - typename CompletionCondition, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncRandomAccessReadDevice, typename Allocator, - typename CompletionCondition, typename ReadHandler> inline bool asio_handler_is_continuation( read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, CompletionCondition, ReadHandler>* this_handler) @@ -599,34 +507,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncRandomAccessReadDevice, - typename Allocator, typename CompletionCondition, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncRandomAccessReadDevice, - typename Allocator, typename CompletionCondition, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, - CompletionCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncRandomAccessReadDevice> class initiate_async_read_at_streambuf { @@ -639,16 +519,16 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return device_.get_executor(); } template <typename ReadHandler, typename Allocator, typename CompletionCondition> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, uint64_t offset, basic_streambuf<Allocator>* b, - ASIO_MOVE_ARG(CompletionCondition) completion_cond) const + CompletionCondition&& completion_cond) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a ReadHandler. @@ -657,7 +537,7 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator, - CompletionCondition, typename decay<ReadHandler>::type>( + CompletionCondition, decay_t<ReadHandler>>( device_, offset, *b, completion_cond2.value, handler2.value)( asio::error_code(), 0, 1); } @@ -681,8 +561,16 @@ struct associator<Associator, { static typename Associator<ReadHandler, DefaultCandidate>::type get( const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, + Executor, CompletionCondition, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice, Executor, CompletionCondition, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -693,34 +581,41 @@ struct associator<Associator, template <typename AsyncRandomAccessReadDevice, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_at(AsyncRandomAccessReadDevice& d, + std::size_t)) ReadToken> +inline auto async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, asio::basic_streambuf<Allocator>& b, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler) + CompletionCondition completion_condition, ReadToken&& token) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_at_streambuf< + AsyncRandomAccessReadDevice>>(), + token, offset, &b, + static_cast<CompletionCondition&&>(completion_condition))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d), - handler, offset, &b, - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + token, offset, &b, + static_cast<CompletionCondition&&>(completion_condition)); } template <typename AsyncRandomAccessReadDevice, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_at(AsyncRandomAccessReadDevice& d, - uint64_t offset, asio::basic_streambuf<Allocator>& b, - ASIO_MOVE_ARG(ReadHandler) handler) + std::size_t)) ReadToken> +inline auto async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, + asio::basic_streambuf<Allocator>& b, ReadToken&& token) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_at_streambuf< + AsyncRandomAccessReadDevice>>(), + token, offset, &b, transfer_all())) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d), - handler, offset, &b, transfer_all()); + token, offset, &b, transfer_all()); } #endif // !defined(ASIO_NO_IOSTREAM) diff --git a/3rdparty/asio/include/asio/impl/read_until.hpp b/3rdparty/asio/include/asio/impl/read_until.hpp index d3a6f259933..7592263723f 100644 --- a/3rdparty/asio/include/asio/impl/read_until.hpp +++ b/3rdparty/asio/include/asio/impl/read_until.hpp @@ -2,7 +2,7 @@ // impl/read_until.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -24,9 +24,7 @@ #include "asio/buffers_iterator.hpp" #include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/bind_handler.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_tracking.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/limits.hpp" @@ -76,34 +74,34 @@ namespace detail template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + DynamicBuffer_v1&& buffers, char delim, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { asio::error_code ec; std::size_t bytes_transferred = read_until(s, - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec); + static_cast<DynamicBuffer_v1&&>(buffers), delim, ec); asio::detail::throw_error(ec, "read_until"); return bytes_transferred; } template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, char delim, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { - typename decay<DynamicBuffer_v1>::type b( - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); + decay_t<DynamicBuffer_v1> b( + static_cast<DynamicBuffer_v1&&>(buffers)); std::size_t search_position = 0; for (;;) @@ -149,35 +147,35 @@ std::size_t read_until(SyncReadStream& s, template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, ASIO_STRING_VIEW_PARAM delim, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { asio::error_code ec; std::size_t bytes_transferred = read_until(s, - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec); + static_cast<DynamicBuffer_v1&&>(buffers), delim, ec); asio::detail::throw_error(ec, "read_until"); return bytes_transferred; } template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { - typename decay<DynamicBuffer_v1>::type b( - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); + decay_t<DynamicBuffer_v1> b( + static_cast<DynamicBuffer_v1&&>(buffers)); std::size_t search_position = 0; for (;;) @@ -233,37 +231,48 @@ std::size_t read_until(SyncReadStream& s, #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) -template <typename SyncReadStream, typename DynamicBuffer_v1> -inline std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - const boost::regex& expr, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) +namespace detail { + +struct regex_match_flags +{ + template <typename T> + operator T() const + { + return T::match_default | T::match_partial; + } +}; + +} // namespace detail + +template <typename SyncReadStream, typename DynamicBuffer_v1, typename Traits> +inline std::size_t read_until(SyncReadStream& s, DynamicBuffer_v1&& buffers, + const boost::basic_regex<char, Traits>& expr, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { asio::error_code ec; std::size_t bytes_transferred = read_until(s, - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr, ec); + static_cast<DynamicBuffer_v1&&>(buffers), expr, ec); asio::detail::throw_error(ec, "read_until"); return bytes_transferred; } -template <typename SyncReadStream, typename DynamicBuffer_v1> -std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - const boost::regex& expr, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) +template <typename SyncReadStream, typename DynamicBuffer_v1, typename Traits> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v1&& buffers, + const boost::basic_regex<char, Traits>& expr, asio::error_code& ec, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { - typename decay<DynamicBuffer_v1>::type b( - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); + decay_t<DynamicBuffer_v1> b( + static_cast<DynamicBuffer_v1&&>(buffers)); std::size_t search_position = 0; for (;;) @@ -278,10 +287,10 @@ std::size_t read_until(SyncReadStream& s, // Look for a match. boost::match_results<iterator, - typename std::vector<boost::sub_match<iterator> >::allocator_type> + typename std::vector<boost::sub_match<iterator>>::allocator_type> match_results; - if (regex_search(start_pos, end, match_results, expr, - boost::match_default | boost::match_partial)) + if (regex_search(start_pos, end, match_results, + expr, detail::regex_match_flags())) { if (match_results[0].matched) { @@ -323,21 +332,21 @@ std::size_t read_until(SyncReadStream& s, template <typename SyncReadStream, typename DynamicBuffer_v1, typename MatchCondition> inline std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, MatchCondition match_condition, - typename constraint< + constraint_t< is_match_condition<MatchCondition>::value - >::type, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + >, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { asio::error_code ec; std::size_t bytes_transferred = read_until(s, - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + static_cast<DynamicBuffer_v1&&>(buffers), match_condition, ec); asio::detail::throw_error(ec, "read_until"); return bytes_transferred; @@ -346,20 +355,20 @@ inline std::size_t read_until(SyncReadStream& s, template <typename SyncReadStream, typename DynamicBuffer_v1, typename MatchCondition> std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, MatchCondition match_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_match_condition<MatchCondition>::value - >::type, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + >, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { - typename decay<DynamicBuffer_v1>::type b( - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); + decay_t<DynamicBuffer_v1> b( + static_cast<DynamicBuffer_v1&&>(buffers)); std::size_t search_position = 0; for (;;) @@ -443,16 +452,18 @@ inline std::size_t read_until(SyncReadStream& s, #if defined(ASIO_HAS_BOOST_REGEX) -template <typename SyncReadStream, typename Allocator> +template <typename SyncReadStream, typename Allocator, typename Traits> inline std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf<Allocator>& b, const boost::regex& expr) + asio::basic_streambuf<Allocator>& b, + const boost::basic_regex<char, Traits>& expr) { return read_until(s, basic_streambuf_ref<Allocator>(b), expr); } -template <typename SyncReadStream, typename Allocator> +template <typename SyncReadStream, typename Allocator, typename Traits> inline std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf<Allocator>& b, const boost::regex& expr, + asio::basic_streambuf<Allocator>& b, + const boost::basic_regex<char, Traits>& expr, asio::error_code& ec) { return read_until(s, basic_streambuf_ref<Allocator>(b), expr, ec); @@ -463,7 +474,7 @@ inline std::size_t read_until(SyncReadStream& s, template <typename SyncReadStream, typename Allocator, typename MatchCondition> inline std::size_t read_until(SyncReadStream& s, asio::basic_streambuf<Allocator>& b, MatchCondition match_condition, - typename constraint<is_match_condition<MatchCondition>::value>::type) + constraint_t<is_match_condition<MatchCondition>::value>) { return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition); } @@ -472,7 +483,7 @@ template <typename SyncReadStream, typename Allocator, typename MatchCondition> inline std::size_t read_until(SyncReadStream& s, asio::basic_streambuf<Allocator>& b, MatchCondition match_condition, asio::error_code& ec, - typename constraint<is_match_condition<MatchCondition>::value>::type) + constraint_t<is_match_condition<MatchCondition>::value>) { return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition, ec); } @@ -484,13 +495,13 @@ inline std::size_t read_until(SyncReadStream& s, template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = read_until(s, - ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec); + static_cast<DynamicBuffer_v2&&>(buffers), delim, ec); asio::detail::throw_error(ec, "read_until"); return bytes_transferred; } @@ -498,9 +509,9 @@ inline std::size_t read_until(SyncReadStream& s, template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { DynamicBuffer_v2& b = buffers; @@ -553,13 +564,13 @@ std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = read_until(s, - ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec); + static_cast<DynamicBuffer_v2&&>(buffers), delim, ec); asio::detail::throw_error(ec, "read_until"); return bytes_transferred; } @@ -567,9 +578,9 @@ inline std::size_t read_until(SyncReadStream& s, template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { DynamicBuffer_v2& b = buffers; @@ -631,26 +642,26 @@ std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) -template <typename SyncReadStream, typename DynamicBuffer_v2> -inline std::size_t read_until(SyncReadStream& s, - DynamicBuffer_v2 buffers, const boost::regex& expr, - typename constraint< +template <typename SyncReadStream, typename DynamicBuffer_v2, typename Traits> +inline std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, + const boost::basic_regex<char, Traits>& expr, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = read_until(s, - ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr, ec); + static_cast<DynamicBuffer_v2&&>(buffers), expr, ec); asio::detail::throw_error(ec, "read_until"); return bytes_transferred; } -template <typename SyncReadStream, typename DynamicBuffer_v2> +template <typename SyncReadStream, typename DynamicBuffer_v2, typename Traits> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, - const boost::regex& expr, asio::error_code& ec, - typename constraint< + const boost::basic_regex<char, Traits>& expr, asio::error_code& ec, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { DynamicBuffer_v2& b = buffers; @@ -668,10 +679,10 @@ std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, // Look for a match. boost::match_results<iterator, - typename std::vector<boost::sub_match<iterator> >::allocator_type> + typename std::vector<boost::sub_match<iterator>>::allocator_type> match_results; - if (regex_search(start_pos, end, match_results, expr, - boost::match_default | boost::match_partial)) + if (regex_search(start_pos, end, match_results, + expr, detail::regex_match_flags())) { if (match_results[0].matched) { @@ -717,16 +728,16 @@ template <typename SyncReadStream, typename DynamicBuffer_v2, typename MatchCondition> inline std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, MatchCondition match_condition, - typename constraint< + constraint_t< is_match_condition<MatchCondition>::value - >::type, - typename constraint< + >, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = read_until(s, - ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + static_cast<DynamicBuffer_v2&&>(buffers), match_condition, ec); asio::detail::throw_error(ec, "read_until"); return bytes_transferred; @@ -736,12 +747,12 @@ template <typename SyncReadStream, typename DynamicBuffer_v2, typename MatchCondition> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, MatchCondition match_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_match_condition<MatchCondition>::value - >::type, - typename constraint< + >, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { DynamicBuffer_v2& b = buffers; @@ -810,20 +821,19 @@ namespace detail public: template <typename BufferSequence> read_until_delim_op_v1(AsyncReadStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, + BufferSequence&& buffers, char delim, ReadHandler& handler) : base_from_cancellation_state<ReadHandler>( handler, enable_partial_cancellation()), stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), delim_(delim), start_(0), search_position_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_until_delim_op_v1(const read_until_delim_op_v1& other) : base_from_cancellation_state<ReadHandler>(other), stream_(other.stream_), @@ -837,17 +847,15 @@ namespace detail read_until_delim_op_v1(read_until_delim_op_v1&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), + buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)), delim_(other.delim_), start_(other.start_), search_position_(other.search_position_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -907,7 +915,7 @@ namespace detail ASIO_HANDLER_LOCATION(( __FILE__, __LINE__, "async_read_until")); stream_.async_read_some(buffers_.prepare(bytes_to_read), - ASIO_MOVE_CAST(read_until_delim_op_v1)(*this)); + static_cast<read_until_delim_op_v1&&>(*this)); } return; default: buffers_.commit(bytes_transferred); @@ -928,7 +936,7 @@ namespace detail (ec || search_position_ == not_found) ? 0 : search_position_; - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); + static_cast<ReadHandler&&>(handler_)(result_ec, result_n); } } @@ -943,36 +951,6 @@ namespace detail template <typename AsyncReadStream, typename DynamicBuffer_v1, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_until_delim_op_v1<AsyncReadStream, - DynamicBuffer_v1, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, - typename DynamicBuffer_v1, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_until_delim_op_v1<AsyncReadStream, - DynamicBuffer_v1, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, - typename DynamicBuffer_v1, typename ReadHandler> inline bool asio_handler_is_continuation( read_until_delim_op_v1<AsyncReadStream, DynamicBuffer_v1, ReadHandler>* this_handler) @@ -982,34 +960,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v1, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_until_delim_op_v1<AsyncReadStream, - DynamicBuffer_v1, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v1, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_until_delim_op_v1<AsyncReadStream, - DynamicBuffer_v1, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncReadStream> class initiate_async_read_until_delim_v1 { @@ -1021,14 +971,14 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename ReadHandler, typename DynamicBuffer_v1> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + void operator()(ReadHandler&& handler, + DynamicBuffer_v1&& buffers, char delim) const { // If you get an error on the following line it means that your handler @@ -1037,9 +987,9 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); read_until_delim_op_v1<AsyncReadStream, - typename decay<DynamicBuffer_v1>::type, - typename decay<ReadHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + decay_t<DynamicBuffer_v1>, + decay_t<ReadHandler>>( + stream_, static_cast<DynamicBuffer_v1&&>(buffers), delim, handler2.value)(asio::error_code(), 0, 1); } @@ -1061,8 +1011,16 @@ struct associator<Associator, { static typename Associator<ReadHandler, DefaultCandidate>::type get( const detail::read_until_delim_op_v1<AsyncReadStream, + DynamicBuffer_v1, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::read_until_delim_op_v1<AsyncReadStream, DynamicBuffer_v1, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -1072,23 +1030,25 @@ struct associator<Associator, template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - char delim, ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, + DynamicBuffer_v1&& buffers, char delim, ReadToken&& token, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_v1<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), delim)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_delim_v1<AsyncReadStream>(s), - handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim); + token, static_cast<DynamicBuffer_v1&&>(buffers), delim); } namespace detail @@ -1101,20 +1061,19 @@ namespace detail public: template <typename BufferSequence> read_until_delim_string_op_v1(AsyncReadStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, + BufferSequence&& buffers, const std::string& delim, ReadHandler& handler) : base_from_cancellation_state<ReadHandler>( handler, enable_partial_cancellation()), stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), delim_(delim), start_(0), search_position_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_until_delim_string_op_v1(const read_until_delim_string_op_v1& other) : base_from_cancellation_state<ReadHandler>(other), stream_(other.stream_), @@ -1128,17 +1087,15 @@ namespace detail read_until_delim_string_op_v1(read_until_delim_string_op_v1&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), - delim_(ASIO_MOVE_CAST(std::string)(other.delim_)), + buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)), + delim_(static_cast<std::string&&>(other.delim_)), start_(other.start_), search_position_(other.search_position_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -1209,7 +1166,7 @@ namespace detail ASIO_HANDLER_LOCATION(( __FILE__, __LINE__, "async_read_until")); stream_.async_read_some(buffers_.prepare(bytes_to_read), - ASIO_MOVE_CAST(read_until_delim_string_op_v1)(*this)); + static_cast<read_until_delim_string_op_v1&&>(*this)); } return; default: buffers_.commit(bytes_transferred); @@ -1230,7 +1187,7 @@ namespace detail (ec || search_position_ == not_found) ? 0 : search_position_; - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); + static_cast<ReadHandler&&>(handler_)(result_ec, result_n); } } @@ -1245,36 +1202,6 @@ namespace detail template <typename AsyncReadStream, typename DynamicBuffer_v1, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_until_delim_string_op_v1<AsyncReadStream, - DynamicBuffer_v1, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, - typename DynamicBuffer_v1, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_until_delim_string_op_v1<AsyncReadStream, - DynamicBuffer_v1, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, - typename DynamicBuffer_v1, typename ReadHandler> inline bool asio_handler_is_continuation( read_until_delim_string_op_v1<AsyncReadStream, DynamicBuffer_v1, ReadHandler>* this_handler) @@ -1284,34 +1211,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v1, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_until_delim_string_op_v1<AsyncReadStream, - DynamicBuffer_v1, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v1, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_until_delim_string_op_v1<AsyncReadStream, - DynamicBuffer_v1, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncReadStream> class initiate_async_read_until_delim_string_v1 { @@ -1323,14 +1222,14 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename ReadHandler, typename DynamicBuffer_v1> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + void operator()(ReadHandler&& handler, + DynamicBuffer_v1&& buffers, const std::string& delim) const { // If you get an error on the following line it means that your handler @@ -1339,9 +1238,9 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); read_until_delim_string_op_v1<AsyncReadStream, - typename decay<DynamicBuffer_v1>::type, - typename decay<ReadHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + decay_t<DynamicBuffer_v1>, + decay_t<ReadHandler>>( + stream_, static_cast<DynamicBuffer_v1&&>(buffers), delim, handler2.value)(asio::error_code(), 0, 1); } @@ -1362,9 +1261,17 @@ struct associator<Associator, : Associator<ReadHandler, DefaultCandidate> { static typename Associator<ReadHandler, DefaultCandidate>::type get( - const detail::read_until_delim_string_op_v1<AsyncReadStream, - DynamicBuffer_v1, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::read_until_delim_string_op_v1< + AsyncReadStream, DynamicBuffer_v1, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::read_until_delim_string_op_v1< + AsyncReadStream, DynamicBuffer_v1, ReadHandler>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -1374,24 +1281,27 @@ struct associator<Associator, template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - ASIO_STRING_VIEW_PARAM delim, - ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v1&& buffers, + ASIO_STRING_VIEW_PARAM delim, ReadToken&& token, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_string_v1< + AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), + static_cast<std::string>(delim))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_delim_string_v1<AsyncReadStream>(s), - handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + token, static_cast<DynamicBuffer_v1&&>(buffers), static_cast<std::string>(delim)); } @@ -1406,22 +1316,20 @@ namespace detail : public base_from_cancellation_state<ReadHandler> { public: - template <typename BufferSequence> - read_until_expr_op_v1(AsyncReadStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, - const boost::regex& expr, ReadHandler& handler) + template <typename BufferSequence, typename Traits> + read_until_expr_op_v1(AsyncReadStream& stream, BufferSequence&& buffers, + const boost::basic_regex<char, Traits>& expr, ReadHandler& handler) : base_from_cancellation_state<ReadHandler>( handler, enable_partial_cancellation()), stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), expr_(expr), start_(0), search_position_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_until_expr_op_v1(const read_until_expr_op_v1& other) : base_from_cancellation_state<ReadHandler>(other), stream_(other.stream_), @@ -1435,17 +1343,15 @@ namespace detail read_until_expr_op_v1(read_until_expr_op_v1&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), + buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)), expr_(other.expr_), start_(other.start_), search_position_(other.search_position_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -1469,10 +1375,10 @@ namespace detail // Look for a match. boost::match_results<iterator, - typename std::vector<boost::sub_match<iterator> >::allocator_type> + typename std::vector<boost::sub_match<iterator>>::allocator_type> match_results; - bool match = regex_search(start_pos, end, match_results, expr_, - boost::match_default | boost::match_partial); + bool match = regex_search(start_pos, end, + match_results, expr_, regex_match_flags()); if (match && match_results[0].matched) { // Full match. We're done. @@ -1519,7 +1425,7 @@ namespace detail ASIO_HANDLER_LOCATION(( __FILE__, __LINE__, "async_read_until")); stream_.async_read_some(buffers_.prepare(bytes_to_read), - ASIO_MOVE_CAST(read_until_expr_op_v1)(*this)); + static_cast<read_until_expr_op_v1&&>(*this)); } return; default: buffers_.commit(bytes_transferred); @@ -1540,7 +1446,7 @@ namespace detail (ec || search_position_ == not_found) ? 0 : search_position_; - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); + static_cast<ReadHandler&&>(handler_)(result_ec, result_n); } } @@ -1555,36 +1461,6 @@ namespace detail template <typename AsyncReadStream, typename DynamicBuffer_v1, typename RegEx, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_until_expr_op_v1<AsyncReadStream, - DynamicBuffer_v1, RegEx, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v1, - typename RegEx, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_until_expr_op_v1<AsyncReadStream, - DynamicBuffer_v1, RegEx, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v1, - typename RegEx, typename ReadHandler> inline bool asio_handler_is_continuation( read_until_expr_op_v1<AsyncReadStream, DynamicBuffer_v1, RegEx, ReadHandler>* this_handler) @@ -1594,34 +1470,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v1, typename RegEx, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_until_expr_op_v1<AsyncReadStream, - DynamicBuffer_v1, RegEx, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v1, typename RegEx, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_until_expr_op_v1<AsyncReadStream, - DynamicBuffer_v1, RegEx, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncReadStream> class initiate_async_read_until_expr_v1 { @@ -1633,14 +1481,14 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename ReadHandler, typename DynamicBuffer_v1, typename RegEx> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const RegEx& expr) const + void operator()(ReadHandler&& handler, + DynamicBuffer_v1&& buffers, const RegEx& expr) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a ReadHandler. @@ -1648,9 +1496,9 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); read_until_expr_op_v1<AsyncReadStream, - typename decay<DynamicBuffer_v1>::type, - RegEx, typename decay<ReadHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + decay_t<DynamicBuffer_v1>, + RegEx, decay_t<ReadHandler>>( + stream_, static_cast<DynamicBuffer_v1&&>(buffers), expr, handler2.value)(asio::error_code(), 0, 1); } @@ -1672,8 +1520,16 @@ struct associator<Associator, { static typename Associator<ReadHandler, DefaultCandidate>::type get( const detail::read_until_expr_op_v1<AsyncReadStream, + DynamicBuffer_v1, RegEx, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::read_until_expr_op_v1<AsyncReadStream, DynamicBuffer_v1, RegEx, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -1681,26 +1537,27 @@ struct associator<Associator, #endif // !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v1, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename Traits, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - const boost::regex& expr, - ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v1&& buffers, + const boost::basic_regex<char, Traits>& expr, ReadToken&& token, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_expr_v1<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), expr)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_expr_v1<AsyncReadStream>(s), - handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr); + token, static_cast<DynamicBuffer_v1&&>(buffers), expr); } #endif // defined(ASIO_HAS_BOOST_REGEX) @@ -1715,20 +1572,19 @@ namespace detail public: template <typename BufferSequence> read_until_match_op_v1(AsyncReadStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, + BufferSequence&& buffers, MatchCondition match_condition, ReadHandler& handler) : base_from_cancellation_state<ReadHandler>( handler, enable_partial_cancellation()), stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), match_condition_(match_condition), start_(0), search_position_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_until_match_op_v1(const read_until_match_op_v1& other) : base_from_cancellation_state<ReadHandler>(other), stream_(other.stream_), @@ -1742,17 +1598,15 @@ namespace detail read_until_match_op_v1(read_until_match_op_v1&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), + buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)), match_condition_(other.match_condition_), start_(other.start_), search_position_(other.search_position_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -1822,7 +1676,7 @@ namespace detail ASIO_HANDLER_LOCATION(( __FILE__, __LINE__, "async_read_until")); stream_.async_read_some(buffers_.prepare(bytes_to_read), - ASIO_MOVE_CAST(read_until_match_op_v1)(*this)); + static_cast<read_until_match_op_v1&&>(*this)); } return; default: buffers_.commit(bytes_transferred); @@ -1843,7 +1697,7 @@ namespace detail (ec || search_position_ == not_found) ? 0 : search_position_; - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); + static_cast<ReadHandler&&>(handler_)(result_ec, result_n); } } @@ -1858,36 +1712,6 @@ namespace detail template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, - MatchCondition, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v1, - typename MatchCondition, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, - MatchCondition, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v1, - typename MatchCondition, typename ReadHandler> inline bool asio_handler_is_continuation( read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, MatchCondition, ReadHandler>* this_handler) @@ -1897,36 +1721,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v1, typename MatchCondition, - typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, - MatchCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v1, typename MatchCondition, - typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, - MatchCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncReadStream> class initiate_async_read_until_match_v1 { @@ -1938,15 +1732,15 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename ReadHandler, typename DynamicBuffer_v1, typename MatchCondition> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + void operator()(ReadHandler&& handler, + DynamicBuffer_v1&& buffers, MatchCondition match_condition) const { // If you get an error on the following line it means that your handler @@ -1955,9 +1749,9 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); read_until_match_op_v1<AsyncReadStream, - typename decay<DynamicBuffer_v1>::type, - MatchCondition, typename decay<ReadHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + decay_t<DynamicBuffer_v1>, + MatchCondition, decay_t<ReadHandler>>( + stream_, static_cast<DynamicBuffer_v1&&>(buffers), match_condition, handler2.value)(asio::error_code(), 0, 1); } @@ -1979,8 +1773,16 @@ struct associator<Associator, { static typename Associator<ReadHandler, DefaultCandidate>::type get( const detail::read_until_match_op_v1<AsyncReadStream, + DynamicBuffer_v1, MatchCondition, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1, MatchCondition, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -1991,86 +1793,111 @@ struct associator<Associator, template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v1&& buffers, + MatchCondition match_condition, ReadToken&& token, + constraint_t< is_match_condition<MatchCondition>::value - >::type, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + >, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_match_v1<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), + match_condition)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - detail::initiate_async_read_until_match_v1<AsyncReadStream>(s), handler, - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), match_condition); + detail::initiate_async_read_until_match_v1<AsyncReadStream>(s), + token, static_cast<DynamicBuffer_v1&&>(buffers), + match_condition); } #if !defined(ASIO_NO_IOSTREAM) template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - asio::basic_streambuf<Allocator>& b, - char delim, ASIO_MOVE_ARG(ReadHandler) handler) + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, + asio::basic_streambuf<Allocator>& b, char delim, ReadToken&& token) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_v1<AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), delim)) { - return async_read_until(s, basic_streambuf_ref<Allocator>(b), - delim, ASIO_MOVE_CAST(ReadHandler)(handler)); + return async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_read_until_delim_v1<AsyncReadStream>(s), + token, basic_streambuf_ref<Allocator>(b), delim); } template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b, - ASIO_STRING_VIEW_PARAM delim, - ASIO_MOVE_ARG(ReadHandler) handler) + ASIO_STRING_VIEW_PARAM delim, ReadToken&& token) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_string_v1< + AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), + static_cast<std::string>(delim))) { - return async_read_until(s, basic_streambuf_ref<Allocator>(b), - delim, ASIO_MOVE_CAST(ReadHandler)(handler)); + return async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_read_until_delim_string_v1<AsyncReadStream>(s), + token, basic_streambuf_ref<Allocator>(b), + static_cast<std::string>(delim)); } #if defined(ASIO_HAS_BOOST_REGEX) -template <typename AsyncReadStream, typename Allocator, +template <typename AsyncReadStream, typename Allocator, typename Traits, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - asio::basic_streambuf<Allocator>& b, const boost::regex& expr, - ASIO_MOVE_ARG(ReadHandler) handler) + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, + asio::basic_streambuf<Allocator>& b, + const boost::basic_regex<char, Traits>& expr, ReadToken&& token) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_expr_v1<AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), expr)) { - return async_read_until(s, basic_streambuf_ref<Allocator>(b), - expr, ASIO_MOVE_CAST(ReadHandler)(handler)); + return async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_read_until_expr_v1<AsyncReadStream>(s), + token, basic_streambuf_ref<Allocator>(b), expr); } #endif // defined(ASIO_HAS_BOOST_REGEX) template <typename AsyncReadStream, typename Allocator, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b, - MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint<is_match_condition<MatchCondition>::value>::type) + MatchCondition match_condition, ReadToken&& token, + constraint_t<is_match_condition<MatchCondition>::value>) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_match_v1<AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), match_condition)) { - return async_read_until(s, basic_streambuf_ref<Allocator>(b), - match_condition, ASIO_MOVE_CAST(ReadHandler)(handler)); + return async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_read_until_match_v1<AsyncReadStream>(s), + token, basic_streambuf_ref<Allocator>(b), match_condition); } #endif // !defined(ASIO_NO_IOSTREAM) @@ -2087,21 +1914,20 @@ namespace detail public: template <typename BufferSequence> read_until_delim_op_v2(AsyncReadStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, + BufferSequence&& buffers, char delim, ReadHandler& handler) : base_from_cancellation_state<ReadHandler>( handler, enable_partial_cancellation()), stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), delim_(delim), start_(0), search_position_(0), bytes_to_read_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_until_delim_op_v2(const read_until_delim_op_v2& other) : base_from_cancellation_state<ReadHandler>(other), stream_(other.stream_), @@ -2116,18 +1942,16 @@ namespace detail read_until_delim_op_v2(read_until_delim_op_v2&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), + buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)), delim_(other.delim_), start_(other.start_), search_position_(other.search_position_), bytes_to_read_(other.bytes_to_read_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -2191,7 +2015,7 @@ namespace detail ASIO_HANDLER_LOCATION(( __FILE__, __LINE__, "async_read_until")); stream_.async_read_some(buffers_.data(pos, bytes_to_read_), - ASIO_MOVE_CAST(read_until_delim_op_v2)(*this)); + static_cast<read_until_delim_op_v2&&>(*this)); } return; default: buffers_.shrink(bytes_to_read_ - bytes_transferred); @@ -2212,7 +2036,7 @@ namespace detail (ec || search_position_ == not_found) ? 0 : search_position_; - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); + static_cast<ReadHandler&&>(handler_)(result_ec, result_n); } } @@ -2228,36 +2052,6 @@ namespace detail template <typename AsyncReadStream, typename DynamicBuffer_v2, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_until_delim_op_v2<AsyncReadStream, - DynamicBuffer_v2, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, - typename DynamicBuffer_v2, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_until_delim_op_v2<AsyncReadStream, - DynamicBuffer_v2, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, - typename DynamicBuffer_v2, typename ReadHandler> inline bool asio_handler_is_continuation( read_until_delim_op_v2<AsyncReadStream, DynamicBuffer_v2, ReadHandler>* this_handler) @@ -2267,34 +2061,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v2, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_until_delim_op_v2<AsyncReadStream, - DynamicBuffer_v2, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v2, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_until_delim_op_v2<AsyncReadStream, - DynamicBuffer_v2, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncReadStream> class initiate_async_read_until_delim_v2 { @@ -2306,14 +2072,14 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename ReadHandler, typename DynamicBuffer_v2> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, char delim) const + void operator()(ReadHandler&& handler, + DynamicBuffer_v2&& buffers, char delim) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a ReadHandler. @@ -2321,9 +2087,9 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); read_until_delim_op_v2<AsyncReadStream, - typename decay<DynamicBuffer_v2>::type, - typename decay<ReadHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + decay_t<DynamicBuffer_v2>, + decay_t<ReadHandler>>( + stream_, static_cast<DynamicBuffer_v2&&>(buffers), delim, handler2.value)(asio::error_code(), 0, 1); } @@ -2345,8 +2111,16 @@ struct associator<Associator, { static typename Associator<ReadHandler, DefaultCandidate>::type get( const detail::read_until_delim_op_v2<AsyncReadStream, + DynamicBuffer_v2, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::read_until_delim_op_v2<AsyncReadStream, DynamicBuffer_v2, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -2356,19 +2130,22 @@ struct associator<Associator, template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, - char delim, ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, + DynamicBuffer_v2 buffers, char delim, ReadToken&& token, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_v2<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), delim)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_delim_v2<AsyncReadStream>(s), - handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim); + token, static_cast<DynamicBuffer_v2&&>(buffers), delim); } namespace detail @@ -2381,21 +2158,20 @@ namespace detail public: template <typename BufferSequence> read_until_delim_string_op_v2(AsyncReadStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, + BufferSequence&& buffers, const std::string& delim, ReadHandler& handler) : base_from_cancellation_state<ReadHandler>( handler, enable_partial_cancellation()), stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), delim_(delim), start_(0), search_position_(0), bytes_to_read_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_until_delim_string_op_v2(const read_until_delim_string_op_v2& other) : base_from_cancellation_state<ReadHandler>(other), stream_(other.stream_), @@ -2410,18 +2186,16 @@ namespace detail read_until_delim_string_op_v2(read_until_delim_string_op_v2&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), - delim_(ASIO_MOVE_CAST(std::string)(other.delim_)), + buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)), + delim_(static_cast<std::string&&>(other.delim_)), start_(other.start_), search_position_(other.search_position_), bytes_to_read_(other.bytes_to_read_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -2496,7 +2270,7 @@ namespace detail ASIO_HANDLER_LOCATION(( __FILE__, __LINE__, "async_read_until")); stream_.async_read_some(buffers_.data(pos, bytes_to_read_), - ASIO_MOVE_CAST(read_until_delim_string_op_v2)(*this)); + static_cast<read_until_delim_string_op_v2&&>(*this)); } return; default: buffers_.shrink(bytes_to_read_ - bytes_transferred); @@ -2517,7 +2291,7 @@ namespace detail (ec || search_position_ == not_found) ? 0 : search_position_; - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); + static_cast<ReadHandler&&>(handler_)(result_ec, result_n); } } @@ -2533,36 +2307,6 @@ namespace detail template <typename AsyncReadStream, typename DynamicBuffer_v2, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_until_delim_string_op_v2<AsyncReadStream, - DynamicBuffer_v2, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, - typename DynamicBuffer_v2, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_until_delim_string_op_v2<AsyncReadStream, - DynamicBuffer_v2, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, - typename DynamicBuffer_v2, typename ReadHandler> inline bool asio_handler_is_continuation( read_until_delim_string_op_v2<AsyncReadStream, DynamicBuffer_v2, ReadHandler>* this_handler) @@ -2572,34 +2316,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v2, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_until_delim_string_op_v2<AsyncReadStream, - DynamicBuffer_v2, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v2, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_until_delim_string_op_v2<AsyncReadStream, - DynamicBuffer_v2, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncReadStream> class initiate_async_read_until_delim_string_v2 { @@ -2611,14 +2327,14 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename ReadHandler, typename DynamicBuffer_v2> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, + void operator()(ReadHandler&& handler, + DynamicBuffer_v2&& buffers, const std::string& delim) const { // If you get an error on the following line it means that your handler @@ -2627,9 +2343,9 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); read_until_delim_string_op_v2<AsyncReadStream, - typename decay<DynamicBuffer_v2>::type, - typename decay<ReadHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + decay_t<DynamicBuffer_v2>, + decay_t<ReadHandler>>( + stream_, static_cast<DynamicBuffer_v2&&>(buffers), delim, handler2.value)(asio::error_code(), 0, 1); } @@ -2650,9 +2366,17 @@ struct associator<Associator, : Associator<ReadHandler, DefaultCandidate> { static typename Associator<ReadHandler, DefaultCandidate>::type get( - const detail::read_until_delim_string_op_v2<AsyncReadStream, - DynamicBuffer_v2, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::read_until_delim_string_op_v2< + AsyncReadStream, DynamicBuffer_v2, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::read_until_delim_string_op_v2< + AsyncReadStream, DynamicBuffer_v2, ReadHandler>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -2663,20 +2387,24 @@ struct associator<Associator, template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim, - ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + ASIO_STRING_VIEW_PARAM delim, ReadToken&& token, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_string_v2< + AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), + static_cast<std::string>(delim))) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_delim_string_v2<AsyncReadStream>(s), - handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + token, static_cast<DynamicBuffer_v2&&>(buffers), static_cast<std::string>(delim)); } @@ -2691,23 +2419,21 @@ namespace detail : public base_from_cancellation_state<ReadHandler> { public: - template <typename BufferSequence> - read_until_expr_op_v2(AsyncReadStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, - const boost::regex& expr, ReadHandler& handler) + template <typename BufferSequence, typename Traits> + read_until_expr_op_v2(AsyncReadStream& stream, BufferSequence&& buffers, + const boost::basic_regex<char, Traits>& expr, ReadHandler& handler) : base_from_cancellation_state<ReadHandler>( handler, enable_partial_cancellation()), stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), expr_(expr), start_(0), search_position_(0), bytes_to_read_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_until_expr_op_v2(const read_until_expr_op_v2& other) : base_from_cancellation_state<ReadHandler>(other), stream_(other.stream_), @@ -2722,18 +2448,16 @@ namespace detail read_until_expr_op_v2(read_until_expr_op_v2&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), + buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)), expr_(other.expr_), start_(other.start_), search_position_(other.search_position_), bytes_to_read_(other.bytes_to_read_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -2759,10 +2483,10 @@ namespace detail // Look for a match. boost::match_results<iterator, - typename std::vector<boost::sub_match<iterator> >::allocator_type> + typename std::vector<boost::sub_match<iterator>>::allocator_type> match_results; - bool match = regex_search(start_pos, end, match_results, expr_, - boost::match_default | boost::match_partial); + bool match = regex_search(start_pos, end, + match_results, expr_, regex_match_flags()); if (match && match_results[0].matched) { // Full match. We're done. @@ -2811,7 +2535,7 @@ namespace detail ASIO_HANDLER_LOCATION(( __FILE__, __LINE__, "async_read_until")); stream_.async_read_some(buffers_.data(pos, bytes_to_read_), - ASIO_MOVE_CAST(read_until_expr_op_v2)(*this)); + static_cast<read_until_expr_op_v2&&>(*this)); } return; default: buffers_.shrink(bytes_to_read_ - bytes_transferred); @@ -2832,7 +2556,7 @@ namespace detail (ec || search_position_ == not_found) ? 0 : search_position_; - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); + static_cast<ReadHandler&&>(handler_)(result_ec, result_n); } } @@ -2848,36 +2572,6 @@ namespace detail template <typename AsyncReadStream, typename DynamicBuffer_v2, typename RegEx, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_until_expr_op_v2<AsyncReadStream, - DynamicBuffer_v2, RegEx, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v2, - typename RegEx, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_until_expr_op_v2<AsyncReadStream, - DynamicBuffer_v2, RegEx, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v2, - typename RegEx, typename ReadHandler> inline bool asio_handler_is_continuation( read_until_expr_op_v2<AsyncReadStream, DynamicBuffer_v2, RegEx, ReadHandler>* this_handler) @@ -2887,34 +2581,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v2, typename RegEx, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_until_expr_op_v2<AsyncReadStream, - DynamicBuffer_v2, RegEx, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v2, typename RegEx, typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_until_expr_op_v2<AsyncReadStream, - DynamicBuffer_v2, RegEx, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncReadStream> class initiate_async_read_until_expr_v2 { @@ -2926,14 +2592,14 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename ReadHandler, typename DynamicBuffer_v2, typename RegEx> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, + void operator()(ReadHandler&& handler, + DynamicBuffer_v2&& buffers, const RegEx& expr) const { // If you get an error on the following line it means that your handler @@ -2942,9 +2608,9 @@ namespace detail non_const_lvalue<ReadHandler> handler2(handler); read_until_expr_op_v2<AsyncReadStream, - typename decay<DynamicBuffer_v2>::type, - RegEx, typename decay<ReadHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + decay_t<DynamicBuffer_v2>, + RegEx, decay_t<ReadHandler>>( + stream_, static_cast<DynamicBuffer_v2&&>(buffers), expr, handler2.value)(asio::error_code(), 0, 1); } @@ -2966,8 +2632,16 @@ struct associator<Associator, { static typename Associator<ReadHandler, DefaultCandidate>::type get( const detail::read_until_expr_op_v2<AsyncReadStream, + DynamicBuffer_v2, RegEx, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::read_until_expr_op_v2<AsyncReadStream, DynamicBuffer_v2, RegEx, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -2975,21 +2649,24 @@ struct associator<Associator, #endif // !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v2, +template <typename AsyncReadStream, typename DynamicBuffer_v2, typename Traits, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, - const boost::regex& expr, ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + const boost::basic_regex<char, Traits>& expr, ReadToken&& token, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_expr_v2<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), expr)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( detail::initiate_async_read_until_expr_v2<AsyncReadStream>(s), - handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr); + token, static_cast<DynamicBuffer_v2&&>(buffers), expr); } #endif // defined(ASIO_HAS_BOOST_REGEX) @@ -3004,21 +2681,20 @@ namespace detail public: template <typename BufferSequence> read_until_match_op_v2(AsyncReadStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, + BufferSequence&& buffers, MatchCondition match_condition, ReadHandler& handler) : base_from_cancellation_state<ReadHandler>( handler, enable_partial_cancellation()), stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), match_condition_(match_condition), start_(0), search_position_(0), bytes_to_read_(0), - handler_(ASIO_MOVE_CAST(ReadHandler)(handler)) + handler_(static_cast<ReadHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) read_until_match_op_v2(const read_until_match_op_v2& other) : base_from_cancellation_state<ReadHandler>(other), stream_(other.stream_), @@ -3033,18 +2709,16 @@ namespace detail read_until_match_op_v2(read_until_match_op_v2&& other) : base_from_cancellation_state<ReadHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - ReadHandler>)(other)), + static_cast<base_from_cancellation_state<ReadHandler>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), + buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)), match_condition_(other.match_condition_), start_(other.start_), search_position_(other.search_position_), bytes_to_read_(other.bytes_to_read_), - handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_)) + handler_(static_cast<ReadHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -3118,7 +2792,7 @@ namespace detail ASIO_HANDLER_LOCATION(( __FILE__, __LINE__, "async_read_until")); stream_.async_read_some(buffers_.data(pos, bytes_to_read_), - ASIO_MOVE_CAST(read_until_match_op_v2)(*this)); + static_cast<read_until_match_op_v2&&>(*this)); } return; default: buffers_.shrink(bytes_to_read_ - bytes_transferred); @@ -3139,7 +2813,7 @@ namespace detail (ec || search_position_ == not_found) ? 0 : search_position_; - ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n); + static_cast<ReadHandler&&>(handler_)(result_ec, result_n); } } @@ -3155,36 +2829,6 @@ namespace detail template <typename AsyncReadStream, typename DynamicBuffer_v2, typename MatchCondition, typename ReadHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, - MatchCondition, ReadHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v2, - typename MatchCondition, typename ReadHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, - MatchCondition, ReadHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncReadStream, typename DynamicBuffer_v2, - typename MatchCondition, typename ReadHandler> inline bool asio_handler_is_continuation( read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, MatchCondition, ReadHandler>* this_handler) @@ -3194,36 +2838,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v2, typename MatchCondition, - typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, - MatchCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncReadStream, - typename DynamicBuffer_v2, typename MatchCondition, - typename ReadHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, - MatchCondition, ReadHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncReadStream> class initiate_async_read_until_match_v2 { @@ -3235,15 +2849,15 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename ReadHandler, typename DynamicBuffer_v2, typename MatchCondition> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, + void operator()(ReadHandler&& handler, + DynamicBuffer_v2&& buffers, MatchCondition match_condition) const { // If you get an error on the following line it means that your handler @@ -3251,11 +2865,10 @@ namespace detail ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check; non_const_lvalue<ReadHandler> handler2(handler); - read_until_match_op_v2<AsyncReadStream, - typename decay<DynamicBuffer_v2>::type, - MatchCondition, typename decay<ReadHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), - match_condition, handler2.value)(asio::error_code(), 0, 1); + read_until_match_op_v2<AsyncReadStream, decay_t<DynamicBuffer_v2>, + MatchCondition, decay_t<ReadHandler>>( + stream_, static_cast<DynamicBuffer_v2&&>(buffers), + match_condition, handler2.value)(asio::error_code(), 0, 1); } private: @@ -3276,8 +2889,16 @@ struct associator<Associator, { static typename Associator<ReadHandler, DefaultCandidate>::type get( const detail::read_until_match_op_v2<AsyncReadStream, + DynamicBuffer_v2, MatchCondition, ReadHandler>& h) noexcept + { + return Associator<ReadHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2, MatchCondition, ReadHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c); } @@ -3288,22 +2909,27 @@ struct associator<Associator, template <typename AsyncReadStream, typename DynamicBuffer_v2, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, - MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler, - typename constraint< + std::size_t)) ReadToken> +inline auto async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + MatchCondition match_condition, ReadToken&& token, + constraint_t< is_match_condition<MatchCondition>::value - >::type, - typename constraint< + >, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_match_v2<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), + match_condition)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - detail::initiate_async_read_until_match_v2<AsyncReadStream>(s), handler, - ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), match_condition); + detail::initiate_async_read_until_match_v2<AsyncReadStream>(s), + token, static_cast<DynamicBuffer_v2&&>(buffers), + match_condition); } #endif // !defined(ASIO_NO_EXTENSIONS) diff --git a/3rdparty/asio/include/asio/impl/redirect_error.hpp b/3rdparty/asio/include/asio/impl/redirect_error.hpp index 79162868959..e75aa0f706c 100644 --- a/3rdparty/asio/include/asio/impl/redirect_error.hpp +++ b/3rdparty/asio/include/asio/impl/redirect_error.hpp @@ -2,7 +2,7 @@ // impl/redirect_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,11 +18,8 @@ #include "asio/detail/config.hpp" #include "asio/associator.hpp" #include "asio/async_result.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" #include "asio/system_error.hpp" #include "asio/detail/push_options.hpp" @@ -40,121 +37,47 @@ public: template <typename CompletionToken> redirect_error_handler(redirect_error_t<CompletionToken> e) : ec_(e.ec_), - handler_(ASIO_MOVE_CAST(CompletionToken)(e.token_)) + handler_(static_cast<CompletionToken&&>(e.token_)) { } template <typename RedirectedHandler> redirect_error_handler(asio::error_code& ec, - ASIO_MOVE_ARG(RedirectedHandler) h) + RedirectedHandler&& h) : ec_(ec), - handler_(ASIO_MOVE_CAST(RedirectedHandler)(h)) + handler_(static_cast<RedirectedHandler&&>(h)) { } void operator()() { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)(); + static_cast<Handler&&>(handler_)(); } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Arg, typename... Args> - typename enable_if< - !is_same<typename decay<Arg>::type, asio::error_code>::value - >::type - operator()(ASIO_MOVE_ARG(Arg) arg, ASIO_MOVE_ARG(Args)... args) + enable_if_t< + !is_same<decay_t<Arg>, asio::error_code>::value + > + operator()(Arg&& arg, Args&&... args) { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( - ASIO_MOVE_CAST(Arg)(arg), - ASIO_MOVE_CAST(Args)(args)...); + static_cast<Handler&&>(handler_)( + static_cast<Arg&&>(arg), + static_cast<Args&&>(args)...); } template <typename... Args> - void operator()(const asio::error_code& ec, - ASIO_MOVE_ARG(Args)... args) - { - ec_ = ec; - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( - ASIO_MOVE_CAST(Args)(args)...); - } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Arg> - typename enable_if< - !is_same<typename decay<Arg>::type, asio::error_code>::value - >::type - operator()(ASIO_MOVE_ARG(Arg) arg) - { - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( - ASIO_MOVE_CAST(Arg)(arg)); - } - - void operator()(const asio::error_code& ec) + void operator()(const asio::error_code& ec, Args&&... args) { ec_ = ec; - ASIO_MOVE_OR_LVALUE(Handler)(handler_)(); + static_cast<Handler&&>(handler_)(static_cast<Args&&>(args)...); } -#define ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \ - template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \ - typename enable_if< \ - !is_same<typename decay<Arg>::type, asio::error_code>::value \ - >::type \ - operator()(ASIO_MOVE_ARG(Arg) arg, ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( \ - ASIO_MOVE_CAST(Arg)(arg), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - void operator()(const asio::error_code& ec, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - ec_ = ec; \ - ASIO_MOVE_OR_LVALUE(Handler)(handler_)( \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF) -#undef ASIO_PRIVATE_REDIRECT_ERROR_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - //private: asio::error_code& ec_; Handler handler_; }; template <typename Handler> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - redirect_error_handler<Handler>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - redirect_error_handler<Handler>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Handler> inline bool asio_handler_is_continuation( redirect_error_handler<Handler>* this_handler) { @@ -162,38 +85,12 @@ inline bool asio_handler_is_continuation( this_handler->handler_); } -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - redirect_error_handler<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - redirect_error_handler<Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - template <typename Signature> struct redirect_error_signature { typedef Signature type; }; -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename R, typename... Args> struct redirect_error_signature<R(asio::error_code, Args...)> { @@ -206,8 +103,6 @@ struct redirect_error_signature<R(const asio::error_code&, Args...)> typedef R type(Args...); }; -# if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - template <typename R, typename... Args> struct redirect_error_signature<R(asio::error_code, Args...) &> { @@ -232,7 +127,7 @@ struct redirect_error_signature<R(const asio::error_code&, Args...) &&> typedef R type(Args...) &&; }; -# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) +#if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) template <typename R, typename... Args> struct redirect_error_signature< @@ -276,196 +171,7 @@ struct redirect_error_signature< typedef R type(Args...) && noexcept; }; -# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) -# endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename R> -struct redirect_error_signature<R(asio::error_code)> -{ - typedef R type(); -}; - -template <typename R> -struct redirect_error_signature<R(const asio::error_code&)> -{ - typedef R type(); -}; - -#define ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(asio::error_code, ASIO_VARIADIC_TARGS(n))> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)); \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(const asio::error_code&, ASIO_VARIADIC_TARGS(n))> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)); \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF) -#undef ASIO_PRIVATE_REDIRECT_ERROR_DEF - -# if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) - -template <typename R> -struct redirect_error_signature<R(asio::error_code) &> -{ - typedef R type() &; -}; - -template <typename R> -struct redirect_error_signature<R(const asio::error_code&) &> -{ - typedef R type() &; -}; - -template <typename R> -struct redirect_error_signature<R(asio::error_code) &&> -{ - typedef R type() &&; -}; - -template <typename R> -struct redirect_error_signature<R(const asio::error_code&) &&> -{ - typedef R type() &&; -}; - -#define ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(asio::error_code, ASIO_VARIADIC_TARGS(n)) &> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)) &; \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(const asio::error_code&, ASIO_VARIADIC_TARGS(n)) &> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)) &; \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(asio::error_code, ASIO_VARIADIC_TARGS(n)) &&> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)) &&; \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(const asio::error_code&, ASIO_VARIADIC_TARGS(n)) &&> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)) &&; \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF) -#undef ASIO_PRIVATE_REDIRECT_ERROR_DEF - -# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) - -template <typename R> -struct redirect_error_signature< - R(asio::error_code) noexcept> -{ - typedef R type() noexcept; -}; - -template <typename R> -struct redirect_error_signature< - R(const asio::error_code&) noexcept> -{ - typedef R type() noexcept; -}; - -template <typename R> -struct redirect_error_signature< - R(asio::error_code) & noexcept> -{ - typedef R type() & noexcept; -}; - -template <typename R> -struct redirect_error_signature< - R(const asio::error_code&) & noexcept> -{ - typedef R type() & noexcept; -}; - -template <typename R> -struct redirect_error_signature< - R(asio::error_code) && noexcept> -{ - typedef R type() && noexcept; -}; - -template <typename R> -struct redirect_error_signature< - R(const asio::error_code&) && noexcept> -{ - typedef R type() && noexcept; -}; - -#define ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(asio::error_code, ASIO_VARIADIC_TARGS(n)) noexcept> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)) noexcept; \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(const asio::error_code&, \ - ASIO_VARIADIC_TARGS(n)) noexcept> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)) noexcept; \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(asio::error_code, \ - ASIO_VARIADIC_TARGS(n)) & noexcept> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)) & noexcept; \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(const asio::error_code&, \ - ASIO_VARIADIC_TARGS(n)) & noexcept> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)) & noexcept; \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(asio::error_code, \ - ASIO_VARIADIC_TARGS(n)) && noexcept> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)) && noexcept; \ - }; \ - \ - template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ - struct redirect_error_signature< \ - R(const asio::error_code&, \ - ASIO_VARIADIC_TARGS(n)) && noexcept> \ - { \ - typedef R type(ASIO_VARIADIC_TARGS(n)) && noexcept; \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF) -#undef ASIO_PRIVATE_REDIRECT_ERROR_DEF - -# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) -# endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) +#endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE) } // namespace detail @@ -473,117 +179,46 @@ struct redirect_error_signature< template <typename CompletionToken, typename Signature> struct async_result<redirect_error_t<CompletionToken>, Signature> + : async_result<CompletionToken, + typename detail::redirect_error_signature<Signature>::type> { - typedef typename async_result<CompletionToken, - typename detail::redirect_error_signature<Signature>::type> - ::return_type return_type; - template <typename Initiation> struct init_wrapper { - template <typename Init> - init_wrapper(asio::error_code& ec, ASIO_MOVE_ARG(Init) init) - : ec_(ec), - initiation_(ASIO_MOVE_CAST(Init)(init)) + explicit init_wrapper(asio::error_code& ec) + : ec_(ec) { } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Handler, typename... Args> - void operator()( - ASIO_MOVE_ARG(Handler) handler, - ASIO_MOVE_ARG(Args)... args) + template <typename Handler, typename Initiation, typename... Args> + void operator()(Handler&& handler, + Initiation&& initiation, Args&&... args) const { - ASIO_MOVE_CAST(Initiation)(initiation_)( - detail::redirect_error_handler< - typename decay<Handler>::type>( - ec_, ASIO_MOVE_CAST(Handler)(handler)), - ASIO_MOVE_CAST(Args)(args)...); + static_cast<Initiation&&>(initiation)( + detail::redirect_error_handler<decay_t<Handler>>( + ec_, static_cast<Handler&&>(handler)), + static_cast<Args&&>(args)...); } -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Handler> - void operator()( - ASIO_MOVE_ARG(Handler) handler) - { - ASIO_MOVE_CAST(Initiation)(initiation_)( - detail::redirect_error_handler< - typename decay<Handler>::type>( - ec_, ASIO_MOVE_CAST(Handler)(handler))); - } - -#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \ - template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \ - void operator()( \ - ASIO_MOVE_ARG(Handler) handler, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - ASIO_MOVE_CAST(Initiation)(initiation_)( \ - detail::redirect_error_handler< \ - typename decay<Handler>::type>( \ - ec_, ASIO_MOVE_CAST(Handler)(handler)), \ - ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF) -#undef ASIO_PRIVATE_INIT_WRAPPER_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - asio::error_code& ec_; - Initiation initiation_; }; -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename Initiation, typename RawCompletionToken, typename... Args> - static return_type initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token, - ASIO_MOVE_ARG(Args)... args) + static auto initiate(Initiation&& initiation, + RawCompletionToken&& token, Args&&... args) + -> decltype( + async_initiate<CompletionToken, + typename detail::redirect_error_signature<Signature>::type>( + declval<init_wrapper>(), token.token_, + static_cast<Initiation&&>(initiation), + static_cast<Args&&>(args)...)) { return async_initiate<CompletionToken, typename detail::redirect_error_signature<Signature>::type>( - init_wrapper<typename decay<Initiation>::type>( - token.ec_, ASIO_MOVE_CAST(Initiation)(initiation)), - token.token_, ASIO_MOVE_CAST(Args)(args)...); + init_wrapper(token.ec_), token.token_, + static_cast<Initiation&&>(initiation), + static_cast<Args&&>(args)...); } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - template <typename Initiation, typename RawCompletionToken> - static return_type initiate( - ASIO_MOVE_ARG(Initiation) initiation, - ASIO_MOVE_ARG(RawCompletionToken) token) - { - return async_initiate<CompletionToken, - typename detail::redirect_error_signature<Signature>::type>( - init_wrapper<typename decay<Initiation>::type>( - token.ec_, ASIO_MOVE_CAST(Initiation)(initiation)), - token.token_); - } - -#define ASIO_PRIVATE_INITIATE_DEF(n) \ - template <typename Initiation, typename RawCompletionToken, \ - ASIO_VARIADIC_TPARAMS(n)> \ - static return_type initiate( \ - ASIO_MOVE_ARG(Initiation) initiation, \ - ASIO_MOVE_ARG(RawCompletionToken) token, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - return async_initiate<CompletionToken, \ - typename detail::redirect_error_signature<Signature>::type>( \ - init_wrapper<typename decay<Initiation>::type>( \ - token.ec_, ASIO_MOVE_CAST(Initiation)(initiation)), \ - token.token_, ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF) -#undef ASIO_PRIVATE_INITIATE_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) }; template <template <typename, typename> class Associator, @@ -593,8 +228,14 @@ struct associator<Associator, : Associator<Handler, DefaultCandidate> { static typename Associator<Handler, DefaultCandidate>::type get( - const detail::redirect_error_handler<Handler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::redirect_error_handler<Handler>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const detail::redirect_error_handler<Handler>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } diff --git a/3rdparty/asio/include/asio/impl/serial_port_base.hpp b/3rdparty/asio/include/asio/impl/serial_port_base.hpp index 6ba9168d2ea..1fa2af66f73 100644 --- a/3rdparty/asio/include/asio/impl/serial_port_base.hpp +++ b/3rdparty/asio/include/asio/impl/serial_port_base.hpp @@ -2,7 +2,7 @@ // impl/serial_port_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/3rdparty/asio/include/asio/impl/serial_port_base.ipp b/3rdparty/asio/include/asio/impl/serial_port_base.ipp index ebb38870a34..646af3453d6 100644 --- a/3rdparty/asio/include/asio/impl/serial_port_base.ipp +++ b/3rdparty/asio/include/asio/impl/serial_port_base.ipp @@ -2,7 +2,7 @@ // impl/serial_port_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/3rdparty/asio/include/asio/impl/spawn.hpp b/3rdparty/asio/include/asio/impl/spawn.hpp index 7b510cebd42..38a96406ed4 100644 --- a/3rdparty/asio/include/asio/impl/spawn.hpp +++ b/3rdparty/asio/include/asio/impl/spawn.hpp @@ -2,7 +2,7 @@ // impl/spawn.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,499 +16,1382 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" +#include <tuple> #include "asio/associated_allocator.hpp" +#include "asio/associated_cancellation_slot.hpp" #include "asio/associated_executor.hpp" #include "asio/async_result.hpp" #include "asio/bind_executor.hpp" #include "asio/detail/atomic_count.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" +#include "asio/detail/bind_handler.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/noncopyable.hpp" #include "asio/detail/type_traits.hpp" +#include "asio/detail/utility.hpp" #include "asio/system_error.hpp" +#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER) +# include <boost/context/fiber.hpp> +#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER) + #include "asio/detail/push_options.hpp" namespace asio { namespace detail { - template <typename Handler, typename T> - class coro_handler +#if !defined(ASIO_NO_EXCEPTIONS) +inline void spawned_thread_rethrow(void* ex) +{ + if (*static_cast<exception_ptr*>(ex)) + rethrow_exception(*static_cast<exception_ptr*>(ex)); +} +#endif // !defined(ASIO_NO_EXCEPTIONS) + +#if defined(ASIO_HAS_BOOST_COROUTINE) + +// Spawned thread implementation using Boost.Coroutine. +class spawned_coroutine_thread : public spawned_thread_base +{ +public: +#if defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2) + typedef boost::coroutines::pull_coroutine<void> callee_type; + typedef boost::coroutines::push_coroutine<void> caller_type; +#else + typedef boost::coroutines::coroutine<void()> callee_type; + typedef boost::coroutines::coroutine<void()> caller_type; +#endif + + spawned_coroutine_thread(caller_type& caller) + : caller_(caller), + on_suspend_fn_(0), + on_suspend_arg_(0) + { + } + + template <typename F> + static spawned_thread_base* spawn(F&& f, + const boost::coroutines::attributes& attributes, + cancellation_slot parent_cancel_slot = cancellation_slot(), + cancellation_state cancel_state = cancellation_state()) { - public: - coro_handler(basic_yield_context<Handler> ctx) - : coro_(ctx.coro_.lock()), - ca_(ctx.ca_), - handler_(ctx.handler_), - ready_(0), - ec_(ctx.ec_), - value_(0) + spawned_coroutine_thread* spawned_thread = 0; + callee_type callee(entry_point<decay_t<F>>( + static_cast<F&&>(f), &spawned_thread), attributes); + spawned_thread->callee_.swap(callee); + spawned_thread->parent_cancellation_slot_ = parent_cancel_slot; + spawned_thread->cancellation_state_ = cancel_state; + return spawned_thread; + } + + template <typename F> + static spawned_thread_base* spawn(F&& f, + cancellation_slot parent_cancel_slot = cancellation_slot(), + cancellation_state cancel_state = cancellation_state()) + { + return spawn(static_cast<F&&>(f), boost::coroutines::attributes(), + parent_cancel_slot, cancel_state); + } + + void resume() + { + callee_(); + if (on_suspend_fn_) { + void (*fn)(void*) = on_suspend_fn_; + void* arg = on_suspend_arg_; + on_suspend_fn_ = 0; + fn(arg); } + } + + void suspend_with(void (*fn)(void*), void* arg) + { + if (throw_if_cancelled_) + if (!!cancellation_state_.cancelled()) + throw_error(asio::error::operation_aborted, "yield"); + has_context_switched_ = true; + on_suspend_fn_ = fn; + on_suspend_arg_ = arg; + caller_(); + } + + void destroy() + { + callee_type callee; + callee.swap(callee_); + if (terminal_) + callee(); + } - void operator()(T value) +private: + template <typename Function> + class entry_point + { + public: + template <typename F> + entry_point(F&& f, + spawned_coroutine_thread** spawned_thread_out) + : function_(static_cast<F&&>(f)), + spawned_thread_out_(spawned_thread_out) { - *ec_ = asio::error_code(); - *value_ = ASIO_MOVE_CAST(T)(value); - if (--*ready_ == 0) - (*coro_)(); } - void operator()(asio::error_code ec, T value) + void operator()(caller_type& caller) { - *ec_ = ec; - *value_ = ASIO_MOVE_CAST(T)(value); - if (--*ready_ == 0) - (*coro_)(); + Function function(static_cast<Function&&>(function_)); + spawned_coroutine_thread spawned_thread(caller); + *spawned_thread_out_ = &spawned_thread; + spawned_thread_out_ = 0; + spawned_thread.suspend(); +#if !defined(ASIO_NO_EXCEPTIONS) + try +#endif // !defined(ASIO_NO_EXCEPTIONS) + { + function(&spawned_thread); + spawned_thread.terminal_ = true; + spawned_thread.suspend(); + } +#if !defined(ASIO_NO_EXCEPTIONS) + catch (const boost::coroutines::detail::forced_unwind&) + { + throw; + } + catch (...) + { + exception_ptr ex = current_exception(); + spawned_thread.terminal_ = true; + spawned_thread.suspend_with(spawned_thread_rethrow, &ex); + } +#endif // !defined(ASIO_NO_EXCEPTIONS) } - //private: - shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_; - typename basic_yield_context<Handler>::caller_type& ca_; - Handler handler_; - atomic_count* ready_; - asio::error_code* ec_; - T* value_; + private: + Function function_; + spawned_coroutine_thread** spawned_thread_out_; }; - template <typename Handler> - class coro_handler<Handler, void> + caller_type& caller_; + callee_type callee_; + void (*on_suspend_fn_)(void*); + void* on_suspend_arg_; +}; + +#endif // defined(ASIO_HAS_BOOST_COROUTINE) + +#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER) + +// Spawned thread implementation using Boost.Context's fiber. +class spawned_fiber_thread : public spawned_thread_base +{ +public: + typedef boost::context::fiber fiber_type; + + spawned_fiber_thread(fiber_type&& caller) + : caller_(static_cast<fiber_type&&>(caller)), + on_suspend_fn_(0), + on_suspend_arg_(0) { - public: - coro_handler(basic_yield_context<Handler> ctx) - : coro_(ctx.coro_.lock()), - ca_(ctx.ca_), - handler_(ctx.handler_), - ready_(0), - ec_(ctx.ec_) + } + + template <typename StackAllocator, typename F> + static spawned_thread_base* spawn(allocator_arg_t, + StackAllocator&& stack_allocator, + F&& f, + cancellation_slot parent_cancel_slot = cancellation_slot(), + cancellation_state cancel_state = cancellation_state()) + { + spawned_fiber_thread* spawned_thread = 0; + fiber_type callee(allocator_arg_t(), + static_cast<StackAllocator&&>(stack_allocator), + entry_point<decay_t<F>>( + static_cast<F&&>(f), &spawned_thread)); + callee = fiber_type(static_cast<fiber_type&&>(callee)).resume(); + spawned_thread->callee_ = static_cast<fiber_type&&>(callee); + spawned_thread->parent_cancellation_slot_ = parent_cancel_slot; + spawned_thread->cancellation_state_ = cancel_state; + return spawned_thread; + } + + template <typename F> + static spawned_thread_base* spawn(F&& f, + cancellation_slot parent_cancel_slot = cancellation_slot(), + cancellation_state cancel_state = cancellation_state()) + { + return spawn(allocator_arg_t(), boost::context::fixedsize_stack(), + static_cast<F&&>(f), parent_cancel_slot, cancel_state); + } + + void resume() + { + callee_ = fiber_type(static_cast<fiber_type&&>(callee_)).resume(); + if (on_suspend_fn_) { + void (*fn)(void*) = on_suspend_fn_; + void* arg = on_suspend_arg_; + on_suspend_fn_ = 0; + fn(arg); } + } - void operator()() + void suspend_with(void (*fn)(void*), void* arg) + { + if (throw_if_cancelled_) + if (!!cancellation_state_.cancelled()) + throw_error(asio::error::operation_aborted, "yield"); + has_context_switched_ = true; + on_suspend_fn_ = fn; + on_suspend_arg_ = arg; + caller_ = fiber_type(static_cast<fiber_type&&>(caller_)).resume(); + } + + void destroy() + { + fiber_type callee = static_cast<fiber_type&&>(callee_); + if (terminal_) + fiber_type(static_cast<fiber_type&&>(callee)).resume(); + } + +private: + template <typename Function> + class entry_point + { + public: + template <typename F> + entry_point(F&& f, + spawned_fiber_thread** spawned_thread_out) + : function_(static_cast<F&&>(f)), + spawned_thread_out_(spawned_thread_out) { - *ec_ = asio::error_code(); - if (--*ready_ == 0) - (*coro_)(); } - void operator()(asio::error_code ec) + fiber_type operator()(fiber_type&& caller) { - *ec_ = ec; - if (--*ready_ == 0) - (*coro_)(); + Function function(static_cast<Function&&>(function_)); + spawned_fiber_thread spawned_thread( + static_cast<fiber_type&&>(caller)); + *spawned_thread_out_ = &spawned_thread; + spawned_thread_out_ = 0; + spawned_thread.suspend(); +#if !defined(ASIO_NO_EXCEPTIONS) + try +#endif // !defined(ASIO_NO_EXCEPTIONS) + { + function(&spawned_thread); + spawned_thread.terminal_ = true; + spawned_thread.suspend(); + } +#if !defined(ASIO_NO_EXCEPTIONS) + catch (const boost::context::detail::forced_unwind&) + { + throw; + } + catch (...) + { + exception_ptr ex = current_exception(); + spawned_thread.terminal_ = true; + spawned_thread.suspend_with(spawned_thread_rethrow, &ex); + } +#endif // !defined(ASIO_NO_EXCEPTIONS) + return static_cast<fiber_type&&>(spawned_thread.caller_); } - //private: - shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_; - typename basic_yield_context<Handler>::caller_type& ca_; - Handler handler_; - atomic_count* ready_; - asio::error_code* ec_; + private: + Function function_; + spawned_fiber_thread** spawned_thread_out_; }; - template <typename Handler, typename T> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - coro_handler<Handler, T>* this_handler) + fiber_type caller_; + fiber_type callee_; + void (*on_suspend_fn_)(void*); + void* on_suspend_arg_; +}; + +#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER) + +#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER) +typedef spawned_fiber_thread default_spawned_thread_type; +#elif defined(ASIO_HAS_BOOST_COROUTINE) +typedef spawned_coroutine_thread default_spawned_thread_type; +#else +# error No spawn() implementation available +#endif + +// Helper class to perform the initial resume on the correct executor. +class spawned_thread_resumer +{ +public: + explicit spawned_thread_resumer(spawned_thread_base* spawned_thread) + : spawned_thread_(spawned_thread) { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) } - template <typename Handler, typename T> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - coro_handler<Handler, T>* this_handler) + spawned_thread_resumer(spawned_thread_resumer&& other) noexcept + : spawned_thread_(other.spawned_thread_) { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) + other.spawned_thread_ = 0; } - template <typename Handler, typename T> - inline bool asio_handler_is_continuation(coro_handler<Handler, T>*) + ~spawned_thread_resumer() { - return true; + if (spawned_thread_) + spawned_thread_->destroy(); } - template <typename Function, typename Handler, typename T> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - coro_handler<Handler, T>* this_handler) + void operator()() + { + spawned_thread_->attach(&spawned_thread_); + spawned_thread_->resume(); + } + +private: + spawned_thread_base* spawned_thread_; +}; + +// Helper class to ensure spawned threads are destroyed on the correct executor. +class spawned_thread_destroyer +{ +public: + explicit spawned_thread_destroyer(spawned_thread_base* spawned_thread) + : spawned_thread_(spawned_thread) { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) + spawned_thread->detach(); } - template <typename Function, typename Handler, typename T> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - coro_handler<Handler, T>* this_handler) + spawned_thread_destroyer(spawned_thread_destroyer&& other) noexcept + : spawned_thread_(other.spawned_thread_) { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) + other.spawned_thread_ = 0; } - template <typename Handler, typename T> - class coro_async_result + ~spawned_thread_destroyer() { - public: - typedef coro_handler<Handler, T> completion_handler_type; - typedef T return_type; + if (spawned_thread_) + spawned_thread_->destroy(); + } - explicit coro_async_result(completion_handler_type& h) - : handler_(h), - ca_(h.ca_), - ready_(2) + void operator()() + { + if (spawned_thread_) { - h.ready_ = &ready_; - out_ec_ = h.ec_; - if (!out_ec_) h.ec_ = &ec_; - h.value_ = &value_; + spawned_thread_->destroy(); + spawned_thread_ = 0; } + } - return_type get() - { - // Must not hold shared_ptr to coro while suspended. - handler_.coro_.reset(); +private: + spawned_thread_base* spawned_thread_; +}; - if (--ready_ != 0) - ca_(); - if (!out_ec_ && ec_) throw asio::system_error(ec_); - return ASIO_MOVE_CAST(return_type)(value_); - } +// Base class for all completion handlers associated with a spawned thread. +template <typename Executor> +class spawn_handler_base +{ +public: + typedef Executor executor_type; + typedef cancellation_slot cancellation_slot_type; - private: - completion_handler_type& handler_; - typename basic_yield_context<Handler>::caller_type& ca_; - atomic_count ready_; - asio::error_code* out_ec_; - asio::error_code ec_; - return_type value_; - }; + spawn_handler_base(const basic_yield_context<Executor>& yield) + : yield_(yield), + spawned_thread_(yield.spawned_thread_) + { + spawned_thread_->detach(); + } + + spawn_handler_base(spawn_handler_base&& other) noexcept + : yield_(other.yield_), + spawned_thread_(other.spawned_thread_) - template <typename Handler> - class coro_async_result<Handler, void> { - public: - typedef coro_handler<Handler, void> completion_handler_type; - typedef void return_type; + other.spawned_thread_ = 0; + } - 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_; - } + ~spawn_handler_base() + { + if (spawned_thread_) + (post)(yield_.executor_, spawned_thread_destroyer(spawned_thread_)); + } - void get() - { - // Must not hold shared_ptr to coro while suspended. - handler_.coro_.reset(); + executor_type get_executor() const noexcept + { + return yield_.executor_; + } - if (--ready_ != 0) - ca_(); - if (!out_ec_ && ec_) throw asio::system_error(ec_); - } + cancellation_slot_type get_cancellation_slot() const noexcept + { + return spawned_thread_->get_cancellation_slot(); + } - private: - completion_handler_type& handler_; - typename basic_yield_context<Handler>::caller_type& ca_; - atomic_count ready_; - asio::error_code* out_ec_; - asio::error_code ec_; - }; + void resume() + { + spawned_thread_resumer resumer(spawned_thread_); + spawned_thread_ = 0; + resumer(); + } -} // namespace detail +protected: + const basic_yield_context<Executor>& yield_; + spawned_thread_base* spawned_thread_; +}; -#if !defined(GENERATING_DOCUMENTATION) +// Completion handlers for when basic_yield_context is used as a token. +template <typename Executor, typename Signature> +class spawn_handler; -template <typename Handler, typename ReturnType> -class async_result<basic_yield_context<Handler>, ReturnType()> - : public detail::coro_async_result<Handler, void> +template <typename Executor, typename R> +class spawn_handler<Executor, R()> + : public spawn_handler_base<Executor> { public: - explicit async_result( - typename detail::coro_async_result<Handler, - void>::completion_handler_type& h) - : detail::coro_async_result<Handler, void>(h) + typedef void return_type; + + struct result_type {}; + + spawn_handler(const basic_yield_context<Executor>& yield, result_type&) + : spawn_handler_base<Executor>(yield) + { + } + + void operator()() + { + this->resume(); + } + + static return_type on_resume(result_type&) { } }; -template <typename Handler, typename ReturnType, typename Arg1> -class async_result<basic_yield_context<Handler>, ReturnType(Arg1)> - : public detail::coro_async_result<Handler, typename decay<Arg1>::type> +template <typename Executor, typename R> +class spawn_handler<Executor, R(asio::error_code)> + : public spawn_handler_base<Executor> { public: - explicit async_result( - typename detail::coro_async_result<Handler, - typename decay<Arg1>::type>::completion_handler_type& h) - : detail::coro_async_result<Handler, typename decay<Arg1>::type>(h) + typedef void return_type; + typedef asio::error_code* result_type; + + spawn_handler(const basic_yield_context<Executor>& yield, result_type& result) + : spawn_handler_base<Executor>(yield), + result_(result) + { + } + + void operator()(asio::error_code ec) + { + if (this->yield_.ec_) + { + *this->yield_.ec_ = ec; + result_ = 0; + } + else + result_ = &ec; + this->resume(); + } + + static return_type on_resume(result_type& result) { + if (result) + throw_error(*result); } + +private: + result_type& result_; }; -template <typename Handler, typename ReturnType> -class async_result<basic_yield_context<Handler>, - ReturnType(asio::error_code)> - : public detail::coro_async_result<Handler, void> +template <typename Executor, typename R> +class spawn_handler<Executor, R(exception_ptr)> + : public spawn_handler_base<Executor> { public: - explicit async_result( - typename detail::coro_async_result<Handler, - void>::completion_handler_type& h) - : detail::coro_async_result<Handler, void>(h) + typedef void return_type; + typedef exception_ptr* result_type; + + spawn_handler(const basic_yield_context<Executor>& yield, result_type& result) + : spawn_handler_base<Executor>(yield), + result_(result) + { + } + + void operator()(exception_ptr ex) { + result_ = &ex; + this->resume(); } + + static return_type on_resume(result_type& result) + { + if (*result) + rethrow_exception(*result); + } + +private: + result_type& result_; }; -template <typename Handler, typename ReturnType, typename Arg2> -class async_result<basic_yield_context<Handler>, - ReturnType(asio::error_code, Arg2)> - : public detail::coro_async_result<Handler, typename decay<Arg2>::type> +template <typename Executor, typename R, typename T> +class spawn_handler<Executor, R(T)> + : public spawn_handler_base<Executor> { public: - explicit async_result( - typename detail::coro_async_result<Handler, - typename decay<Arg2>::type>::completion_handler_type& h) - : detail::coro_async_result<Handler, typename decay<Arg2>::type>(h) + typedef T return_type; + typedef return_type* result_type; + + spawn_handler(const basic_yield_context<Executor>& yield, result_type& result) + : spawn_handler_base<Executor>(yield), + result_(result) { } -}; -template <template <typename, typename> class Associator, - typename Handler, typename T, typename DefaultCandidate> -struct associator<Associator, - detail::coro_handler<Handler, T>, - DefaultCandidate> - : Associator<Handler, DefaultCandidate> -{ - static typename Associator<Handler, DefaultCandidate>::type get( - const detail::coro_handler<Handler, T>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + void operator()(T value) { - return Associator<Handler, DefaultCandidate>::get(h.handler_, c); + result_ = &value; + this->resume(); } + + static return_type on_resume(result_type& result) + { + return static_cast<return_type&&>(*result); + } + +private: + result_type& result_; }; -namespace detail { +template <typename Executor, typename R, typename T> +class spawn_handler<Executor, R(asio::error_code, T)> + : public spawn_handler_base<Executor> +{ +public: + typedef T return_type; + + struct result_type + { + asio::error_code* ec_; + return_type* value_; + }; - template <typename Handler, typename Function> - struct spawn_data : private noncopyable + spawn_handler(const basic_yield_context<Executor>& yield, result_type& result) + : spawn_handler_base<Executor>(yield), + result_(result) { - template <typename Hand, typename Func> - spawn_data(ASIO_MOVE_ARG(Hand) handler, - bool call_handler, ASIO_MOVE_ARG(Func) function) - : handler_(ASIO_MOVE_CAST(Hand)(handler)), - call_handler_(call_handler), - function_(ASIO_MOVE_CAST(Func)(function)) + } + + void operator()(asio::error_code ec, T value) + { + if (this->yield_.ec_) { + *this->yield_.ec_ = ec; + result_.ec_ = 0; } + else + result_.ec_ = &ec; + result_.value_ = &value; + this->resume(); + } - weak_ptr<typename basic_yield_context<Handler>::callee_type> coro_; - Handler handler_; - bool call_handler_; - Function function_; + static return_type on_resume(result_type& result) + { + if (result.ec_) + throw_error(*result.ec_); + return static_cast<return_type&&>(*result.value_); + } + +private: + result_type& result_; +}; + +template <typename Executor, typename R, typename T> +class spawn_handler<Executor, R(exception_ptr, T)> + : public spawn_handler_base<Executor> +{ +public: + typedef T return_type; + + struct result_type + { + exception_ptr* ex_; + return_type* value_; }; - template <typename Handler, typename Function> - struct coro_entry_point + spawn_handler(const basic_yield_context<Executor>& yield, result_type& result) + : spawn_handler_base<Executor>(yield), + result_(result) + { + } + + void operator()(exception_ptr ex, T value) { - void operator()(typename basic_yield_context<Handler>::caller_type& ca) + result_.ex_ = &ex; + result_.value_ = &value; + this->resume(); + } + + static return_type on_resume(result_type& result) + { + if (*result.ex_) + rethrow_exception(*result.ex_); + return static_cast<return_type&&>(*result.value_); + } + +private: + result_type& result_; +}; + +template <typename Executor, typename R, typename... Ts> +class spawn_handler<Executor, R(Ts...)> + : public spawn_handler_base<Executor> +{ +public: + typedef std::tuple<Ts...> return_type; + + typedef return_type* result_type; + + spawn_handler(const basic_yield_context<Executor>& yield, result_type& result) + : spawn_handler_base<Executor>(yield), + result_(result) + { + } + + template <typename... Args> + void operator()(Args&&... args) + { + return_type value(static_cast<Args&&>(args)...); + result_ = &value; + this->resume(); + } + + static return_type on_resume(result_type& result) + { + return static_cast<return_type&&>(*result); + } + +private: + result_type& result_; +}; + +template <typename Executor, typename R, typename... Ts> +class spawn_handler<Executor, R(asio::error_code, Ts...)> + : public spawn_handler_base<Executor> +{ +public: + typedef std::tuple<Ts...> return_type; + + struct result_type + { + asio::error_code* ec_; + return_type* value_; + }; + + spawn_handler(const basic_yield_context<Executor>& yield, result_type& result) + : spawn_handler_base<Executor>(yield), + result_(result) + { + } + + template <typename... Args> + void operator()(asio::error_code ec, + Args&&... args) + { + return_type value(static_cast<Args&&>(args)...); + if (this->yield_.ec_) { - shared_ptr<spawn_data<Handler, Function> > data(data_); -#if !defined(BOOST_COROUTINES_UNIDIRECT) && !defined(BOOST_COROUTINES_V2) - ca(); // Yield until coroutine pointer has been initialised. -#endif // !defined(BOOST_COROUTINES_UNIDIRECT) && !defined(BOOST_COROUTINES_V2) - const basic_yield_context<Handler> yield( - data->coro_, ca, data->handler_); - - (data->function_)(yield); - if (data->call_handler_) - ASIO_MOVE_OR_LVALUE(Handler)(data->handler_)(); + *this->yield_.ec_ = ec; + result_.ec_ = 0; } + else + result_.ec_ = &ec; + result_.value_ = &value; + this->resume(); + } - shared_ptr<spawn_data<Handler, Function> > data_; + static return_type on_resume(result_type& result) + { + if (result.ec_) + throw_error(*result.ec_); + return static_cast<return_type&&>(*result.value_); + } + +private: + result_type& result_; +}; + +template <typename Executor, typename R, typename... Ts> +class spawn_handler<Executor, R(exception_ptr, Ts...)> + : public spawn_handler_base<Executor> +{ +public: + typedef std::tuple<Ts...> return_type; + + struct result_type + { + exception_ptr* ex_; + return_type* value_; }; - template <typename Handler, typename Function> - struct spawn_helper + spawn_handler(const basic_yield_context<Executor>& yield, result_type& result) + : spawn_handler_base<Executor>(yield), + result_(result) + { + } + + template <typename... Args> + void operator()(exception_ptr ex, Args&&... args) + { + return_type value(static_cast<Args&&>(args)...); + result_.ex_ = &ex; + result_.value_ = &value; + this->resume(); + } + + static return_type on_resume(result_type& result) { - typedef typename associated_allocator<Handler>::type allocator_type; + if (*result.ex_) + rethrow_exception(*result.ex_); + return static_cast<return_type&&>(*result.value_); + } + +private: + result_type& result_; +}; + +template <typename Executor, typename Signature> +inline bool asio_handler_is_continuation(spawn_handler<Executor, Signature>*) +{ + return true; +} + +} // namespace detail - allocator_type get_allocator() const ASIO_NOEXCEPT +template <typename Executor, typename Signature> +class async_result<basic_yield_context<Executor>, Signature> +{ +public: + typedef typename detail::spawn_handler<Executor, Signature> handler_type; + typedef typename handler_type::return_type return_type; + +#if defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES) + + template <typename Initiation, typename... InitArgs> + static return_type initiate(Initiation&& init, + const basic_yield_context<Executor>& yield, + InitArgs&&... init_args) + { + typename handler_type::result_type result + = typename handler_type::result_type(); + + yield.spawned_thread_->suspend_with( + [&]() + { + static_cast<Initiation&&>(init)( + handler_type(yield, result), + static_cast<InitArgs&&>(init_args)...); + }); + + return handler_type::on_resume(result); + } + +#else // defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES) + + template <typename Initiation, typename... InitArgs> + struct suspend_with_helper + { + typename handler_type::result_type& result_; + Initiation&& init_; + const basic_yield_context<Executor>& yield_; + std::tuple<InitArgs&&...> init_args_; + + template <std::size_t... I> + void do_invoke(detail::index_sequence<I...>) { - return (get_associated_allocator)(data_->handler_); + static_cast<Initiation&&>(init_)( + handler_type(yield_, result_), + static_cast<InitArgs&&>(std::get<I>(init_args_))...); } - typedef typename associated_executor<Handler>::type executor_type; + void operator()() + { + this->do_invoke(detail::make_index_sequence<sizeof...(InitArgs)>()); + } + }; + + template <typename Initiation, typename... InitArgs> + static return_type initiate(Initiation&& init, + const basic_yield_context<Executor>& yield, + InitArgs&&... init_args) + { + typename handler_type::result_type result + = typename handler_type::result_type(); + + yield.spawned_thread_->suspend_with( + suspend_with_helper<Initiation, InitArgs...>{ + result, static_cast<Initiation&&>(init), yield, + std::tuple<InitArgs&&...>( + static_cast<InitArgs&&>(init_args)...)}); + + return handler_type::on_resume(result); + } + +#endif // defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES) +}; + +namespace detail { - executor_type get_executor() const ASIO_NOEXCEPT +template <typename Executor, typename Function, typename Handler> +class spawn_entry_point +{ +public: + template <typename F, typename H> + spawn_entry_point(const Executor& ex, + F&& f, H&& h) + : executor_(ex), + function_(static_cast<F&&>(f)), + handler_(static_cast<H&&>(h)), + work_(handler_, executor_) + { + } + + void operator()(spawned_thread_base* spawned_thread) + { + const basic_yield_context<Executor> yield(spawned_thread, executor_); + this->call(yield, + void_type<result_of_t<Function(basic_yield_context<Executor>)>>()); + } + +private: + void call(const basic_yield_context<Executor>& yield, void_type<void>) + { +#if !defined(ASIO_NO_EXCEPTIONS) + try +#endif // !defined(ASIO_NO_EXCEPTIONS) + { + function_(yield); + if (!yield.spawned_thread_->has_context_switched()) + (post)(yield); + detail::binder1<Handler, exception_ptr> + handler(handler_, exception_ptr()); + work_.complete(handler, handler.handler_); + } +#if !defined(ASIO_NO_EXCEPTIONS) +# if defined(ASIO_HAS_BOOST_CONTEXT_FIBER) + catch (const boost::context::detail::forced_unwind&) { - return (get_associated_executor)(data_->handler_); + throw; } +# endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER) +# if defined(ASIO_HAS_BOOST_COROUTINE) + catch (const boost::coroutines::detail::forced_unwind&) + { + throw; + } +# endif // defined(ASIO_HAS_BOOST_COROUTINE) + catch (...) + { + exception_ptr ex = current_exception(); + if (!yield.spawned_thread_->has_context_switched()) + (post)(yield); + detail::binder1<Handler, exception_ptr> handler(handler_, ex); + work_.complete(handler, handler.handler_); + } +#endif // !defined(ASIO_NO_EXCEPTIONS) + } - void operator()() + template <typename T> + void call(const basic_yield_context<Executor>& yield, void_type<T>) + { +#if !defined(ASIO_NO_EXCEPTIONS) + try +#endif // !defined(ASIO_NO_EXCEPTIONS) + { + T result(function_(yield)); + if (!yield.spawned_thread_->has_context_switched()) + (post)(yield); + detail::binder2<Handler, exception_ptr, T> + handler(handler_, exception_ptr(), static_cast<T&&>(result)); + work_.complete(handler, handler.handler_); + } +#if !defined(ASIO_NO_EXCEPTIONS) +# if defined(ASIO_HAS_BOOST_CONTEXT_FIBER) + catch (const boost::context::detail::forced_unwind&) + { + throw; + } +# endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER) +# if defined(ASIO_HAS_BOOST_COROUTINE) + catch (const boost::coroutines::detail::forced_unwind&) { - typedef typename basic_yield_context<Handler>::callee_type callee_type; - coro_entry_point<Handler, Function> entry_point = { data_ }; - shared_ptr<callee_type> coro(new callee_type(entry_point, attributes_)); - data_->coro_ = coro; - (*coro)(); + throw; } +# endif // defined(ASIO_HAS_BOOST_COROUTINE) + catch (...) + { + exception_ptr ex = current_exception(); + if (!yield.spawned_thread_->has_context_switched()) + (post)(yield); + detail::binder2<Handler, exception_ptr, T> handler(handler_, ex, T()); + work_.complete(handler, handler.handler_); + } +#endif // !defined(ASIO_NO_EXCEPTIONS) + } - shared_ptr<spawn_data<Handler, Function> > data_; - boost::coroutines::attributes attributes_; - }; + Executor executor_; + Function function_; + Handler handler_; + handler_work<Handler, Executor> work_; +}; + +struct spawn_cancellation_signal_emitter +{ + cancellation_signal* signal_; + cancellation_type_t type_; + + void operator()() + { + signal_->emit(type_); + } +}; - template <typename Function, typename Handler, typename Function1> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - spawn_helper<Handler, Function1>* this_handler) +template <typename Handler, typename Executor, typename = void> +class spawn_cancellation_handler +{ +public: + spawn_cancellation_handler(const Handler&, const Executor& ex) + : ex_(ex) + { + } + + cancellation_slot slot() + { + return signal_.slot(); + } + + void operator()(cancellation_type_t type) + { + spawn_cancellation_signal_emitter emitter = { &signal_, type }; + (dispatch)(ex_, emitter); + } + +private: + cancellation_signal signal_; + Executor ex_; +}; + + +template <typename Handler, typename Executor> +class spawn_cancellation_handler<Handler, Executor, + enable_if_t< + is_same< + typename associated_executor<Handler, + Executor>::asio_associated_executor_is_unspecialised, + void + >::value + >> +{ +public: + spawn_cancellation_handler(const Handler&, const Executor&) + { + } + + cancellation_slot slot() + { + return signal_.slot(); + } + + void operator()(cancellation_type_t type) + { + signal_.emit(type); + } + +private: + cancellation_signal signal_; +}; + +template <typename Executor> +class initiate_spawn +{ +public: + typedef Executor executor_type; + + explicit initiate_spawn(const executor_type& ex) + : executor_(ex) + { + } + + executor_type get_executor() const noexcept { - asio_handler_invoke_helpers::invoke( - function, this_handler->data_->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) + return executor_; } - template <typename Function, typename Handler, typename Function1> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - spawn_helper<Handler, Function1>* this_handler) + template <typename Handler, typename F> + void operator()(Handler&& handler, + F&& f) const { - asio_handler_invoke_helpers::invoke( - function, this_handler->data_->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) + typedef decay_t<Handler> handler_type; + typedef decay_t<F> function_type; + typedef spawn_cancellation_handler< + handler_type, Executor> cancel_handler_type; + + associated_cancellation_slot_t<handler_type> slot + = asio::get_associated_cancellation_slot(handler); + + cancel_handler_type* cancel_handler = slot.is_connected() + ? &slot.template emplace<cancel_handler_type>(handler, executor_) + : 0; + + cancellation_slot proxy_slot( + cancel_handler + ? cancel_handler->slot() + : cancellation_slot()); + + cancellation_state cancel_state(proxy_slot); + + (dispatch)(executor_, + spawned_thread_resumer( + default_spawned_thread_type::spawn( + spawn_entry_point<Executor, function_type, handler_type>( + executor_, static_cast<F&&>(f), + static_cast<Handler&&>(handler)), + proxy_slot, cancel_state))); } - inline void default_spawn_handler() {} +#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER) + + template <typename Handler, typename StackAllocator, typename F> + void operator()(Handler&& handler, allocator_arg_t, + StackAllocator&& stack_allocator, + F&& f) const + { + typedef decay_t<Handler> handler_type; + typedef decay_t<F> function_type; + typedef spawn_cancellation_handler< + handler_type, Executor> cancel_handler_type; + + associated_cancellation_slot_t<handler_type> slot + = asio::get_associated_cancellation_slot(handler); + + cancel_handler_type* cancel_handler = slot.is_connected() + ? &slot.template emplace<cancel_handler_type>(handler, executor_) + : 0; + + cancellation_slot proxy_slot( + cancel_handler + ? cancel_handler->slot() + : cancellation_slot()); + + cancellation_state cancel_state(proxy_slot); + + (dispatch)(executor_, + spawned_thread_resumer( + spawned_fiber_thread::spawn(allocator_arg_t(), + static_cast<StackAllocator&&>(stack_allocator), + spawn_entry_point<Executor, function_type, handler_type>( + executor_, static_cast<F&&>(f), + static_cast<Handler&&>(handler)), + proxy_slot, cancel_state))); + } + +#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER) + +private: + executor_type executor_; +}; + +} // namespace detail + +template <typename Executor, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type) CompletionToken> +inline auto spawn(const Executor& ex, F&& function, CompletionToken&& token, +#if defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + !is_same< + decay_t<CompletionToken>, + boost::coroutines::attributes + >::value + >, +#endif // defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + >) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type>( + declval<detail::initiate_spawn<Executor>>(), + token, static_cast<F&&>(function))) +{ + return async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type>( + detail::initiate_spawn<Executor>(ex), + token, static_cast<F&&>(function)); +} + +template <typename ExecutionContext, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context< + typename ExecutionContext::executor_type>)>>::type) CompletionToken> +inline auto spawn(ExecutionContext& ctx, F&& function, CompletionToken&& token, +#if defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + !is_same< + decay_t<CompletionToken>, + boost::coroutines::attributes + >::value + >, +#endif // defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + >) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context< + typename ExecutionContext::executor_type>)>>::type>( + declval<detail::initiate_spawn< + typename ExecutionContext::executor_type>>(), + token, static_cast<F&&>(function))) +{ + return (spawn)(ctx.get_executor(), static_cast<F&&>(function), + static_cast<CompletionToken&&>(token)); +} + +template <typename Executor, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type) + CompletionToken> +inline auto spawn(const basic_yield_context<Executor>& ctx, + F&& function, CompletionToken&& token, +#if defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + !is_same< + decay_t<CompletionToken>, + boost::coroutines::attributes + >::value + >, +#endif // defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + >) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type>( + declval<detail::initiate_spawn<Executor>>(), + token, static_cast<F&&>(function))) +{ + return (spawn)(ctx.get_executor(), static_cast<F&&>(function), + static_cast<CompletionToken&&>(token)); +} + +#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER) + +template <typename Executor, typename StackAllocator, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type) + CompletionToken> +inline auto spawn(const Executor& ex, allocator_arg_t, + StackAllocator&& stack_allocator, F&& function, CompletionToken&& token, + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + >) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type>( + declval<detail::initiate_spawn<Executor>>(), + token, allocator_arg_t(), + static_cast<StackAllocator&&>(stack_allocator), + static_cast<F&&>(function))) +{ + return async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type>( + detail::initiate_spawn<Executor>(ex), token, allocator_arg_t(), + static_cast<StackAllocator&&>(stack_allocator), + static_cast<F&&>(function)); +} + +template <typename ExecutionContext, typename StackAllocator, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context< + typename ExecutionContext::executor_type>)>>::type) CompletionToken> +inline auto spawn(ExecutionContext& ctx, allocator_arg_t, + StackAllocator&& stack_allocator, F&& function, CompletionToken&& token, + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + >) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context< + typename ExecutionContext::executor_type>)>>::type>( + declval<detail::initiate_spawn< + typename ExecutionContext::executor_type>>(), + token, allocator_arg_t(), + static_cast<StackAllocator&&>(stack_allocator), + static_cast<F&&>(function))) +{ + return (spawn)(ctx.get_executor(), allocator_arg_t(), + static_cast<StackAllocator&&>(stack_allocator), + static_cast<F&&>(function), static_cast<CompletionToken&&>(token)); +} + +template <typename Executor, typename StackAllocator, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type) CompletionToken> +inline auto spawn(const basic_yield_context<Executor>& ctx, allocator_arg_t, + StackAllocator&& stack_allocator, F&& function, CompletionToken&& token, + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + >) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type>( + declval<detail::initiate_spawn<Executor>>(), token, + allocator_arg_t(), static_cast<StackAllocator&&>(stack_allocator), + static_cast<F&&>(function))) +{ + return (spawn)(ctx.get_executor(), allocator_arg_t(), + static_cast<StackAllocator&&>(stack_allocator), + static_cast<F&&>(function), static_cast<CompletionToken&&>(token)); +} + +#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER) + +#if defined(ASIO_HAS_BOOST_COROUTINE) + +namespace detail { + +template <typename Executor, typename Function, typename Handler> +class old_spawn_entry_point +{ +public: + template <typename F, typename H> + old_spawn_entry_point(const Executor& ex, F&& f, H&& h) + : executor_(ex), + function_(static_cast<F&&>(f)), + handler_(static_cast<H&&>(h)) + { + } + + void operator()(spawned_thread_base* spawned_thread) + { + const basic_yield_context<Executor> yield(spawned_thread, executor_); + this->call(yield, + void_type<result_of_t<Function(basic_yield_context<Executor>)>>()); + } + +private: + void call(const basic_yield_context<Executor>& yield, void_type<void>) + { + function_(yield); + static_cast<Handler&&>(handler_)(); + } + + template <typename T> + void call(const basic_yield_context<Executor>& yield, void_type<T>) + { + static_cast<Handler&&>(handler_)(function_(yield)); + } + + Executor executor_; + Function function_; + Handler handler_; +}; + +inline void default_spawn_handler() {} } // namespace detail template <typename Function> -inline void spawn(ASIO_MOVE_ARG(Function) function, +inline void spawn(Function&& function, const boost::coroutines::attributes& attributes) { - typedef typename decay<Function>::type function_type; - - typename associated_executor<function_type>::type ex( + associated_executor_t<decay_t<Function>> ex( (get_associated_executor)(function)); - asio::spawn(ex, ASIO_MOVE_CAST(Function)(function), attributes); + asio::spawn(ex, static_cast<Function&&>(function), attributes); } template <typename Handler, typename Function> -void spawn(ASIO_MOVE_ARG(Handler) handler, - ASIO_MOVE_ARG(Function) function, +void spawn(Handler&& handler, Function&& function, const boost::coroutines::attributes& attributes, - typename constraint< - !is_executor<typename decay<Handler>::type>::value && - !execution::is_executor<typename decay<Handler>::type>::value && - !is_convertible<Handler&, execution_context&>::value>::type) -{ - typedef typename decay<Handler>::type handler_type; - typedef typename decay<Function>::type function_type; - - detail::spawn_helper<handler_type, function_type> helper; - helper.data_.reset( - new detail::spawn_data<handler_type, function_type>( - ASIO_MOVE_CAST(Handler)(handler), true, - ASIO_MOVE_CAST(Function)(function))); - helper.attributes_ = attributes; - - asio::dispatch(helper); + constraint_t< + !is_executor<decay_t<Handler>>::value && + !execution::is_executor<decay_t<Handler>>::value && + !is_convertible<Handler&, execution_context&>::value>) +{ + typedef associated_executor_t<decay_t<Handler>> executor_type; + executor_type ex((get_associated_executor)(handler)); + + (dispatch)(ex, + detail::spawned_thread_resumer( + detail::spawned_coroutine_thread::spawn( + detail::old_spawn_entry_point<executor_type, + decay_t<Function>, void (*)()>( + ex, static_cast<Function&&>(function), + &detail::default_spawn_handler), attributes))); } -template <typename Handler, typename Function> -void spawn(basic_yield_context<Handler> ctx, - ASIO_MOVE_ARG(Function) function, +template <typename Executor, typename Function> +void spawn(basic_yield_context<Executor> ctx, Function&& function, const boost::coroutines::attributes& attributes) { - typedef typename decay<Function>::type function_type; - - Handler handler(ctx.handler_); // Explicit copy that might be moved from. - - detail::spawn_helper<Handler, function_type> helper; - helper.data_.reset( - new detail::spawn_data<Handler, function_type>( - ASIO_MOVE_CAST(Handler)(handler), false, - ASIO_MOVE_CAST(Function)(function))); - helper.attributes_ = attributes; - - asio::dispatch(helper); + (dispatch)(ctx.get_executor(), + detail::spawned_thread_resumer( + detail::spawned_coroutine_thread::spawn( + detail::old_spawn_entry_point<Executor, + decay_t<Function>, void (*)()>( + ctx.get_executor(), static_cast<Function&&>(function), + &detail::default_spawn_handler), attributes))); } template <typename Function, typename Executor> -inline void spawn(const Executor& ex, - ASIO_MOVE_ARG(Function) function, +inline void spawn(const Executor& ex, Function&& function, const boost::coroutines::attributes& attributes, - typename constraint< + constraint_t< is_executor<Executor>::value || execution::is_executor<Executor>::value - >::type) + >) { asio::spawn(asio::strand<Executor>(ex), - ASIO_MOVE_CAST(Function)(function), attributes); + static_cast<Function&&>(function), attributes); } template <typename Function, typename Executor> -inline void spawn(const strand<Executor>& ex, - ASIO_MOVE_ARG(Function) function, +inline void spawn(const strand<Executor>& ex, Function&& function, const boost::coroutines::attributes& attributes) { asio::spawn(asio::bind_executor( ex, &detail::default_spawn_handler), - ASIO_MOVE_CAST(Function)(function), attributes); + static_cast<Function&&>(function), attributes); } #if !defined(ASIO_NO_TS_EXECUTORS) template <typename Function> -inline void spawn(const asio::io_context::strand& s, - ASIO_MOVE_ARG(Function) function, +inline void spawn(const asio::io_context::strand& s, Function&& function, const boost::coroutines::attributes& attributes) { asio::spawn(asio::bind_executor( s, &detail::default_spawn_handler), - ASIO_MOVE_CAST(Function)(function), attributes); + static_cast<Function&&>(function), attributes); } #endif // !defined(ASIO_NO_TS_EXECUTORS) template <typename Function, typename ExecutionContext> -inline void spawn(ExecutionContext& ctx, - ASIO_MOVE_ARG(Function) function, +inline void spawn(ExecutionContext& ctx, Function&& function, const boost::coroutines::attributes& attributes, - typename constraint<is_convertible< - ExecutionContext&, execution_context&>::value>::type) + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + >) { asio::spawn(ctx.get_executor(), - ASIO_MOVE_CAST(Function)(function), attributes); + static_cast<Function&&>(function), attributes); } -#endif // !defined(GENERATING_DOCUMENTATION) +#endif // defined(ASIO_HAS_BOOST_COROUTINE) } // namespace asio diff --git a/3rdparty/asio/include/asio/impl/src.hpp b/3rdparty/asio/include/asio/impl/src.hpp index 14ca9c252f4..28396195b06 100644 --- a/3rdparty/asio/include/asio/impl/src.hpp +++ b/3rdparty/asio/include/asio/impl/src.hpp @@ -2,7 +2,7 @@ // impl/src.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,11 +19,14 @@ # error Do not compile Asio library source with ASIO_HEADER_ONLY defined #endif +#include "asio/impl/any_completion_executor.ipp" +#include "asio/impl/any_io_executor.ipp" +#include "asio/impl/cancellation_signal.ipp" +#include "asio/impl/connect_pipe.ipp" #include "asio/impl/error.ipp" #include "asio/impl/error_code.ipp" #include "asio/impl/execution_context.ipp" #include "asio/impl/executor.ipp" -#include "asio/impl/handler_alloc_hook.ipp" #include "asio/impl/io_context.ipp" #include "asio/impl/multiple_exceptions.ipp" #include "asio/impl/serial_port_base.ipp" @@ -35,15 +38,19 @@ #include "asio/detail/impl/epoll_reactor.ipp" #include "asio/detail/impl/eventfd_select_interrupter.ipp" #include "asio/detail/impl/handler_tracking.ipp" +#include "asio/detail/impl/io_uring_descriptor_service.ipp" +#include "asio/detail/impl/io_uring_file_service.ipp" +#include "asio/detail/impl/io_uring_socket_service_base.ipp" +#include "asio/detail/impl/io_uring_service.ipp" #include "asio/detail/impl/kqueue_reactor.ipp" #include "asio/detail/impl/null_event.ipp" #include "asio/detail/impl/pipe_select_interrupter.ipp" #include "asio/detail/impl/posix_event.ipp" #include "asio/detail/impl/posix_mutex.ipp" +#include "asio/detail/impl/posix_serial_port_service.ipp" #include "asio/detail/impl/posix_thread.ipp" #include "asio/detail/impl/posix_tss_ptr.ipp" #include "asio/detail/impl/reactive_descriptor_service.ipp" -#include "asio/detail/impl/reactive_serial_port_service.ipp" #include "asio/detail/impl/reactive_socket_service_base.ipp" #include "asio/detail/impl/resolver_service_base.ipp" #include "asio/detail/impl/scheduler.ipp" @@ -58,6 +65,7 @@ #include "asio/detail/impl/throw_error.ipp" #include "asio/detail/impl/timer_queue_ptime.ipp" #include "asio/detail/impl/timer_queue_set.ipp" +#include "asio/detail/impl/win_iocp_file_service.ipp" #include "asio/detail/impl/win_iocp_handle_service.ipp" #include "asio/detail/impl/win_iocp_io_context.ipp" #include "asio/detail/impl/win_iocp_serial_port_service.ipp" @@ -72,7 +80,7 @@ #include "asio/detail/impl/winrt_timer_scheduler.ipp" #include "asio/detail/impl/winsock_init.ipp" #include "asio/execution/impl/bad_executor.ipp" -#include "asio/execution/impl/receiver_invocation_error.ipp" +#include "asio/experimental/impl/channel_error.ipp" #include "asio/generic/detail/impl/endpoint.ipp" #include "asio/ip/impl/address.ipp" #include "asio/ip/impl/address_v4.ipp" diff --git a/3rdparty/asio/include/asio/impl/system_context.hpp b/3rdparty/asio/include/asio/impl/system_context.hpp index 650b0ca57dc..34b5a3a0659 100644 --- a/3rdparty/asio/include/asio/impl/system_context.hpp +++ b/3rdparty/asio/include/asio/impl/system_context.hpp @@ -2,7 +2,7 @@ // impl/system_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,7 +22,7 @@ namespace asio { inline system_context::executor_type -system_context::get_executor() ASIO_NOEXCEPT +system_context::get_executor() noexcept { return system_executor(); } diff --git a/3rdparty/asio/include/asio/impl/system_context.ipp b/3rdparty/asio/include/asio/impl/system_context.ipp index d12c5747277..95fda4804da 100644 --- a/3rdparty/asio/include/asio/impl/system_context.ipp +++ b/3rdparty/asio/include/asio/impl/system_context.ipp @@ -2,7 +2,7 @@ // impl/system_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -67,7 +67,7 @@ void system_context::stop() scheduler_.stop(); } -bool system_context::stopped() const ASIO_NOEXCEPT +bool system_context::stopped() const noexcept { return scheduler_.stopped(); } diff --git a/3rdparty/asio/include/asio/impl/system_executor.hpp b/3rdparty/asio/include/asio/impl/system_executor.hpp index bee9e9ee8c9..099b2d63ef2 100644 --- a/3rdparty/asio/include/asio/impl/system_executor.hpp +++ b/3rdparty/asio/include/asio/impl/system_executor.hpp @@ -2,7 +2,7 @@ // impl/system_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -27,7 +27,7 @@ namespace asio { template <typename Blocking, typename Relationship, typename Allocator> inline system_context& basic_system_executor<Blocking, Relationship, Allocator>::query( - execution::context_t) ASIO_NOEXCEPT + execution::context_t) noexcept { return detail::global<system_context>(); } @@ -35,7 +35,7 @@ basic_system_executor<Blocking, Relationship, Allocator>::query( template <typename Blocking, typename Relationship, typename Allocator> inline std::size_t basic_system_executor<Blocking, Relationship, Allocator>::query( - execution::occupancy_t) const ASIO_NOEXCEPT + execution::occupancy_t) const noexcept { return detail::global<system_context>().num_threads_; } @@ -44,7 +44,7 @@ template <typename Blocking, typename Relationship, typename Allocator> template <typename Function> inline void basic_system_executor<Blocking, Relationship, Allocator>::do_execute( - ASIO_MOVE_ARG(Function) f, execution::blocking_t::possibly_t) const + Function&& f, execution::blocking_t::possibly_t) const { // Obtain a non-const instance of the function. detail::non_const_lvalue<Function> f2(f); @@ -54,7 +54,7 @@ basic_system_executor<Blocking, Relationship, Allocator>::do_execute( { #endif// !defined(ASIO_NO_EXCEPTIONS) detail::fenced_block b(detail::fenced_block::full); - asio_handler_invoke_helpers::invoke(f2.value, f2.value); + static_cast<decay_t<Function>&&>(f2.value)(); #if !defined(ASIO_NO_EXCEPTIONS) } catch (...) @@ -68,7 +68,7 @@ template <typename Blocking, typename Relationship, typename Allocator> template <typename Function> inline void basic_system_executor<Blocking, Relationship, Allocator>::do_execute( - ASIO_MOVE_ARG(Function) f, execution::blocking_t::always_t) const + Function&& f, execution::blocking_t::always_t) const { // Obtain a non-const instance of the function. detail::non_const_lvalue<Function> f2(f); @@ -78,7 +78,7 @@ basic_system_executor<Blocking, Relationship, Allocator>::do_execute( { #endif// !defined(ASIO_NO_EXCEPTIONS) detail::fenced_block b(detail::fenced_block::full); - asio_handler_invoke_helpers::invoke(f2.value, f2.value); + static_cast<decay_t<Function>&&>(f2.value)(); #if !defined(ASIO_NO_EXCEPTIONS) } catch (...) @@ -91,16 +91,15 @@ basic_system_executor<Blocking, Relationship, Allocator>::do_execute( template <typename Blocking, typename Relationship, typename Allocator> template <typename Function> void basic_system_executor<Blocking, Relationship, Allocator>::do_execute( - ASIO_MOVE_ARG(Function) f, execution::blocking_t::never_t) const + Function&& f, execution::blocking_t::never_t) const { system_context& ctx = detail::global<system_context>(); // Allocate and construct an operation to wrap the function. - typedef typename decay<Function>::type function_type; - typedef detail::executor_op<function_type, Allocator> op; + typedef detail::executor_op<decay_t<Function>, Allocator> op; typename op::ptr p = { detail::addressof(allocator_), op::ptr::allocate(allocator_), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), allocator_); + p.p = new (p.v) op(static_cast<Function&&>(f), allocator_); if (is_same<Relationship, execution::relationship_t::continuation_t>::value) { @@ -121,7 +120,7 @@ void basic_system_executor<Blocking, Relationship, Allocator>::do_execute( #if !defined(ASIO_NO_TS_EXECUTORS) template <typename Blocking, typename Relationship, typename Allocator> inline system_context& basic_system_executor< - Blocking, Relationship, Allocator>::context() const ASIO_NOEXCEPT + Blocking, Relationship, Allocator>::context() const noexcept { return detail::global<system_context>(); } @@ -129,25 +128,22 @@ inline system_context& basic_system_executor< template <typename Blocking, typename Relationship, typename Allocator> template <typename Function, typename OtherAllocator> void basic_system_executor<Blocking, Relationship, Allocator>::dispatch( - ASIO_MOVE_ARG(Function) f, const OtherAllocator&) const + Function&& f, const OtherAllocator&) const { - typename decay<Function>::type tmp(ASIO_MOVE_CAST(Function)(f)); - asio_handler_invoke_helpers::invoke(tmp, tmp); + decay_t<Function>(static_cast<Function&&>(f))(); } template <typename Blocking, typename Relationship, typename Allocator> template <typename Function, typename OtherAllocator> void basic_system_executor<Blocking, Relationship, Allocator>::post( - ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const + Function&& f, const OtherAllocator& 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, OtherAllocator> op; + typedef detail::executor_op<decay_t<Function>, OtherAllocator> op; typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a); + p.p = new (p.v) op(static_cast<Function&&>(f), a); ASIO_HANDLER_CREATION((ctx, *p.p, "system_executor", &this->context(), 0, "post")); @@ -159,16 +155,14 @@ void basic_system_executor<Blocking, Relationship, Allocator>::post( template <typename Blocking, typename Relationship, typename Allocator> template <typename Function, typename OtherAllocator> void basic_system_executor<Blocking, Relationship, Allocator>::defer( - ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const + Function&& f, const OtherAllocator& 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, OtherAllocator> op; + typedef detail::executor_op<decay_t<Function>, OtherAllocator> op; typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a); + p.p = new (p.v) op(static_cast<Function&&>(f), a); ASIO_HANDLER_CREATION((ctx, *p.p, "system_executor", &this->context(), 0, "defer")); diff --git a/3rdparty/asio/include/asio/impl/thread_pool.hpp b/3rdparty/asio/include/asio/impl/thread_pool.hpp index 4a6d9d4ca38..3aed249781a 100644 --- a/3rdparty/asio/include/asio/impl/thread_pool.hpp +++ b/3rdparty/asio/include/asio/impl/thread_pool.hpp @@ -2,7 +2,7 @@ // impl/thread_pool.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,7 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/blocking_executor_op.hpp" -#include "asio/detail/bulk_executor_op.hpp" #include "asio/detail/executor_op.hpp" #include "asio/detail/fenced_block.hpp" #include "asio/detail/non_const_lvalue.hpp" @@ -28,27 +27,21 @@ namespace asio { inline thread_pool::executor_type -thread_pool::get_executor() ASIO_NOEXCEPT +thread_pool::get_executor() noexcept { return executor_type(*this); } inline thread_pool::executor_type -thread_pool::executor() ASIO_NOEXCEPT +thread_pool::executor() noexcept { return executor_type(*this); } -inline thread_pool::scheduler_type -thread_pool::scheduler() ASIO_NOEXCEPT -{ - return scheduler_type(*this); -} - template <typename Allocator, unsigned int Bits> thread_pool::basic_executor_type<Allocator, Bits>& thread_pool::basic_executor_type<Allocator, Bits>::operator=( - const basic_executor_type& other) ASIO_NOEXCEPT + const basic_executor_type& other) noexcept { if (this != &other) { @@ -67,11 +60,10 @@ thread_pool::basic_executor_type<Allocator, Bits>::operator=( return *this; } -#if defined(ASIO_HAS_MOVE) template <typename Allocator, unsigned int Bits> thread_pool::basic_executor_type<Allocator, Bits>& thread_pool::basic_executor_type<Allocator, Bits>::operator=( - basic_executor_type&& other) ASIO_NOEXCEPT + basic_executor_type&& other) noexcept { if (this != &other) { @@ -88,11 +80,10 @@ thread_pool::basic_executor_type<Allocator, Bits>::operator=( } return *this; } -#endif // defined(ASIO_HAS_MOVE) template <typename Allocator, unsigned int Bits> inline bool thread_pool::basic_executor_type<Allocator, - Bits>::running_in_this_thread() const ASIO_NOEXCEPT + Bits>::running_in_this_thread() const noexcept { return pool_->scheduler_.can_dispatch(); } @@ -100,43 +91,39 @@ inline bool thread_pool::basic_executor_type<Allocator, template <typename Allocator, unsigned int Bits> template <typename Function> void thread_pool::basic_executor_type<Allocator, - Bits>::do_execute(ASIO_MOVE_ARG(Function) f, false_type) const + Bits>::do_execute(Function&& f, false_type) const { - typedef typename decay<Function>::type function_type; + typedef decay_t<Function> function_type; // Invoke immediately if the blocking.possibly property is enabled and we are // already inside the thread pool. if ((bits_ & blocking_never) == 0 && pool_->scheduler_.can_dispatch()) { // Make a local, non-const copy of the function. - function_type tmp(ASIO_MOVE_CAST(Function)(f)); + function_type tmp(static_cast<Function&&>(f)); -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \ - && !defined(ASIO_NO_EXCEPTIONS) +#if !defined(ASIO_NO_EXCEPTIONS) try { -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - // && !defined(ASIO_NO_EXCEPTIONS) +#endif // !defined(ASIO_NO_EXCEPTIONS) detail::fenced_block b(detail::fenced_block::full); - asio_handler_invoke_helpers::invoke(tmp, tmp); + static_cast<function_type&&>(tmp)(); return; -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \ - && !defined(ASIO_NO_EXCEPTIONS) +#if !defined(ASIO_NO_EXCEPTIONS) } catch (...) { pool_->scheduler_.capture_current_exception(); return; } -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - // && !defined(ASIO_NO_EXCEPTIONS) +#endif // !defined(ASIO_NO_EXCEPTIONS) } // Allocate and construct an operation to wrap the function. typedef detail::executor_op<function_type, Allocator> op; typename op::ptr p = { detail::addressof(allocator_), op::ptr::allocate(allocator_), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), allocator_); + p.p = new (p.v) op(static_cast<Function&&>(f), allocator_); if ((bits_ & relationship_continuation) != 0) { @@ -157,7 +144,7 @@ void thread_pool::basic_executor_type<Allocator, template <typename Allocator, unsigned int Bits> template <typename Function> void thread_pool::basic_executor_type<Allocator, - Bits>::do_execute(ASIO_MOVE_ARG(Function) f, true_type) const + Bits>::do_execute(Function&& f, true_type) const { // Obtain a non-const instance of the function. detail::non_const_lvalue<Function> f2(f); @@ -170,7 +157,7 @@ void thread_pool::basic_executor_type<Allocator, { #endif // !defined(ASIO_NO_EXCEPTIONS) detail::fenced_block b(detail::fenced_block::full); - asio_handler_invoke_helpers::invoke(f2.value, f2.value); + static_cast<decay_t<Function>&&>(f2.value)(); return; #if !defined(ASIO_NO_EXCEPTIONS) } @@ -182,7 +169,7 @@ void thread_pool::basic_executor_type<Allocator, } // Construct an operation to wrap the function. - typedef typename decay<Function>::type function_type; + typedef decay_t<Function> function_type; detail::blocking_executor_op<function_type> op(f2.value); ASIO_HANDLER_CREATION((*pool_, op, @@ -192,88 +179,24 @@ void thread_pool::basic_executor_type<Allocator, op.wait(); } -template <typename Allocator, unsigned int Bits> -template <typename Function> -void thread_pool::basic_executor_type<Allocator, Bits>::do_bulk_execute( - ASIO_MOVE_ARG(Function) f, std::size_t n, false_type) const -{ - typedef typename decay<Function>::type function_type; - typedef detail::bulk_executor_op<function_type, Allocator> op; - - // Allocate and construct operations to wrap the function. - detail::op_queue<detail::scheduler_operation> ops; - for (std::size_t i = 0; i < n; ++i) - { - typename op::ptr p = { detail::addressof(allocator_), - op::ptr::allocate(allocator_), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), allocator_, i); - ops.push(p.p); - - if ((bits_ & relationship_continuation) != 0) - { - ASIO_HANDLER_CREATION((*pool_, *p.p, - "thread_pool", pool_, 0, "bulk_execute(blk=never,rel=cont)")); - } - else - { - ASIO_HANDLER_CREATION((*pool_, *p.p, - "thread_pool", pool_, 0, "bulk)execute(blk=never,rel=fork)")); - } - - p.v = p.p = 0; - } - - pool_->scheduler_.post_immediate_completions(n, - ops, (bits_ & relationship_continuation) != 0); -} - -template <typename Function> -struct thread_pool_always_blocking_function_adapter -{ - typename decay<Function>::type* f; - std::size_t n; - - void operator()() - { - for (std::size_t i = 0; i < n; ++i) - { - (*f)(i); - } - } -}; - -template <typename Allocator, unsigned int Bits> -template <typename Function> -void thread_pool::basic_executor_type<Allocator, Bits>::do_bulk_execute( - ASIO_MOVE_ARG(Function) f, std::size_t n, true_type) const -{ - // Obtain a non-const instance of the function. - detail::non_const_lvalue<Function> f2(f); - - thread_pool_always_blocking_function_adapter<Function> - adapter = { detail::addressof(f2.value), n }; - - this->do_execute(adapter, true_type()); -} - #if !defined(ASIO_NO_TS_EXECUTORS) template <typename Allocator, unsigned int Bits> inline thread_pool& thread_pool::basic_executor_type< - Allocator, Bits>::context() const ASIO_NOEXCEPT + Allocator, Bits>::context() const noexcept { return *pool_; } template <typename Allocator, unsigned int Bits> inline void thread_pool::basic_executor_type<Allocator, - Bits>::on_work_started() const ASIO_NOEXCEPT + Bits>::on_work_started() const noexcept { pool_->scheduler_.work_started(); } template <typename Allocator, unsigned int Bits> inline void thread_pool::basic_executor_type<Allocator, - Bits>::on_work_finished() const ASIO_NOEXCEPT + Bits>::on_work_finished() const noexcept { pool_->scheduler_.work_finished(); } @@ -281,25 +204,25 @@ inline void thread_pool::basic_executor_type<Allocator, template <typename Allocator, unsigned int Bits> template <typename Function, typename OtherAllocator> void thread_pool::basic_executor_type<Allocator, Bits>::dispatch( - ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const + Function&& f, const OtherAllocator& a) const { - typedef typename decay<Function>::type function_type; + typedef decay_t<Function> 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(ASIO_MOVE_CAST(Function)(f)); + function_type tmp(static_cast<Function&&>(f)); detail::fenced_block b(detail::fenced_block::full); - asio_handler_invoke_helpers::invoke(tmp, tmp); + static_cast<function_type&&>(tmp)(); return; } // Allocate and construct an operation to wrap the function. typedef detail::executor_op<function_type, OtherAllocator> op; typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a); + p.p = new (p.v) op(static_cast<Function&&>(f), a); ASIO_HANDLER_CREATION((*pool_, *p.p, "thread_pool", pool_, 0, "dispatch")); @@ -311,14 +234,14 @@ void thread_pool::basic_executor_type<Allocator, Bits>::dispatch( template <typename Allocator, unsigned int Bits> template <typename Function, typename OtherAllocator> void thread_pool::basic_executor_type<Allocator, Bits>::post( - ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const + Function&& f, const OtherAllocator& a) const { - typedef typename decay<Function>::type function_type; + typedef decay_t<Function> function_type; // Allocate and construct an operation to wrap the function. typedef detail::executor_op<function_type, OtherAllocator> op; typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a); + p.p = new (p.v) op(static_cast<Function&&>(f), a); ASIO_HANDLER_CREATION((*pool_, *p.p, "thread_pool", pool_, 0, "post")); @@ -330,14 +253,14 @@ void thread_pool::basic_executor_type<Allocator, Bits>::post( template <typename Allocator, unsigned int Bits> template <typename Function, typename OtherAllocator> void thread_pool::basic_executor_type<Allocator, Bits>::defer( - ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const + Function&& f, const OtherAllocator& a) const { - typedef typename decay<Function>::type function_type; + typedef decay_t<Function> function_type; // Allocate and construct an operation to wrap the function. typedef detail::executor_op<function_type, OtherAllocator> op; typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 }; - p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a); + p.p = new (p.v) op(static_cast<Function&&>(f), a); ASIO_HANDLER_CREATION((*pool_, *p.p, "thread_pool", pool_, 0, "defer")); diff --git a/3rdparty/asio/include/asio/impl/thread_pool.ipp b/3rdparty/asio/include/asio/impl/thread_pool.ipp index 2e04d2afffc..3f327e4610b 100644 --- a/3rdparty/asio/include/asio/impl/thread_pool.ipp +++ b/3rdparty/asio/include/asio/impl/thread_pool.ipp @@ -2,7 +2,7 @@ // impl/thread_pool.ipp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -98,6 +98,7 @@ thread_pool::~thread_pool() { stop(); join(); + shutdown(); } void thread_pool::stop() @@ -114,11 +115,11 @@ void thread_pool::attach() void thread_pool::join() { - if (!threads_.empty()) - { + if (num_threads_) scheduler_.work_finished(); + + if (!threads_.empty()) threads_.join(); - } } detail::scheduler& thread_pool::add_scheduler(detail::scheduler* s) diff --git a/3rdparty/asio/include/asio/impl/use_awaitable.hpp b/3rdparty/asio/include/asio/impl/use_awaitable.hpp index 2f5449f5428..3cd95165c4f 100644 --- a/3rdparty/asio/include/asio/impl/use_awaitable.hpp +++ b/3rdparty/asio/include/asio/impl/use_awaitable.hpp @@ -2,7 +2,7 @@ // impl/use_awaitable.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -258,21 +258,31 @@ class async_result<use_awaitable_t<Executor>, R(Args...)> { public: typedef typename detail::awaitable_handler< - Executor, typename decay<Args>::type...> handler_type; + Executor, decay_t<Args>...> handler_type; typedef typename handler_type::awaitable_type return_type; template <typename Initiation, typename... InitArgs> - static return_type initiate(Initiation initiation, - use_awaitable_t<Executor> u, InitArgs... args) +#if defined(__APPLE_CC__) && (__clang_major__ == 13) + __attribute__((noinline)) +#endif // defined(__APPLE_CC__) && (__clang_major__ == 13) + static handler_type* do_init( + detail::awaitable_frame_base<Executor>* frame, Initiation& initiation, + use_awaitable_t<Executor> u, InitArgs&... args) { (void)u; + ASIO_HANDLER_LOCATION((u.file_name_, u.line_, u.function_name_)); + handler_type handler(frame->detach_thread()); + std::move(initiation)(std::move(handler), std::move(args)...); + return nullptr; + } - co_await [&](auto* frame) + template <typename Initiation, typename... InitArgs> + static return_type initiate(Initiation initiation, + use_awaitable_t<Executor> u, InitArgs... args) + { + co_await [&] (auto* frame) { - ASIO_HANDLER_LOCATION((u.file_name_, u.line_, u.function_name_)); - handler_type handler(frame->detach_thread()); - std::move(initiation)(std::move(handler), std::move(args)...); - return static_cast<handler_type*>(nullptr); + return do_init(frame, initiation, u, args...); }; for (;;) {} // Never reached. diff --git a/3rdparty/asio/include/asio/impl/use_future.hpp b/3rdparty/asio/include/asio/impl/use_future.hpp index 4a35ab4754d..579b93f5f30 100644 --- a/3rdparty/asio/include/asio/impl/use_future.hpp +++ b/3rdparty/asio/include/asio/impl/use_future.hpp @@ -2,7 +2,7 @@ // impl/use_future.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -31,17 +31,15 @@ namespace asio { namespace detail { -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename T, typename F, typename... Args> inline void promise_invoke_and_set(std::promise<T>& p, - F& f, ASIO_MOVE_ARG(Args)... args) + F& f, Args&&... args) { #if !defined(ASIO_NO_EXCEPTIONS) try #endif // !defined(ASIO_NO_EXCEPTIONS) { - p.set_value(f(ASIO_MOVE_CAST(Args)(args)...)); + p.set_value(f(static_cast<Args&&>(args)...)); } #if !defined(ASIO_NO_EXCEPTIONS) catch (...) @@ -53,13 +51,13 @@ inline void promise_invoke_and_set(std::promise<T>& p, template <typename F, typename... Args> inline void promise_invoke_and_set(std::promise<void>& p, - F& f, ASIO_MOVE_ARG(Args)... args) + F& f, Args&&... args) { #if !defined(ASIO_NO_EXCEPTIONS) try #endif // !defined(ASIO_NO_EXCEPTIONS) { - f(ASIO_MOVE_CAST(Args)(args)...); + f(static_cast<Args&&>(args)...); p.set_value(); } #if !defined(ASIO_NO_EXCEPTIONS) @@ -70,112 +68,15 @@ inline void promise_invoke_and_set(std::promise<void>& p, #endif // !defined(ASIO_NO_EXCEPTIONS) } -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T, typename F> -inline void promise_invoke_and_set(std::promise<T>& p, F& f) -{ -#if !defined(ASIO_NO_EXCEPTIONS) - try -#endif // !defined(ASIO_NO_EXCEPTIONS) - { - p.set_value(f()); - } -#if !defined(ASIO_NO_EXCEPTIONS) - catch (...) - { - p.set_exception(std::current_exception()); - } -#endif // !defined(ASIO_NO_EXCEPTIONS) -} - -template <typename F, typename Args> -inline void promise_invoke_and_set(std::promise<void>& p, F& f) -{ -#if !defined(ASIO_NO_EXCEPTIONS) - try -#endif // !defined(ASIO_NO_EXCEPTIONS) - { - f(); - p.set_value(); -#if !defined(ASIO_NO_EXCEPTIONS) - } - catch (...) - { - p.set_exception(std::current_exception()); - } -#endif // !defined(ASIO_NO_EXCEPTIONS) -} - -#if defined(ASIO_NO_EXCEPTIONS) - -#define ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \ - template <typename T, typename F, ASIO_VARIADIC_TPARAMS(n)> \ - inline void promise_invoke_and_set(std::promise<T>& p, \ - F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - p.set_value(f(ASIO_VARIADIC_MOVE_ARGS(n))); \ - } \ - \ - template <typename F, ASIO_VARIADIC_TPARAMS(n)> \ - inline void promise_invoke_and_set(std::promise<void>& p, \ - F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - f(ASIO_VARIADIC_MOVE_ARGS(n)); \ - p.set_value(); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_INVOKE_DEF) -#undef ASIO_PRIVATE_PROMISE_INVOKE_DEF - -#else // defined(ASIO_NO_EXCEPTIONS) - -#define ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \ - template <typename T, typename F, ASIO_VARIADIC_TPARAMS(n)> \ - inline void promise_invoke_and_set(std::promise<T>& p, \ - F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - try \ - { \ - p.set_value(f(ASIO_VARIADIC_MOVE_ARGS(n))); \ - } \ - catch (...) \ - { \ - p.set_exception(std::current_exception()); \ - } \ - } \ - \ - template <typename F, ASIO_VARIADIC_TPARAMS(n)> \ - inline void promise_invoke_and_set(std::promise<void>& p, \ - F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \ - { \ - try \ - { \ - f(ASIO_VARIADIC_MOVE_ARGS(n)); \ - p.set_value(); \ - } \ - catch (...) \ - { \ - p.set_exception(std::current_exception()); \ - } \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_INVOKE_DEF) -#undef ASIO_PRIVATE_PROMISE_INVOKE_DEF - -#endif // defined(ASIO_NO_EXCEPTIONS) - -#endif // defined(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, - ASIO_MOVE_ARG(F) f) - : p_(p), f_(ASIO_MOVE_CAST(F)(f)) + promise_invoker(const shared_ptr<std::promise<T>>& p, + F&& f) + : p_(p), f_(static_cast<F&&>(f)) { } @@ -196,8 +97,8 @@ public: } private: - shared_ptr<std::promise<T> > p_; - typename decay<F>::type f_; + shared_ptr<std::promise<T>> p_; + decay_t<F> f_; }; // An executor that adapts the system_executor to capture any exeption thrown @@ -206,12 +107,17 @@ template <typename T, typename Blocking = execution::blocking_t::possibly_t> class promise_executor { public: - explicit promise_executor(const shared_ptr<std::promise<T> >& p) + explicit promise_executor(const shared_ptr<std::promise<T>>& p) : p_(p) { } - static ASIO_CONSTEXPR Blocking query(execution::blocking_t) + execution_context& query(execution::context_t) const noexcept + { + return asio::query(system_executor(), execution::context); + } + + static constexpr Blocking query(execution::blocking_t) { return Blocking(); } @@ -229,57 +135,56 @@ public: } template <typename F> - void execute(ASIO_MOVE_ARG(F) f) const + void execute(F&& f) const { - execution::execute( - asio::require(system_executor(), Blocking()), - promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f))); + asio::require(system_executor(), Blocking()).execute( + promise_invoker<T, F>(p_, static_cast<F&&>(f))); } #if !defined(ASIO_NO_TS_EXECUTORS) - execution_context& context() const ASIO_NOEXCEPT + execution_context& context() const noexcept { return system_executor().context(); } - void on_work_started() const ASIO_NOEXCEPT {} - void on_work_finished() const ASIO_NOEXCEPT {} + void on_work_started() const noexcept {} + void on_work_finished() const noexcept {} template <typename F, typename A> - void dispatch(ASIO_MOVE_ARG(F) f, const A&) const + void dispatch(F&& f, const A&) const { - promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f))(); + promise_invoker<T, F>(p_, static_cast<F&&>(f))(); } template <typename F, typename A> - void post(ASIO_MOVE_ARG(F) f, const A& a) const + void post(F&& f, const A& a) const { system_executor().post( - promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)), a); + promise_invoker<T, F>(p_, static_cast<F&&>(f)), a); } template <typename F, typename A> - void defer(ASIO_MOVE_ARG(F) f, const A& a) const + void defer(F&& f, const A& a) const { system_executor().defer( - promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)), a); + promise_invoker<T, F>(p_, static_cast<F&&>(f)), a); } #endif // !defined(ASIO_NO_TS_EXECUTORS) friend bool operator==(const promise_executor& a, - const promise_executor& b) ASIO_NOEXCEPT + const promise_executor& b) noexcept { return a.p_ == b.p_; } friend bool operator!=(const promise_executor& a, - const promise_executor& b) ASIO_NOEXCEPT + const promise_executor& b) noexcept { return a.p_ != b.p_; } private: - shared_ptr<std::promise<T> > p_; + shared_ptr<std::promise<T>> p_; }; // The base class for all completion handlers that create promises. @@ -289,7 +194,7 @@ class promise_creator public: typedef promise_executor<T> executor_type; - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return executor_type(p_); } @@ -309,7 +214,7 @@ protected: p_ = std::allocate_shared<std::promise<T>>(b, std::allocator_arg, b); } - shared_ptr<std::promise<T> > p_; + shared_ptr<std::promise<T>> p_; }; // For completion signature void(). @@ -368,9 +273,9 @@ class promise_handler_1 { public: template <typename Arg> - void operator()(ASIO_MOVE_ARG(Arg) arg) + void operator()(Arg&& arg) { - this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg)); + this->p_->set_value(static_cast<Arg&&>(arg)); } }; @@ -382,7 +287,7 @@ class promise_handler_ec_1 public: template <typename Arg> void operator()(const asio::error_code& ec, - ASIO_MOVE_ARG(Arg) arg) + Arg&& arg) { if (ec) { @@ -391,7 +296,7 @@ public: asio::system_error(ec))); } else - this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg)); + this->p_->set_value(static_cast<Arg&&>(arg)); } }; @@ -403,12 +308,12 @@ class promise_handler_ex_1 public: template <typename Arg> void operator()(const std::exception_ptr& ex, - ASIO_MOVE_ARG(Arg) arg) + Arg&& arg) { if (ex) this->p_->set_exception(ex); else - this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg)); + this->p_->set_value(static_cast<Arg&&>(arg)); } }; @@ -418,31 +323,13 @@ class promise_handler_n : public promise_creator<T> { public: -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename... Args> - void operator()(ASIO_MOVE_ARG(Args)... args) + void operator()(Args&&... args) { this->p_->set_value( std::forward_as_tuple( - ASIO_MOVE_CAST(Args)(args)...)); + static_cast<Args&&>(args)...)); } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#define ASIO_PRIVATE_CALL_OP_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \ - {\ - this->p_->set_value( \ - std::forward_as_tuple( \ - ASIO_VARIADIC_MOVE_ARGS(n))); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) -#undef ASIO_PRIVATE_CALL_OP_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) }; // For completion signature void(error_code, T1, ..., Tn); @@ -451,11 +338,8 @@ class promise_handler_ec_n : public promise_creator<T> { public: -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename... Args> - void operator()(const asio::error_code& ec, - ASIO_MOVE_ARG(Args)... args) + void operator()(const asio::error_code& ec, Args&&... args) { if (ec) { @@ -467,35 +351,9 @@ public: { this->p_->set_value( std::forward_as_tuple( - ASIO_MOVE_CAST(Args)(args)...)); + static_cast<Args&&>(args)...)); } } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#define ASIO_PRIVATE_CALL_OP_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - void operator()(const asio::error_code& ec, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - {\ - if (ec) \ - { \ - this->p_->set_exception( \ - std::make_exception_ptr( \ - asio::system_error(ec))); \ - } \ - else \ - { \ - this->p_->set_value( \ - std::forward_as_tuple( \ - ASIO_VARIADIC_MOVE_ARGS(n))); \ - } \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) -#undef ASIO_PRIVATE_CALL_OP_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) }; // For completion signature void(exception_ptr, T1, ..., Tn); @@ -504,11 +362,9 @@ class promise_handler_ex_n : public promise_creator<T> { public: -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename... Args> void operator()(const std::exception_ptr& ex, - ASIO_MOVE_ARG(Args)... args) + Args&&... args) { if (ex) this->p_->set_exception(ex); @@ -516,31 +372,9 @@ public: { this->p_->set_value( std::forward_as_tuple( - ASIO_MOVE_CAST(Args)(args)...)); + static_cast<Args&&>(args)...)); } } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#define ASIO_PRIVATE_CALL_OP_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - void operator()(const std::exception_ptr& ex, \ - ASIO_VARIADIC_MOVE_PARAMS(n)) \ - {\ - if (ex) \ - this->p_->set_exception(ex); \ - else \ - { \ - this->p_->set_value( \ - std::forward_as_tuple( \ - ASIO_VARIADIC_MOVE_ARGS(n))); \ - } \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) -#undef ASIO_PRIVATE_CALL_OP_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) }; // Helper template to choose the appropriate concrete promise handler @@ -571,45 +405,17 @@ template <typename Arg> class promise_handler_selector<void(std::exception_ptr, Arg)> : public promise_handler_ex_1<Arg> {}; -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename... Arg> class promise_handler_selector<void(Arg...)> - : public promise_handler_n<std::tuple<Arg...> > {}; + : public promise_handler_n<std::tuple<Arg...>> {}; template <typename... Arg> class promise_handler_selector<void(asio::error_code, Arg...)> - : public promise_handler_ec_n<std::tuple<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(ASIO_HAS_VARIADIC_TEMPLATES) - -#define ASIO_PRIVATE_PROMISE_SELECTOR_DEF(n) \ - template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \ - class promise_handler_selector< \ - void(Arg, ASIO_VARIADIC_TARGS(n))> \ - : public promise_handler_n< \ - std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \ - \ - template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \ - class promise_handler_selector< \ - void(asio::error_code, Arg, ASIO_VARIADIC_TARGS(n))> \ - : public promise_handler_ec_n< \ - std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \ - \ - template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \ - class promise_handler_selector< \ - void(std::exception_ptr, Arg, ASIO_VARIADIC_TARGS(n))> \ - : public promise_handler_ex_n< \ - std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \ - /**/ - ASIO_VARIADIC_GENERATE_5(ASIO_PRIVATE_PROMISE_SELECTOR_DEF) -#undef ASIO_PRIVATE_PROMISE_SELECTOR_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) + : public promise_handler_ex_n<std::tuple<Arg...>> {}; // Completion handlers produced from the use_future completion token, when not // using use_future::operator(). @@ -627,7 +433,7 @@ public: this->create_promise(allocator_); } - allocator_type get_allocator() const ASIO_NOEXCEPT + allocator_type get_allocator() const noexcept { return allocator_; } @@ -640,7 +446,7 @@ template <typename Function> struct promise_function_wrapper { explicit promise_function_wrapper(Function& f) - : function_(ASIO_MOVE_CAST(Function)(f)) + : function_(static_cast<Function&&>(f)) { } @@ -657,28 +463,6 @@ struct promise_function_wrapper Function function_; }; -#if !defined(ASIO_NO_DEPRECATED) - -template <typename Function, typename Signature, typename Allocator> -inline void asio_handler_invoke(Function& f, - promise_handler<Signature, Allocator>* h) -{ - typename promise_handler<Signature, Allocator>::executor_type - ex(h->get_executor()); - asio::dispatch(ex, promise_function_wrapper<Function>(f)); -} - -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()); - asio::dispatch(ex, promise_function_wrapper<Function>(f)); -} - -#endif // !defined(ASIO_NO_DEPRECATED) - // Helper base class for async_result specialisation. template <typename Signature, typename Allocator> class promise_async_result @@ -694,7 +478,7 @@ public: return_type get() { - return ASIO_MOVE_CAST(return_type)(future_); + return static_cast<return_type&&>(future_); } private: @@ -707,7 +491,7 @@ class packaged_token { public: packaged_token(Function f, const Allocator& a) - : function_(ASIO_MOVE_CAST(Function)(f)), + : function_(static_cast<Function&&>(f)), allocator_(a) { } @@ -728,75 +512,29 @@ public: typedef void result_type; packaged_handler(packaged_token<Function, Allocator> t) - : function_(ASIO_MOVE_CAST(Function)(t.function_)), + : function_(static_cast<Function&&>(t.function_)), allocator_(t.allocator_) { this->create_promise(allocator_); } - allocator_type get_allocator() const ASIO_NOEXCEPT + allocator_type get_allocator() const noexcept { return allocator_; } -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename... Args> - void operator()(ASIO_MOVE_ARG(Args)... args) + void operator()(Args&&... args) { (promise_invoke_and_set)(*this->p_, - function_, ASIO_MOVE_CAST(Args)(args)...); - } - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - - void operator()() - { - (promise_invoke_and_set)(*this->p_, function_); + function_, static_cast<Args&&>(args)...); } -#define ASIO_PRIVATE_CALL_OP_DEF(n) \ - template <ASIO_VARIADIC_TPARAMS(n)> \ - void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \ - {\ - (promise_invoke_and_set)(*this->p_, \ - function_, ASIO_VARIADIC_MOVE_ARGS(n)); \ - } \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF) -#undef ASIO_PRIVATE_CALL_OP_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - private: Function function_; Allocator allocator_; }; -#if !defined(ASIO_NO_DEPRECATED) - -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()); - asio::dispatch(ex, promise_function_wrapper<Function>(f)); -} - -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()); - asio::dispatch(ex, promise_function_wrapper<Function>(f)); -} - -#endif // !defined(ASIO_NO_DEPRECATED) - // Helper base class for async_result specialisation. template <typename Function, typename Allocator, typename Result> class packaged_async_result @@ -812,7 +550,7 @@ public: return_type get() { - return ASIO_MOVE_CAST(return_type)(future_); + return static_cast<return_type&&>(future_); } private: @@ -822,28 +560,26 @@ private: } // namespace detail template <typename Allocator> template <typename Function> -inline detail::packaged_token<typename decay<Function>::type, Allocator> -use_future_t<Allocator>::operator()(ASIO_MOVE_ARG(Function) f) const +inline detail::packaged_token<decay_t<Function>, Allocator> +use_future_t<Allocator>::operator()(Function&& f) const { - return detail::packaged_token<typename decay<Function>::type, Allocator>( - ASIO_MOVE_CAST(Function)(f), allocator_); + return detail::packaged_token<decay_t<Function>, Allocator>( + static_cast<Function&&>(f), allocator_); } #if !defined(GENERATING_DOCUMENTATION) -#if defined(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> + void(decay_t<Args>...), Allocator> { public: explicit async_result( - typename detail::promise_async_result<void(typename decay<Args>::type...), + typename detail::promise_async_result<void(decay_t<Args>...), Allocator>::completion_handler_type& h) : detail::promise_async_result< - void(typename decay<Args>::type...), Allocator>(h) + void(decay_t<Args>...), Allocator>(h) { } }; @@ -852,100 +588,28 @@ 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(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> + result_of_t<Function(Args...)>> { public: explicit async_result( typename detail::packaged_async_result<Function, Allocator, - typename result_of<Function()>::type>::completion_handler_type& h) + result_of_t<Function(Args...)>>::completion_handler_type& h) : detail::packaged_async_result<Function, Allocator, - typename result_of<Function()>::type>(h) + result_of_t<Function(Args...)>>(h) { } }; -#define ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \ - template <typename Allocator, \ - typename Result, ASIO_VARIADIC_TPARAMS(n)> \ - class async_result<use_future_t<Allocator>, \ - Result(ASIO_VARIADIC_TARGS(n))> \ - : public detail::promise_async_result< \ - void(ASIO_VARIADIC_DECAY(n)), Allocator> \ - { \ - public: \ - explicit async_result( \ - typename detail::promise_async_result< \ - void(ASIO_VARIADIC_DECAY(n)), \ - Allocator>::completion_handler_type& h) \ - : detail::promise_async_result< \ - void(ASIO_VARIADIC_DECAY(n)), Allocator>(h) \ - { \ - } \ - }; \ - \ - template <typename Function, typename Allocator, \ - typename Result, ASIO_VARIADIC_TPARAMS(n)> \ - class async_result<detail::packaged_token<Function, Allocator>, \ - Result(ASIO_VARIADIC_TARGS(n))> \ - : public detail::packaged_async_result<Function, Allocator, \ - typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type> \ - { \ - public: \ - explicit async_result( \ - typename detail::packaged_async_result<Function, Allocator, \ - typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type \ - >::completion_handler_type& h) \ - : detail::packaged_async_result<Function, Allocator, \ - typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type>(h) \ - { \ - } \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_RESULT_DEF) -#undef ASIO_PRIVATE_ASYNC_RESULT_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - namespace traits { #if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) template <typename T, typename Blocking> struct equality_comparable< - asio::detail::promise_executor<T, Blocking> > + asio::detail::promise_executor<T, Blocking>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; }; #endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) @@ -956,14 +620,14 @@ template <typename T, typename Blocking, typename Function> struct execute_member< asio::detail::promise_executor<T, Blocking>, Function> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef void result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) -#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT) +#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) template <typename T, typename Blocking, typename Property> struct query_static_constexpr_member< @@ -977,17 +641,32 @@ struct query_static_constexpr_member< >::type > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef Blocking result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return Blocking(); } }; -#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT) +#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) + +#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) + +template <typename T, typename Blocking> +struct query_member< + asio::detail::promise_executor<T, Blocking>, + execution::context_t + > +{ + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; + typedef asio::system_context& result_type; +}; + +#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) @@ -997,8 +676,8 @@ struct require_member< execution::blocking_t::possibly_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::detail::promise_executor<T, execution::blocking_t::possibly_t> result_type; }; @@ -1009,8 +688,8 @@ struct require_member< execution::blocking_t::never_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::detail::promise_executor<T, execution::blocking_t::never_t> result_type; }; diff --git a/3rdparty/asio/include/asio/impl/write.hpp b/3rdparty/asio/include/asio/impl/write.hpp index 67eb093f894..af2bb5544bb 100644 --- a/3rdparty/asio/include/asio/impl/write.hpp +++ b/3rdparty/asio/include/asio/impl/write.hpp @@ -2,7 +2,7 @@ // impl/write.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,16 +17,13 @@ #include "asio/associator.hpp" #include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp" #include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp" #include "asio/detail/dependent_type.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_tracking.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/non_const_lvalue.hpp" @@ -40,7 +37,7 @@ namespace detail { template <typename SyncWriteStream, typename ConstBufferSequence, typename ConstBufferIterator, typename CompletionCondition> - std::size_t write_buffer_sequence(SyncWriteStream& s, + std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, const ConstBufferIterator&, CompletionCondition completion_condition, asio::error_code& ec) { @@ -63,20 +60,20 @@ template <typename SyncWriteStream, typename ConstBufferSequence, typename CompletionCondition> inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type) + >) { - return detail::write_buffer_sequence(s, buffers, + return detail::write(s, buffers, asio::buffer_sequence_begin(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); } template <typename SyncWriteStream, typename ConstBufferSequence> inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, - typename constraint< + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec); @@ -87,9 +84,9 @@ 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, asio::error_code& ec, - typename constraint< + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type) + >) { return write(s, buffers, transfer_all(), ec); } @@ -98,13 +95,13 @@ template <typename SyncWriteStream, typename ConstBufferSequence, typename CompletionCondition> inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, CompletionCondition completion_condition, - typename constraint< + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = write(s, buffers, - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); asio::detail::throw_error(ec, "write"); return bytes_transferred; } @@ -114,37 +111,37 @@ inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, template <typename SyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t write(SyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { - typename decay<DynamicBuffer_v1>::type b( - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers)); + decay_t<DynamicBuffer_v1> b( + static_cast<DynamicBuffer_v1&&>(buffers)); std::size_t bytes_transferred = write(s, b.data(), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); b.consume(bytes_transferred); return bytes_transferred; } template <typename SyncWriteStream, typename DynamicBuffer_v1> inline std::size_t write(SyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + DynamicBuffer_v1&& buffers, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { asio::error_code ec; std::size_t bytes_transferred = write(s, - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + static_cast<DynamicBuffer_v1&&>(buffers), transfer_all(), ec); asio::detail::throw_error(ec, "write"); return bytes_transferred; @@ -152,35 +149,35 @@ inline std::size_t write(SyncWriteStream& s, template <typename SyncWriteStream, typename DynamicBuffer_v1> inline std::size_t write(SyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) -{ - return write(s, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) +{ + return write(s, static_cast<DynamicBuffer_v1&&>(buffers), transfer_all(), ec); } template <typename SyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition> inline std::size_t write(SyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, CompletionCondition completion_condition, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) { asio::error_code ec; std::size_t bytes_transferred = write(s, - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<DynamicBuffer_v1&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition), ec); asio::detail::throw_error(ec, "write"); return bytes_transferred; } @@ -195,7 +192,7 @@ inline std::size_t write(SyncWriteStream& s, CompletionCondition completion_condition, asio::error_code& ec) { return write(s, basic_streambuf_ref<Allocator>(b), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); } template <typename SyncWriteStream, typename Allocator> @@ -220,7 +217,7 @@ inline std::size_t write(SyncWriteStream& s, CompletionCondition completion_condition) { return write(s, basic_streambuf_ref<Allocator>(b), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + static_cast<CompletionCondition&&>(completion_condition)); } #endif // !defined(ASIO_NO_IOSTREAM) @@ -231,25 +228,25 @@ template <typename SyncWriteStream, typename DynamicBuffer_v2, typename CompletionCondition> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); buffers.consume(bytes_transferred); return bytes_transferred; } template <typename SyncWriteStream, typename DynamicBuffer_v2> inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = write(s, - ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + static_cast<DynamicBuffer_v2&&>(buffers), transfer_all(), ec); asio::detail::throw_error(ec, "write"); return bytes_transferred; @@ -258,11 +255,11 @@ inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, template <typename SyncWriteStream, typename DynamicBuffer_v2> inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { - return write(s, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), + return write(s, static_cast<DynamicBuffer_v2&&>(buffers), transfer_all(), ec); } @@ -270,14 +267,14 @@ template <typename SyncWriteStream, typename DynamicBuffer_v2, typename CompletionCondition> inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) + >) { asio::error_code ec; std::size_t bytes_transferred = write(s, - ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<DynamicBuffer_v2&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition), ec); asio::detail::throw_error(ec, "write"); return bytes_transferred; } @@ -300,11 +297,10 @@ namespace detail stream_(stream), buffers_(buffers), start_(0), - handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + handler_(static_cast<WriteHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) write_op(const write_op& other) : base_from_cancellation_state<WriteHandler>(other), base_from_completion_cond<CompletionCondition>(other), @@ -317,18 +313,15 @@ namespace detail write_op(write_op&& other) : base_from_cancellation_state<WriteHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - WriteHandler>)(other)), + static_cast<base_from_cancellation_state<WriteHandler>&&>(other)), base_from_completion_cond<CompletionCondition>( - ASIO_MOVE_CAST(base_from_completion_cond< - CompletionCondition>)(other)), + static_cast<base_from_completion_cond<CompletionCondition>&&>(other)), stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)), + buffers_(static_cast<buffers_type&&>(other.buffers_)), start_(other.start_), - handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + handler_(static_cast<WriteHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -343,7 +336,7 @@ namespace detail { ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write")); stream_.async_write_some(buffers_.prepare(max_size), - ASIO_MOVE_CAST(write_op)(*this)); + static_cast<write_op&&>(*this)); } return; default: buffers_.consume(bytes_transferred); @@ -359,7 +352,7 @@ namespace detail } } - ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)( + static_cast<WriteHandler&&>(handler_)( static_cast<const asio::error_code&>(ec), static_cast<const std::size_t&>(buffers_.total_consumed())); } @@ -378,38 +371,6 @@ namespace detail template <typename AsyncWriteStream, typename ConstBufferSequence, typename ConstBufferIterator, typename CompletionCondition, typename WriteHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator, - CompletionCondition, WriteHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncWriteStream, typename ConstBufferSequence, - typename ConstBufferIterator, typename CompletionCondition, - typename WriteHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator, - CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncWriteStream, typename ConstBufferSequence, - typename ConstBufferIterator, typename CompletionCondition, - typename WriteHandler> inline bool asio_handler_is_continuation( write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler) @@ -419,40 +380,10 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncWriteStream, - typename ConstBufferSequence, typename ConstBufferIterator, - typename CompletionCondition, typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator, - CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncWriteStream, - typename ConstBufferSequence, typename ConstBufferIterator, - typename CompletionCondition, typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator, - CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncWriteStream, typename ConstBufferSequence, typename ConstBufferIterator, typename CompletionCondition, typename WriteHandler> - inline void start_write_buffer_sequence_op(AsyncWriteStream& stream, + inline void start_write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers, const ConstBufferIterator&, CompletionCondition& completion_condition, WriteHandler& handler) { @@ -463,26 +394,26 @@ namespace detail } template <typename AsyncWriteStream> - class initiate_async_write_buffer_sequence + class initiate_async_write { public: typedef typename AsyncWriteStream::executor_type executor_type; - explicit initiate_async_write_buffer_sequence(AsyncWriteStream& stream) + explicit initiate_async_write(AsyncWriteStream& stream) : stream_(stream) { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename WriteHandler, typename ConstBufferSequence, typename CompletionCondition> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(CompletionCondition) completion_cond) const + CompletionCondition&& completion_cond) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a WriteHandler. @@ -490,7 +421,7 @@ namespace detail non_const_lvalue<WriteHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); - start_write_buffer_sequence_op(stream_, buffers, + start_write_op(stream_, buffers, asio::buffer_sequence_begin(buffers), completion_cond2.value, handler2.value); } @@ -514,8 +445,16 @@ struct associator<Associator, { static typename Associator<WriteHandler, DefaultCandidate>::type get( const detail::write_op<AsyncWriteStream, ConstBufferSequence, + ConstBufferIterator, CompletionCondition, WriteHandler>& h) noexcept + { + return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator, CompletionCondition, WriteHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } @@ -526,38 +465,44 @@ struct associator<Associator, template <typename AsyncWriteStream, typename ConstBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler, - typename constraint< + std::size_t)) WriteToken> +inline auto async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, + CompletionCondition completion_condition, WriteToken&& token, + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type) -{ - return async_initiate<WriteHandler, + >) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write<AsyncWriteStream>>(), + token, buffers, + static_cast<CompletionCondition&&>(completion_condition))) +{ + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s), - handler, buffers, - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + detail::initiate_async_write<AsyncWriteStream>(s), + token, buffers, + static_cast<CompletionCondition&&>(completion_condition)); } template <typename AsyncWriteStream, typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler, - typename constraint< + std::size_t)) WriteToken> +inline auto async_write(AsyncWriteStream& s, + const ConstBufferSequence& buffers, WriteToken&& token, + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type) -{ - return async_initiate<WriteHandler, + >) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write<AsyncWriteStream>>(), + token, buffers, transfer_all())) +{ + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s), - handler, buffers, transfer_all()); + detail::initiate_async_write<AsyncWriteStream>(s), + token, buffers, transfer_all()); } #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -571,17 +516,16 @@ namespace detail public: template <typename BufferSequence> write_dynbuf_v1_op(AsyncWriteStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, + BufferSequence&& buffers, CompletionCondition& completion_condition, WriteHandler& handler) : stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), completion_condition_( - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)), - handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + static_cast<CompletionCondition&&>(completion_condition)), + handler_(static_cast<WriteHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) write_dynbuf_v1_op(const write_dynbuf_v1_op& other) : stream_(other.stream_), buffers_(other.buffers_), @@ -592,14 +536,13 @@ namespace detail write_dynbuf_v1_op(write_dynbuf_v1_op&& other) : stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)), + buffers_(static_cast<DynamicBuffer_v1&&>(other.buffers_)), completion_condition_( - ASIO_MOVE_CAST(CompletionCondition)( + static_cast<CompletionCondition&&>( other.completion_condition_)), - handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + handler_(static_cast<WriteHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(const asio::error_code& ec, std::size_t bytes_transferred, int start = 0) @@ -608,11 +551,11 @@ namespace detail { case 1: async_write(stream_, buffers_.data(), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition_), - ASIO_MOVE_CAST(write_dynbuf_v1_op)(*this)); + static_cast<CompletionCondition&&>(completion_condition_), + static_cast<write_dynbuf_v1_op&&>(*this)); return; default: buffers_.consume(bytes_transferred); - ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, + static_cast<WriteHandler&&>(handler_)(ec, static_cast<const std::size_t&>(bytes_transferred)); } } @@ -626,36 +569,6 @@ namespace detail template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, typename WriteHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, - CompletionCondition, WriteHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncWriteStream, typename DynamicBuffer_v1, - typename CompletionCondition, typename WriteHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, - CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncWriteStream, typename DynamicBuffer_v1, - typename CompletionCondition, typename WriteHandler> inline bool asio_handler_is_continuation( write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, CompletionCondition, WriteHandler>* this_handler) @@ -664,36 +577,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncWriteStream, - typename DynamicBuffer_v1, typename CompletionCondition, - typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, - CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncWriteStream, - typename DynamicBuffer_v1, typename CompletionCondition, - typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, - CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncWriteStream> class initiate_async_write_dynbuf_v1 { @@ -705,16 +588,16 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename WriteHandler, typename DynamicBuffer_v1, typename CompletionCondition> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - ASIO_MOVE_ARG(CompletionCondition) completion_cond) const + void operator()(WriteHandler&& handler, + DynamicBuffer_v1&& buffers, + CompletionCondition&& completion_cond) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a WriteHandler. @@ -723,9 +606,9 @@ namespace detail non_const_lvalue<WriteHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); write_dynbuf_v1_op<AsyncWriteStream, - typename decay<DynamicBuffer_v1>::type, - CompletionCondition, typename decay<WriteHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), + decay_t<DynamicBuffer_v1>, + CompletionCondition, decay_t<WriteHandler>>( + stream_, static_cast<DynamicBuffer_v1&&>(buffers), completion_cond2.value, handler2.value)( asio::error_code(), 0, 1); } @@ -748,9 +631,17 @@ struct associator<Associator, : Associator<WriteHandler, DefaultCandidate> { static typename Associator<WriteHandler, DefaultCandidate>::type get( + const detail::write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, + CompletionCondition, WriteHandler>& h) noexcept + { + return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( const detail::write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1, CompletionCondition, WriteHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } @@ -760,46 +651,53 @@ struct associator<Associator, template <typename AsyncWriteStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - ASIO_MOVE_ARG(WriteHandler) handler, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) -{ - return async_write(s, - ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), - transfer_all(), ASIO_MOVE_CAST(WriteHandler)(handler)); + std::size_t)) WriteToken> +inline auto async_write(AsyncWriteStream& s, + DynamicBuffer_v1&& buffers, WriteToken&& token, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), + transfer_all())) +{ + return async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s), + token, static_cast<DynamicBuffer_v1&&>(buffers), + transfer_all()); } template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type) -{ - return async_initiate<WriteHandler, + std::size_t)) WriteToken> +inline auto async_write(AsyncWriteStream& s, DynamicBuffer_v1&& buffers, + CompletionCondition completion_condition, WriteToken&& token, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + >, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + >) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition))) +{ + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s), - handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + token, static_cast<DynamicBuffer_v1&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition)); } #if !defined(ASIO_NO_EXTENSIONS) @@ -807,31 +705,41 @@ async_write(AsyncWriteStream& s, template <typename AsyncWriteStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, + std::size_t)) WriteToken> +inline auto async_write(AsyncWriteStream& s, asio::basic_streambuf<Allocator>& b, - ASIO_MOVE_ARG(WriteHandler) handler) -{ - return async_write(s, basic_streambuf_ref<Allocator>(b), - ASIO_MOVE_CAST(WriteHandler)(handler)); + WriteToken&& token) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(), + token, basic_streambuf_ref<Allocator>(b), transfer_all())) +{ + return async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s), + token, basic_streambuf_ref<Allocator>(b), transfer_all()); } template <typename AsyncWriteStream, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, + std::size_t)) WriteToken> +inline auto async_write(AsyncWriteStream& s, asio::basic_streambuf<Allocator>& b, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler) -{ - return async_write(s, basic_streambuf_ref<Allocator>(b), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), - ASIO_MOVE_CAST(WriteHandler)(handler)); + CompletionCondition completion_condition, WriteToken&& token) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(), + token, basic_streambuf_ref<Allocator>(b), + static_cast<CompletionCondition&&>(completion_condition))) +{ + return async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s), + token, basic_streambuf_ref<Allocator>(b), + static_cast<CompletionCondition&&>(completion_condition)); } #endif // !defined(ASIO_NO_IOSTREAM) @@ -847,17 +755,16 @@ namespace detail public: template <typename BufferSequence> write_dynbuf_v2_op(AsyncWriteStream& stream, - ASIO_MOVE_ARG(BufferSequence) buffers, + BufferSequence&& buffers, CompletionCondition& completion_condition, WriteHandler& handler) : stream_(stream), - buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)), + buffers_(static_cast<BufferSequence&&>(buffers)), completion_condition_( - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)), - handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + static_cast<CompletionCondition&&>(completion_condition)), + handler_(static_cast<WriteHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) write_dynbuf_v2_op(const write_dynbuf_v2_op& other) : stream_(other.stream_), buffers_(other.buffers_), @@ -868,14 +775,13 @@ namespace detail write_dynbuf_v2_op(write_dynbuf_v2_op&& other) : stream_(other.stream_), - buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)), + buffers_(static_cast<DynamicBuffer_v2&&>(other.buffers_)), completion_condition_( - ASIO_MOVE_CAST(CompletionCondition)( + static_cast<CompletionCondition&&>( other.completion_condition_)), - handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + handler_(static_cast<WriteHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(const asio::error_code& ec, std::size_t bytes_transferred, int start = 0) @@ -884,11 +790,11 @@ namespace detail { case 1: async_write(stream_, buffers_.data(0, buffers_.size()), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition_), - ASIO_MOVE_CAST(write_dynbuf_v2_op)(*this)); + static_cast<CompletionCondition&&>(completion_condition_), + static_cast<write_dynbuf_v2_op&&>(*this)); return; default: buffers_.consume(bytes_transferred); - ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, + static_cast<WriteHandler&&>(handler_)(ec, static_cast<const std::size_t&>(bytes_transferred)); } } @@ -902,36 +808,6 @@ namespace detail template <typename AsyncWriteStream, typename DynamicBuffer_v2, typename CompletionCondition, typename WriteHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, - CompletionCondition, WriteHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncWriteStream, typename DynamicBuffer_v2, - typename CompletionCondition, typename WriteHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, - CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncWriteStream, typename DynamicBuffer_v2, - typename CompletionCondition, typename WriteHandler> inline bool asio_handler_is_continuation( write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, CompletionCondition, WriteHandler>* this_handler) @@ -940,36 +816,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncWriteStream, - typename DynamicBuffer_v2, typename CompletionCondition, - typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, - CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncWriteStream, - typename DynamicBuffer_v2, typename CompletionCondition, - typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, - CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncWriteStream> class initiate_async_write_dynbuf_v2 { @@ -981,16 +827,16 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return stream_.get_executor(); } template <typename WriteHandler, typename DynamicBuffer_v2, typename CompletionCondition> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, - ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, - ASIO_MOVE_ARG(CompletionCondition) completion_cond) const + void operator()(WriteHandler&& handler, + DynamicBuffer_v2&& buffers, + CompletionCondition&& completion_cond) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a WriteHandler. @@ -998,12 +844,11 @@ namespace detail non_const_lvalue<WriteHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); - write_dynbuf_v2_op<AsyncWriteStream, - typename decay<DynamicBuffer_v2>::type, - CompletionCondition, typename decay<WriteHandler>::type>( - stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), - completion_cond2.value, handler2.value)( - asio::error_code(), 0, 1); + write_dynbuf_v2_op<AsyncWriteStream, decay_t<DynamicBuffer_v2>, + CompletionCondition, decay_t<WriteHandler>>( + stream_, static_cast<DynamicBuffer_v2&&>(buffers), + completion_cond2.value, handler2.value)( + asio::error_code(), 0, 1); } private: @@ -1024,34 +869,19 @@ struct associator<Associator, : Associator<WriteHandler, DefaultCandidate> { static typename Associator<WriteHandler, DefaultCandidate>::type get( - const detail::write_dynbuf_v2_op<AsyncWriteStream, - DynamicBuffer_v2, CompletionCondition, WriteHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const detail::write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, + CompletionCondition, WriteHandler>& h) noexcept { - return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); + return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); } -}; -template <typename AsyncWriteStream, typename DynamicBuffer_v2, - typename CompletionCondition, typename WriteHandler, - typename CancellationSlot> -struct associated_cancellation_slot< - detail::write_dynbuf_v2_op<AsyncWriteStream, - DynamicBuffer_v2, CompletionCondition, WriteHandler>, - CancellationSlot> - : detail::associated_cancellation_slot_forwarding_base< - WriteHandler, CancellationSlot> -{ - typedef typename associated_cancellation_slot< - WriteHandler, CancellationSlot>::type type; - - static type get( + static auto get( const detail::write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2, CompletionCondition, WriteHandler>& h, - const CancellationSlot& s = CancellationSlot()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)) { - return associated_cancellation_slot<WriteHandler, - CancellationSlot>::get(h.handler_, s); + return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } }; @@ -1059,38 +889,47 @@ struct associated_cancellation_slot< template <typename AsyncWriteStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, - ASIO_MOVE_ARG(WriteHandler) handler, - typename constraint< + std::size_t)) WriteToken> +inline auto async_write(AsyncWriteStream& s, + DynamicBuffer_v2 buffers, WriteToken&& token, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) -{ - return async_write(s, - ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), - transfer_all(), ASIO_MOVE_CAST(WriteHandler)(handler)); + >) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), + transfer_all())) +{ + return async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s), + token, static_cast<DynamicBuffer_v2&&>(buffers), + transfer_all()); } template <typename AsyncWriteStream, typename DynamicBuffer_v2, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler, - typename constraint< + std::size_t)) WriteToken> +inline auto async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, + CompletionCondition completion_condition, WriteToken&& token, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type) -{ - return async_initiate<WriteHandler, + >) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition))) +{ + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s), - handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + token, static_cast<DynamicBuffer_v2&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition)); } } // namespace asio diff --git a/3rdparty/asio/include/asio/impl/write_at.hpp b/3rdparty/asio/include/asio/impl/write_at.hpp index 87780d552b6..b5a67e30051 100644 --- a/3rdparty/asio/include/asio/impl/write_at.hpp +++ b/3rdparty/asio/include/asio/impl/write_at.hpp @@ -2,7 +2,7 @@ // impl/write_at.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,16 +17,13 @@ #include "asio/associator.hpp" #include "asio/buffer.hpp" -#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp" #include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp" #include "asio/detail/dependent_type.hpp" -#include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" -#include "asio/detail/handler_invoke_helpers.hpp" #include "asio/detail/handler_tracking.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/non_const_lvalue.hpp" @@ -71,7 +68,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, { return detail::write_at_buffer_sequence(d, offset, buffers, asio::buffer_sequence_begin(buffers), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); } template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence> @@ -101,7 +98,7 @@ inline std::size_t write_at(SyncRandomAccessWriteDevice& d, { asio::error_code ec; std::size_t bytes_transferred = write_at(d, offset, buffers, - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); asio::detail::throw_error(ec, "write_at"); return bytes_transferred; } @@ -116,7 +113,7 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, CompletionCondition completion_condition, asio::error_code& ec) { std::size_t bytes_transferred = write_at(d, offset, b.data(), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); b.consume(bytes_transferred); return bytes_transferred; } @@ -147,7 +144,7 @@ inline std::size_t write_at(SyncRandomAccessWriteDevice& d, { asio::error_code ec; std::size_t bytes_transferred = write_at(d, offset, b, - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec); + static_cast<CompletionCondition&&>(completion_condition), ec); asio::detail::throw_error(ec, "write_at"); return bytes_transferred; } @@ -175,11 +172,10 @@ namespace detail offset_(offset), buffers_(buffers), start_(0), - handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + handler_(static_cast<WriteHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) write_at_op(const write_at_op& other) : base_from_cancellation_state<WriteHandler>(other), base_from_completion_cond<CompletionCondition>(other), @@ -193,19 +189,16 @@ namespace detail write_at_op(write_at_op&& other) : base_from_cancellation_state<WriteHandler>( - ASIO_MOVE_CAST(base_from_cancellation_state< - WriteHandler>)(other)), + static_cast<base_from_cancellation_state<WriteHandler>&&>(other)), base_from_completion_cond<CompletionCondition>( - ASIO_MOVE_CAST(base_from_completion_cond< - CompletionCondition>)(other)), + static_cast<base_from_completion_cond<CompletionCondition>&&>(other)), device_(other.device_), offset_(other.offset_), - buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)), + buffers_(static_cast<buffers_type&&>(other.buffers_)), start_(other.start_), - handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + handler_(static_cast<WriteHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred, int start = 0) @@ -221,7 +214,7 @@ namespace detail ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write_at")); device_.async_write_some_at( offset_ + buffers_.total_consumed(), buffers_.prepare(max_size), - ASIO_MOVE_CAST(write_at_op)(*this)); + static_cast<write_at_op&&>(*this)); } return; default: buffers_.consume(bytes_transferred); @@ -237,7 +230,7 @@ namespace detail } } - ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)( + static_cast<WriteHandler&&>(handler_)( static_cast<const asio::error_code&>(ec), static_cast<const std::size_t&>(buffers_.total_consumed())); } @@ -257,38 +250,6 @@ namespace detail template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, typename ConstBufferIterator, typename CompletionCondition, typename WriteHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, - ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncRandomAccessWriteDevice, - typename ConstBufferSequence, typename ConstBufferIterator, - typename CompletionCondition, typename WriteHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, - ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename AsyncRandomAccessWriteDevice, - typename ConstBufferSequence, typename ConstBufferIterator, - typename CompletionCondition, typename WriteHandler> inline bool asio_handler_is_continuation( write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler) @@ -298,40 +259,10 @@ namespace detail this_handler->handler_); } - template <typename Function, typename AsyncRandomAccessWriteDevice, - typename ConstBufferSequence, typename ConstBufferIterator, - typename CompletionCondition, typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, - ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename AsyncRandomAccessWriteDevice, - typename ConstBufferSequence, typename ConstBufferIterator, - typename CompletionCondition, typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, - ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, typename ConstBufferIterator, typename CompletionCondition, typename WriteHandler> - inline void start_write_at_buffer_sequence_op(AsyncRandomAccessWriteDevice& d, + inline void start_write_at_op(AsyncRandomAccessWriteDevice& d, uint64_t offset, const ConstBufferSequence& buffers, const ConstBufferIterator&, CompletionCondition& completion_condition, WriteHandler& handler) @@ -343,27 +274,26 @@ namespace detail } template <typename AsyncRandomAccessWriteDevice> - class initiate_async_write_at_buffer_sequence + class initiate_async_write_at { public: typedef typename AsyncRandomAccessWriteDevice::executor_type executor_type; - explicit initiate_async_write_at_buffer_sequence( - AsyncRandomAccessWriteDevice& device) + explicit initiate_async_write_at(AsyncRandomAccessWriteDevice& device) : device_(device) { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return device_.get_executor(); } template <typename WriteHandler, typename ConstBufferSequence, typename CompletionCondition> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, uint64_t offset, const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(CompletionCondition) completion_cond) const + CompletionCondition&& completion_cond) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a WriteHandler. @@ -371,7 +301,7 @@ namespace detail non_const_lvalue<WriteHandler> handler2(handler); non_const_lvalue<CompletionCondition> completion_cond2(completion_cond); - start_write_at_buffer_sequence_op(device_, offset, buffers, + start_write_at_op(device_, offset, buffers, asio::buffer_sequence_begin(buffers), completion_cond2.value, handler2.value); } @@ -396,8 +326,17 @@ struct associator<Associator, static typename Associator<WriteHandler, DefaultCandidate>::type get( const detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence, ConstBufferIterator, + CompletionCondition, WriteHandler>& h) noexcept + { + return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( + const detail::write_at_op<AsyncRandomAccessWriteDevice, + ConstBufferSequence, ConstBufferIterator, CompletionCondition, WriteHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } @@ -408,36 +347,41 @@ struct associator<Associator, template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write_at(AsyncRandomAccessWriteDevice& d, + std::size_t)) WriteToken> +inline auto async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, const ConstBufferSequence& buffers, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler) + CompletionCondition completion_condition, WriteToken&& token) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_at< + AsyncRandomAccessWriteDevice>>(), + token, offset, buffers, + static_cast<CompletionCondition&&>(completion_condition))) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - detail::initiate_async_write_at_buffer_sequence< - AsyncRandomAccessWriteDevice>(d), - handler, offset, buffers, - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + detail::initiate_async_write_at<AsyncRandomAccessWriteDevice>(d), + token, offset, buffers, + static_cast<CompletionCondition&&>(completion_condition)); } template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write_at(AsyncRandomAccessWriteDevice& d, - uint64_t offset, const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler) + std::size_t)) WriteToken> +inline auto async_write_at(AsyncRandomAccessWriteDevice& d, + uint64_t offset, const ConstBufferSequence& buffers, WriteToken&& token) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_at< + AsyncRandomAccessWriteDevice>>(), + token, offset, buffers, transfer_all())) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - detail::initiate_async_write_at_buffer_sequence< - AsyncRandomAccessWriteDevice>(d), - handler, offset, buffers, transfer_all()); + detail::initiate_async_write_at<AsyncRandomAccessWriteDevice>(d), + token, offset, buffers, transfer_all()); } #if !defined(ASIO_NO_EXTENSIONS) @@ -453,11 +397,10 @@ namespace detail asio::basic_streambuf<Allocator>& streambuf, WriteHandler& handler) : streambuf_(streambuf), - handler_(ASIO_MOVE_CAST(WriteHandler)(handler)) + handler_(static_cast<WriteHandler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) write_at_streambuf_op(const write_at_streambuf_op& other) : streambuf_(other.streambuf_), handler_(other.handler_) @@ -466,16 +409,15 @@ namespace detail write_at_streambuf_op(write_at_streambuf_op&& other) : streambuf_(other.streambuf_), - handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_)) + handler_(static_cast<WriteHandler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(const asio::error_code& ec, const std::size_t bytes_transferred) { streambuf_.consume(bytes_transferred); - ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_transferred); + static_cast<WriteHandler&&>(handler_)(ec, bytes_transferred); } //private: @@ -484,32 +426,6 @@ namespace detail }; template <typename Allocator, typename WriteHandler> - inline asio_handler_allocate_is_deprecated - asio_handler_allocate(std::size_t size, - write_at_streambuf_op<Allocator, WriteHandler>* this_handler) - { -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Allocator, typename WriteHandler> - inline asio_handler_deallocate_is_deprecated - asio_handler_deallocate(void* pointer, std::size_t size, - write_at_streambuf_op<Allocator, WriteHandler>* this_handler) - { - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Allocator, typename WriteHandler> inline bool asio_handler_is_continuation( write_at_streambuf_op<Allocator, WriteHandler>* this_handler) { @@ -517,30 +433,6 @@ namespace detail this_handler->handler_); } - template <typename Function, typename Allocator, typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(Function& function, - write_at_streambuf_op<Allocator, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - - template <typename Function, typename Allocator, typename WriteHandler> - inline asio_handler_invoke_is_deprecated - asio_handler_invoke(const Function& function, - write_at_streambuf_op<Allocator, WriteHandler>* this_handler) - { - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) - } - template <typename AsyncRandomAccessWriteDevice> class initiate_async_write_at_streambuf { @@ -553,16 +445,16 @@ namespace detail { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return device_.get_executor(); } template <typename WriteHandler, typename Allocator, typename CompletionCondition> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, uint64_t offset, basic_streambuf<Allocator>* b, - ASIO_MOVE_ARG(CompletionCondition) completion_condition) const + CompletionCondition&& completion_condition) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a WriteHandler. @@ -570,8 +462,8 @@ namespace detail non_const_lvalue<WriteHandler> handler2(handler); async_write_at(device_, offset, b->data(), - ASIO_MOVE_CAST(CompletionCondition)(completion_condition), - write_at_streambuf_op<Allocator, typename decay<WriteHandler>::type>( + static_cast<CompletionCondition&&>(completion_condition), + write_at_streambuf_op<Allocator, decay_t<WriteHandler>>( *b, handler2.value)); } @@ -590,8 +482,15 @@ struct associator<Associator, : Associator<WriteHandler, DefaultCandidate> { static typename Associator<WriteHandler, DefaultCandidate>::type get( + const detail::write_at_streambuf_op<Executor, WriteHandler>& h) noexcept + { + return Associator<WriteHandler, DefaultCandidate>::get(h.handler_); + } + + static auto get( const detail::write_at_streambuf_op<Executor, WriteHandler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const DefaultCandidate& c) noexcept + -> decltype(Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)) { return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c); } @@ -602,36 +501,44 @@ struct associator<Associator, template <typename AsyncRandomAccessWriteDevice, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write_at(AsyncRandomAccessWriteDevice& d, + std::size_t)) WriteToken> +inline auto async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, asio::basic_streambuf<Allocator>& b, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler) + CompletionCondition completion_condition, WriteToken&& token) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_at_streambuf< + AsyncRandomAccessWriteDevice>>(), + token, offset, &b, + static_cast<CompletionCondition&&>(completion_condition))) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( detail::initiate_async_write_at_streambuf< AsyncRandomAccessWriteDevice>(d), - handler, offset, &b, - ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); + token, offset, &b, + static_cast<CompletionCondition&&>(completion_condition)); } template <typename AsyncRandomAccessWriteDevice, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write_at(AsyncRandomAccessWriteDevice& d, + std::size_t)) WriteToken> +inline auto async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, asio::basic_streambuf<Allocator>& b, - ASIO_MOVE_ARG(WriteHandler) handler) + WriteToken&& token) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_at_streambuf< + AsyncRandomAccessWriteDevice>>(), + token, offset, &b, transfer_all())) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( detail::initiate_async_write_at_streambuf< AsyncRandomAccessWriteDevice>(d), - handler, offset, &b, transfer_all()); + token, offset, &b, transfer_all()); } #endif // !defined(ASIO_NO_IOSTREAM) diff --git a/3rdparty/asio/include/asio/io_context.hpp b/3rdparty/asio/include/asio/io_context.hpp index 7b69418c1b7..5de125685fc 100644 --- a/3rdparty/asio/include/asio/io_context.hpp +++ b/3rdparty/asio/include/asio/io_context.hpp @@ -2,7 +2,7 @@ // io_context.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,15 +20,14 @@ #include <stdexcept> #include <typeinfo> #include "asio/async_result.hpp" +#include "asio/detail/chrono.hpp" +#include "asio/detail/concurrency_hint.hpp" +#include "asio/detail/cstdint.hpp" #include "asio/detail/wrapped_handler.hpp" #include "asio/error_code.hpp" #include "asio/execution.hpp" #include "asio/execution_context.hpp" -#if defined(ASIO_HAS_CHRONO) -# include "asio/detail/chrono.hpp" -#endif // defined(ASIO_HAS_CHRONO) - #if defined(ASIO_WINDOWS) || defined(__CYGWIN__) # include "asio/detail/winsock_init.hpp" #elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \ @@ -56,9 +55,10 @@ namespace detail { struct io_context_bits { - ASIO_STATIC_CONSTEXPR(unsigned int, blocking_never = 1); - ASIO_STATIC_CONSTEXPR(unsigned int, relationship_continuation = 2); - ASIO_STATIC_CONSTEXPR(unsigned int, outstanding_work_tracked = 4); + static constexpr uintptr_t blocking_never = 1; + static constexpr uintptr_t relationship_continuation = 2; + static constexpr uintptr_t outstanding_work_tracked = 4; + static constexpr uintptr_t runtime_bits = 3; }; } // namespace detail @@ -166,30 +166,12 @@ namespace detail { * returning when there is no more work to do. For example, the io_context may * be being run in a background thread that is launched prior to the * application's asynchronous operations. The run() call may be kept running by - * creating an executor that tracks work against the io_context: - * - * @code asio::io_context io_context; - * auto work = asio::require(io_context.get_executor(), - * asio::execution::outstanding_work.tracked); - * ... @endcode - * - * If using C++03, which lacks automatic variable type deduction, you may - * compute the return type of the require call: + * using the @ref make_work_guard function to create an object of type + * asio::executor_work_guard<io_context::executor_type>: * * @code asio::io_context io_context; - * typename asio::require_result< - * asio::io_context::executor_type, - * asio::exeution::outstanding_work_t::tracked_t> - * work = asio::require(io_context.get_executor(), - * asio::execution::outstanding_work.tracked); - * ... @endcode - * - * or store the result in the type-erasing executor wrapper, any_io_executor: - * - * @code asio::io_context io_context; - * asio::any_io_executor work - * = asio::require(io_context.get_executor(), - * asio::execution::outstanding_work.tracked); + * asio::executor_work_guard<asio::io_context::executor_type> + * = asio::make_work_guard(io_context); * ... @endcode * * To effect a shutdown, the application will then need to call the io_context @@ -198,15 +180,13 @@ namespace detail { * permitting ready handlers to be dispatched. * * Alternatively, if the application requires that all operations and handlers - * be allowed to finish normally, store the work-tracking executor in an - * any_io_executor object, so that it may be explicitly reset. + * be allowed to finish normally, the work object may be explicitly reset. * * @code asio::io_context io_context; - * asio::any_io_executor work - * = asio::require(io_context.get_executor(), - * asio::execution::outstanding_work.tracked); + * asio::executor_work_guard<asio::io_context::executor_type> + * = asio::make_work_guard(io_context); * ... - * work = asio::any_io_executor(); // Allow run() to exit. @endcode + * work.reset(); // Allow run() to exit. @endcode */ class io_context : public execution_context @@ -217,11 +197,16 @@ private: friend class detail::win_iocp_overlapped_ptr; #endif +#if !defined(ASIO_NO_DEPRECATED) + struct initiate_dispatch; + struct initiate_post; +#endif // !defined(ASIO_NO_DEPRECATED) + public: - template <typename Allocator, unsigned int Bits> + template <typename Allocator, uintptr_t Bits> class basic_executor_type; - template <typename Allocator, unsigned int Bits> + template <typename Allocator, uintptr_t Bits> friend class basic_executor_type; /// Executor used to submit functions to an io_context. @@ -290,7 +275,7 @@ public: ASIO_DECL ~io_context(); /// Obtains the executor associated with the io_context. - executor_type get_executor() ASIO_NOEXCEPT; + executor_type get_executor() noexcept; /// Run the io_context object's event processing loop. /** @@ -351,7 +336,6 @@ public: ASIO_DECL count_type run(asio::error_code& ec); #endif // !defined(ASIO_NO_DEPRECATED) -#if defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) /// Run the io_context object's event processing loop for a specified /// duration. /** @@ -378,7 +362,6 @@ public: */ template <typename Clock, typename Duration> std::size_t run_until(const chrono::time_point<Clock, Duration>& abs_time); -#endif // defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) /// Run the io_context object's event processing loop to execute at most one /// handler. @@ -400,7 +383,7 @@ public: ASIO_DECL count_type run_one(); #if !defined(ASIO_NO_DEPRECATED) - /// (Deprecated: Use non-error_code overlaod.) Run the io_context object's + /// (Deprecated: Use non-error_code overload.) Run the io_context object's /// event processing loop to execute at most one handler. /** * The run_one() function blocks until one handler has been dispatched, or @@ -422,7 +405,6 @@ public: ASIO_DECL count_type run_one(asio::error_code& ec); #endif // !defined(ASIO_NO_DEPRECATED) -#if defined(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. /** @@ -451,7 +433,6 @@ public: template <typename Clock, typename Duration> std::size_t run_one_until( const chrono::time_point<Clock, Duration>& abs_time); -#endif // defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) /// Run the io_context object's event processing loop to execute ready /// handlers. @@ -566,15 +547,17 @@ public: * * @note This function throws an exception only if: * - * @li the handler's @c asio_handler_allocate function; or + * @li the handler's associated allocator; or * * @li the handler's copy constructor * * throws an exception. */ template <typename LegacyCompletionHandler> - ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ()) - dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler); + auto dispatch(LegacyCompletionHandler&& handler) + -> decltype( + async_initiate<LegacyCompletionHandler, void ()>( + declval<initiate_dispatch>(), handler, this)); /// (Deprecated: Use asio::post().) Request the io_context to invoke /// the given handler and return immediately. @@ -593,15 +576,17 @@ public: * * @note This function throws an exception only if: * - * @li the handler's @c asio_handler_allocate function; or + * @li the handler's associated allocator; or * * @li the handler's copy constructor * * throws an exception. */ template <typename LegacyCompletionHandler> - ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ()) - post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler); + auto post(LegacyCompletionHandler&& handler) + -> decltype( + async_initiate<LegacyCompletionHandler, void ()>( + declval<initiate_post>(), handler, this)); /// (Deprecated: Use asio::bind_executor().) Create a new handler that /// automatically dispatches the wrapped handler on the io_context. @@ -635,13 +620,8 @@ public: #endif // !defined(ASIO_NO_DEPRECATED) private: - io_context(const io_context&) ASIO_DELETED; - io_context& operator=(const io_context&) ASIO_DELETED; - -#if !defined(ASIO_NO_DEPRECATED) - struct initiate_dispatch; - struct initiate_post; -#endif // !defined(ASIO_NO_DEPRECATED) + io_context(const io_context&) = delete; + io_context& operator=(const io_context&) = delete; // Helper function to add the implementation. ASIO_DECL impl_type& add_impl(impl_type* impl); @@ -662,56 +642,44 @@ private: impl_type& impl_; }; -namespace detail { - -} // namespace detail - /// Executor implementation type used to submit functions to an io_context. -template <typename Allocator, unsigned int Bits> -class io_context::basic_executor_type : detail::io_context_bits +template <typename Allocator, uintptr_t Bits> +class io_context::basic_executor_type : + detail::io_context_bits, Allocator { public: /// Copy constructor. - basic_executor_type( - const basic_executor_type& other) ASIO_NOEXCEPT - : io_context_(other.io_context_), - allocator_(other.allocator_), - bits_(other.bits_) + basic_executor_type(const basic_executor_type& other) noexcept + : Allocator(static_cast<const Allocator&>(other)), + target_(other.target_) { if (Bits & outstanding_work_tracked) - if (io_context_) - io_context_->impl_.work_started(); + if (context_ptr()) + context_ptr()->impl_.work_started(); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. - basic_executor_type(basic_executor_type&& other) ASIO_NOEXCEPT - : io_context_(other.io_context_), - allocator_(ASIO_MOVE_CAST(Allocator)(other.allocator_)), - bits_(other.bits_) + basic_executor_type(basic_executor_type&& other) noexcept + : Allocator(static_cast<Allocator&&>(other)), + target_(other.target_) { if (Bits & outstanding_work_tracked) - other.io_context_ = 0; + other.target_ = 0; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destructor. - ~basic_executor_type() ASIO_NOEXCEPT + ~basic_executor_type() noexcept { if (Bits & outstanding_work_tracked) - if (io_context_) - io_context_->impl_.work_finished(); + if (context_ptr()) + context_ptr()->impl_.work_finished(); } /// Assignment operator. - basic_executor_type& operator=( - const basic_executor_type& other) ASIO_NOEXCEPT; + basic_executor_type& operator=(const basic_executor_type& other) noexcept; -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move assignment operator. - basic_executor_type& operator=( - basic_executor_type&& other) ASIO_NOEXCEPT; -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + basic_executor_type& operator=(basic_executor_type&& other) noexcept; #if !defined(GENERATING_DOCUMENTATION) private: @@ -729,11 +697,10 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::blocking.possibly); @endcode */ - ASIO_CONSTEXPR basic_executor_type require( - execution::blocking_t::possibly_t) const + constexpr basic_executor_type require(execution::blocking_t::possibly_t) const { - return basic_executor_type(io_context_, - allocator_, bits_ & ~blocking_never); + return basic_executor_type(context_ptr(), + *this, bits() & ~blocking_never); } /// Obtain an executor with the @c blocking.never property. @@ -746,11 +713,10 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::blocking.never); @endcode */ - ASIO_CONSTEXPR basic_executor_type require( - execution::blocking_t::never_t) const + constexpr basic_executor_type require(execution::blocking_t::never_t) const { - return basic_executor_type(io_context_, - allocator_, bits_ | blocking_never); + return basic_executor_type(context_ptr(), + *this, bits() | blocking_never); } /// Obtain an executor with the @c relationship.fork property. @@ -763,11 +729,10 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::relationship.fork); @endcode */ - ASIO_CONSTEXPR basic_executor_type require( - execution::relationship_t::fork_t) const + constexpr basic_executor_type require(execution::relationship_t::fork_t) const { - return basic_executor_type(io_context_, - allocator_, bits_ & ~relationship_continuation); + return basic_executor_type(context_ptr(), + *this, bits() & ~relationship_continuation); } /// Obtain an executor with the @c relationship.continuation property. @@ -780,11 +745,11 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::relationship.continuation); @endcode */ - ASIO_CONSTEXPR basic_executor_type require( + constexpr basic_executor_type require( execution::relationship_t::continuation_t) const { - return basic_executor_type(io_context_, - allocator_, bits_ | relationship_continuation); + return basic_executor_type(context_ptr(), + *this, bits() | relationship_continuation); } /// Obtain an executor with the @c outstanding_work.tracked property. @@ -797,12 +762,12 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::outstanding_work.tracked); @endcode */ - ASIO_CONSTEXPR basic_executor_type<Allocator, + constexpr basic_executor_type<Allocator, ASIO_UNSPECIFIED(Bits | outstanding_work_tracked)> require(execution::outstanding_work_t::tracked_t) const { return basic_executor_type<Allocator, Bits | outstanding_work_tracked>( - io_context_, allocator_, bits_); + context_ptr(), *this, bits()); } /// Obtain an executor with the @c outstanding_work.untracked property. @@ -815,12 +780,12 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::outstanding_work.untracked); @endcode */ - ASIO_CONSTEXPR basic_executor_type<Allocator, + constexpr basic_executor_type<Allocator, ASIO_UNSPECIFIED(Bits & ~outstanding_work_tracked)> require(execution::outstanding_work_t::untracked_t) const { return basic_executor_type<Allocator, Bits & ~outstanding_work_tracked>( - io_context_, allocator_, bits_); + context_ptr(), *this, bits()); } /// Obtain an executor with the specified @c allocator property. @@ -834,11 +799,11 @@ private: * asio::execution::allocator(my_allocator)); @endcode */ template <typename OtherAllocator> - ASIO_CONSTEXPR basic_executor_type<OtherAllocator, Bits> + constexpr basic_executor_type<OtherAllocator, Bits> require(execution::allocator_t<OtherAllocator> a) const { return basic_executor_type<OtherAllocator, Bits>( - io_context_, a.value(), bits_); + context_ptr(), a.value(), bits()); } /// Obtain an executor with the default @c allocator property. @@ -851,11 +816,11 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::allocator); @endcode */ - ASIO_CONSTEXPR basic_executor_type<std::allocator<void>, Bits> + constexpr basic_executor_type<std::allocator<void>, Bits> require(execution::allocator_t<void>) const { return basic_executor_type<std::allocator<void>, Bits>( - io_context_, std::allocator<void>(), bits_); + context_ptr(), std::allocator<void>(), bits()); } #if !defined(GENERATING_DOCUMENTATION) @@ -876,8 +841,7 @@ private: * == asio::execution::mapping.thread) * ... @endcode */ - static ASIO_CONSTEXPR execution::mapping_t query( - execution::mapping_t) ASIO_NOEXCEPT + static constexpr execution::mapping_t query(execution::mapping_t) noexcept { return execution::mapping.thread; } @@ -892,9 +856,9 @@ private: * asio::io_context& ctx = asio::query( * ex, asio::execution::context); @endcode */ - io_context& query(execution::context_t) const ASIO_NOEXCEPT + io_context& query(execution::context_t) const noexcept { - return *io_context_; + return *context_ptr(); } /// Query the current value of the @c blocking property. @@ -908,10 +872,9 @@ private: * == asio::execution::blocking.always) * ... @endcode */ - ASIO_CONSTEXPR execution::blocking_t query( - execution::blocking_t) const ASIO_NOEXCEPT + constexpr execution::blocking_t query(execution::blocking_t) const noexcept { - return (bits_ & blocking_never) + return (bits() & blocking_never) ? execution::blocking_t(execution::blocking.never) : execution::blocking_t(execution::blocking.possibly); } @@ -927,10 +890,10 @@ private: * == asio::execution::relationship.continuation) * ... @endcode */ - ASIO_CONSTEXPR execution::relationship_t query( - execution::relationship_t) const ASIO_NOEXCEPT + constexpr execution::relationship_t query( + execution::relationship_t) const noexcept { - return (bits_ & relationship_continuation) + return (bits() & relationship_continuation) ? execution::relationship_t(execution::relationship.continuation) : execution::relationship_t(execution::relationship.fork); } @@ -946,8 +909,8 @@ private: * == asio::execution::outstanding_work.tracked) * ... @endcode */ - static ASIO_CONSTEXPR execution::outstanding_work_t query( - execution::outstanding_work_t) ASIO_NOEXCEPT + static constexpr execution::outstanding_work_t query( + execution::outstanding_work_t) noexcept { return (Bits & outstanding_work_tracked) ? execution::outstanding_work_t(execution::outstanding_work.tracked) @@ -965,10 +928,10 @@ private: * asio::execution::allocator); @endcode */ template <typename OtherAllocator> - ASIO_CONSTEXPR Allocator query( - execution::allocator_t<OtherAllocator>) const ASIO_NOEXCEPT + constexpr Allocator query( + execution::allocator_t<OtherAllocator>) const noexcept { - return allocator_; + return static_cast<const Allocator&>(*this); } /// Query the current value of the @c allocator property. @@ -981,10 +944,9 @@ private: * auto alloc = asio::query(ex, * asio::execution::allocator); @endcode */ - ASIO_CONSTEXPR Allocator query( - execution::allocator_t<void>) const ASIO_NOEXCEPT + constexpr Allocator query(execution::allocator_t<void>) const noexcept { - return allocator_; + return static_cast<const Allocator&>(*this); } public: @@ -993,18 +955,17 @@ public: * @return @c true if the current thread is running the io_context. Otherwise * returns @c false. */ - bool running_in_this_thread() const ASIO_NOEXCEPT; + bool running_in_this_thread() const noexcept; /// Compare two executors for equality. /** * Two executors are equal if they refer to the same underlying io_context. */ friend bool operator==(const basic_executor_type& a, - const basic_executor_type& b) ASIO_NOEXCEPT + const basic_executor_type& b) noexcept { - return a.io_context_ == b.io_context_ - && a.allocator_ == b.allocator_ - && a.bits_ == b.bits_; + return a.target_ == b.target_ + && static_cast<const Allocator&>(a) == static_cast<const Allocator&>(b); } /// Compare two executors for inequality. @@ -1012,34 +973,20 @@ public: * Two executors are equal if they refer to the same underlying io_context. */ friend bool operator!=(const basic_executor_type& a, - const basic_executor_type& b) ASIO_NOEXCEPT + const basic_executor_type& b) noexcept { - return a.io_context_ != b.io_context_ - || a.allocator_ != b.allocator_ - || a.bits_ != b.bits_; + return a.target_ != b.target_ + || static_cast<const Allocator&>(a) != static_cast<const Allocator&>(b); } -#if !defined(GENERATING_DOCUMENTATION) -private: - friend struct asio_execution_execute_fn::impl; -#endif // !defined(GENERATING_DOCUMENTATION) - /// Execution function. - /** - * Do not call this function directly. It is intended for use with the - * execution::execute customisation point. - * - * For example: - * @code auto ex = my_io_context.get_executor(); - * execution::execute(ex, my_function_object); @endcode - */ template <typename Function> - void execute(ASIO_MOVE_ARG(Function) f) const; + void execute(Function&& f) const; #if !defined(ASIO_NO_TS_EXECUTORS) public: /// Obtain the underlying execution context. - io_context& context() const ASIO_NOEXCEPT; + io_context& context() const noexcept; /// Inform the io_context that it has some outstanding work to do. /** @@ -1047,7 +994,7 @@ public: * 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 ASIO_NOEXCEPT; + void on_work_started() const noexcept; /// Inform the io_context that some work is no longer outstanding. /** @@ -1055,7 +1002,7 @@ public: * 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 ASIO_NOEXCEPT; + void on_work_finished() const noexcept; /// Request the io_context to invoke the given function object. /** @@ -1072,8 +1019,7 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename OtherAllocator> - void dispatch(ASIO_MOVE_ARG(Function) f, - const OtherAllocator& a) const; + void dispatch(Function&& f, const OtherAllocator& a) const; /// Request the io_context to invoke the given function object. /** @@ -1089,8 +1035,7 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename OtherAllocator> - void post(ASIO_MOVE_ARG(Function) f, - const OtherAllocator& a) const; + void post(Function&& f, const OtherAllocator& a) const; /// Request the io_context to invoke the given function object. /** @@ -1110,44 +1055,45 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename OtherAllocator> - void defer(ASIO_MOVE_ARG(Function) f, - const OtherAllocator& a) const; + void defer(Function&& f, const OtherAllocator& a) const; #endif // !defined(ASIO_NO_TS_EXECUTORS) private: friend class io_context; - template <typename, unsigned int> friend class basic_executor_type; + template <typename, uintptr_t> friend class basic_executor_type; // Constructor used by io_context::get_executor(). - explicit basic_executor_type(io_context& i) ASIO_NOEXCEPT - : io_context_(&i), - allocator_(), - bits_(0) + explicit basic_executor_type(io_context& i) noexcept + : Allocator(), + target_(reinterpret_cast<uintptr_t>(&i)) { if (Bits & outstanding_work_tracked) - io_context_->impl_.work_started(); + context_ptr()->impl_.work_started(); } // Constructor used by require(). basic_executor_type(io_context* i, - const Allocator& a, unsigned int bits) ASIO_NOEXCEPT - : io_context_(i), - allocator_(a), - bits_(bits) + const Allocator& a, uintptr_t bits) noexcept + : Allocator(a), + target_(reinterpret_cast<uintptr_t>(i) | bits) { if (Bits & outstanding_work_tracked) - if (io_context_) - io_context_->impl_.work_started(); + if (context_ptr()) + context_ptr()->impl_.work_started(); } - // The underlying io_context. - io_context* io_context_; + io_context* context_ptr() const noexcept + { + return reinterpret_cast<io_context*>(target_ & ~runtime_bits); + } - // The allocator used for execution functions. - Allocator allocator_; + uintptr_t bits() const noexcept + { + return target_ & runtime_bits; + } - // The runtime-switched properties of the io_context executor. - unsigned int bits_; + // The underlying io_context and runtime bits. + uintptr_t target_; }; #if !defined(ASIO_NO_DEPRECATED) @@ -1278,27 +1224,27 @@ namespace traits { #if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> struct equality_comparable< asio::io_context::basic_executor_type<Allocator, Bits> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; }; #endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) #if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits, typename Function> +template <typename Allocator, uintptr_t Bits, typename Function> struct execute_member< asio::io_context::basic_executor_type<Allocator, Bits>, Function > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef void result_type; }; @@ -1306,99 +1252,99 @@ struct execute_member< #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::blocking_t::possibly_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::io_context::basic_executor_type< Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::blocking_t::never_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::io_context::basic_executor_type< Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::relationship_t::fork_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::io_context::basic_executor_type< Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::relationship_t::continuation_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::io_context::basic_executor_type< Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::outstanding_work_t::tracked_t > : asio::detail::io_context_bits { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::io_context::basic_executor_type< Allocator, Bits | outstanding_work_tracked> result_type; }; -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::outstanding_work_t::untracked_t > : asio::detail::io_context_bits { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::io_context::basic_executor_type< Allocator, Bits & ~outstanding_work_tracked> result_type; }; -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::allocator_t<void> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::io_context::basic_executor_type< std::allocator<void>, Bits> result_type; }; -template <unsigned int Bits, +template <uintptr_t Bits, typename Allocator, typename OtherAllocator> struct require_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::allocator_t<OtherAllocator> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::io_context::basic_executor_type< OtherAllocator, Bits> result_type; }; @@ -1407,7 +1353,7 @@ struct require_member< #if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits, typename Property> +template <typename Allocator, uintptr_t Bits, typename Property> struct query_static_constexpr_member< asio::io_context::basic_executor_type<Allocator, Bits>, Property, @@ -1419,11 +1365,11 @@ struct query_static_constexpr_member< >::type > : asio::detail::io_context_bits { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::execution::outstanding_work_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return (Bits & outstanding_work_tracked) ? execution::outstanding_work_t(execution::outstanding_work.tracked) @@ -1431,7 +1377,7 @@ struct query_static_constexpr_member< } }; -template <typename Allocator, unsigned int Bits, typename Property> +template <typename Allocator, uintptr_t Bits, typename Property> struct query_static_constexpr_member< asio::io_context::basic_executor_type<Allocator, Bits>, Property, @@ -1443,11 +1389,11 @@ struct query_static_constexpr_member< >::type > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::execution::mapping_t::thread_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return result_type(); } @@ -1457,7 +1403,7 @@ struct query_static_constexpr_member< #if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits, typename Property> +template <typename Allocator, uintptr_t Bits, typename Property> struct query_member< asio::io_context::basic_executor_type<Allocator, Bits>, Property, @@ -1469,12 +1415,12 @@ struct query_member< >::type > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::execution::blocking_t result_type; }; -template <typename Allocator, unsigned int Bits, typename Property> +template <typename Allocator, uintptr_t Bits, typename Property> struct query_member< asio::io_context::basic_executor_type<Allocator, Bits>, Property, @@ -1486,41 +1432,41 @@ struct query_member< >::type > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::execution::relationship_t result_type; }; -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> struct query_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::context_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::io_context& result_type; }; -template <typename Allocator, unsigned int Bits> +template <typename Allocator, uintptr_t Bits> struct query_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::allocator_t<void> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef Allocator result_type; }; -template <typename Allocator, unsigned int Bits, typename OtherAllocator> +template <typename Allocator, uintptr_t Bits, typename OtherAllocator> struct query_member< asio::io_context::basic_executor_type<Allocator, Bits>, asio::execution::allocator_t<OtherAllocator> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef Allocator result_type; }; @@ -1528,6 +1474,15 @@ struct query_member< } // namespace traits +namespace execution { + +template <> +struct is_executor<io_context> : false_type +{ +}; + +} // namespace execution + #endif // !defined(GENERATING_DOCUMENTATION) } // namespace asio diff --git a/3rdparty/asio/include/asio/io_context_strand.hpp b/3rdparty/asio/include/asio/io_context_strand.hpp index 8cd17cfbfc5..288ac238feb 100644 --- a/3rdparty/asio/include/asio/io_context_strand.hpp +++ b/3rdparty/asio/include/asio/io_context_strand.hpp @@ -2,7 +2,7 @@ // io_context_strand.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -64,8 +64,7 @@ namespace asio { * @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). + * then @c a() happens-before @c b() * * Note that in the following case: * @code async_op_1(..., s.wrap(a)); @@ -88,6 +87,12 @@ namespace asio { */ class io_context::strand { +private: +#if !defined(ASIO_NO_DEPRECATED) + struct initiate_dispatch; + struct initiate_post; +#endif // !defined(ASIO_NO_DEPRECATED) + public: /// Constructor. /** @@ -103,6 +108,17 @@ public: service_.construct(impl_); } + /// Copy constructor. + /** + * Creates a copy such that both strand objects share the same underlying + * state. + */ + strand(const strand& other) noexcept + : service_(other.service_), + impl_(other.impl_) + { + } + /// Destructor. /** * Destroys a strand. @@ -115,7 +131,7 @@ public: } /// Obtain the underlying execution context. - asio::io_context& context() const ASIO_NOEXCEPT + asio::io_context& context() const noexcept { return service_.get_io_context(); } @@ -124,7 +140,7 @@ public: /** * The strand delegates this call to its underlying io_context. */ - void on_work_started() const ASIO_NOEXCEPT + void on_work_started() const noexcept { context().get_executor().on_work_started(); } @@ -133,7 +149,7 @@ public: /** * The strand delegates this call to its underlying io_context. */ - void on_work_finished() const ASIO_NOEXCEPT + void on_work_finished() const noexcept { context().get_executor().on_work_finished(); } @@ -154,9 +170,9 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename Allocator> - void dispatch(ASIO_MOVE_ARG(Function) f, const Allocator& a) const + void dispatch(Function&& f, const Allocator& a) const { - typename decay<Function>::type tmp(ASIO_MOVE_CAST(Function)(f)); + decay_t<Function> tmp(static_cast<Function&&>(f)); service_.dispatch(impl_, tmp); (void)a; } @@ -183,8 +199,10 @@ public: * @code void handler(); @endcode */ template <typename LegacyCompletionHandler> - ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ()) - dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler) + auto dispatch(LegacyCompletionHandler&& handler) + -> decltype( + async_initiate<LegacyCompletionHandler, void ()>( + declval<initiate_dispatch>(), handler, this)) { return async_initiate<LegacyCompletionHandler, void ()>( initiate_dispatch(), handler, this); @@ -205,9 +223,9 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename Allocator> - void post(ASIO_MOVE_ARG(Function) f, const Allocator& a) const + void post(Function&& f, const Allocator& a) const { - typename decay<Function>::type tmp(ASIO_MOVE_CAST(Function)(f)); + decay_t<Function> tmp(static_cast<Function&&>(f)); service_.post(impl_, tmp); (void)a; } @@ -230,8 +248,10 @@ public: * @code void handler(); @endcode */ template <typename LegacyCompletionHandler> - ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ()) - post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler) + auto post(LegacyCompletionHandler&& handler) + -> decltype( + async_initiate<LegacyCompletionHandler, void ()>( + declval<initiate_post>(), handler, this)) { return async_initiate<LegacyCompletionHandler, void ()>( initiate_post(), handler, this); @@ -252,9 +272,9 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename Allocator> - void defer(ASIO_MOVE_ARG(Function) f, const Allocator& a) const + void defer(Function&& f, const Allocator& a) const { - typename decay<Function>::type tmp(ASIO_MOVE_CAST(Function)(f)); + decay_t<Function> tmp(static_cast<Function&&>(f)); service_.post(impl_, tmp); (void)a; } @@ -300,7 +320,7 @@ public: * submitted to the strand using post(), dispatch() or wrap(). Otherwise * returns @c false. */ - bool running_in_this_thread() const ASIO_NOEXCEPT + bool running_in_this_thread() const noexcept { return service_.running_in_this_thread(impl_); } @@ -310,7 +330,7 @@ public: * Two strands are equal if they refer to the same ordered, non-concurrent * state. */ - friend bool operator==(const strand& a, const strand& b) ASIO_NOEXCEPT + friend bool operator==(const strand& a, const strand& b) noexcept { return a.impl_ == b.impl_; } @@ -320,7 +340,7 @@ public: * Two strands are equal if they refer to the same ordered, non-concurrent * state. */ - friend bool operator!=(const strand& a, const strand& b) ASIO_NOEXCEPT + friend bool operator!=(const strand& a, const strand& b) noexcept { return a.impl_ != b.impl_; } @@ -330,7 +350,7 @@ private: struct initiate_dispatch { template <typename LegacyCompletionHandler> - void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler, + void operator()(LegacyCompletionHandler&& handler, strand* self) const { // If you get an error on the following line it means that your @@ -347,7 +367,7 @@ private: struct initiate_post { template <typename LegacyCompletionHandler> - void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler, + void operator()(LegacyCompletionHandler&& handler, strand* self) const { // If you get an error on the following line it means that your diff --git a/3rdparty/asio/include/asio/io_service.hpp b/3rdparty/asio/include/asio/io_service.hpp index 7290ad159c5..748d8a6a323 100644 --- a/3rdparty/asio/include/asio/io_service.hpp +++ b/3rdparty/asio/include/asio/io_service.hpp @@ -2,7 +2,7 @@ // io_service.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/io_service_strand.hpp b/3rdparty/asio/include/asio/io_service_strand.hpp index 46756a3106a..65bb8db2dd3 100644 --- a/3rdparty/asio/include/asio/io_service_strand.hpp +++ b/3rdparty/asio/include/asio/io_service_strand.hpp @@ -2,7 +2,7 @@ // io_service_strand.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/address.hpp b/3rdparty/asio/include/asio/ip/address.hpp index 1b26c384df5..337abe7fd69 100644 --- a/3rdparty/asio/include/asio/ip/address.hpp +++ b/3rdparty/asio/include/asio/ip/address.hpp @@ -2,7 +2,7 @@ // ip/address.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" +#include <functional> #include <string> #include "asio/detail/throw_exception.hpp" #include "asio/detail/string_view.hpp" @@ -25,10 +26,6 @@ #include "asio/ip/address_v6.hpp" #include "asio/ip/bad_address_cast.hpp" -#if defined(ASIO_HAS_STD_HASH) -# include <functional> -#endif // defined(ASIO_HAS_STD_HASH) - #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM) @@ -51,48 +48,44 @@ class address { public: /// Default constructor. - ASIO_DECL address() ASIO_NOEXCEPT; + ASIO_DECL address() noexcept; /// Construct an address from an IPv4 address. ASIO_DECL address( - const asio::ip::address_v4& ipv4_address) ASIO_NOEXCEPT; + const asio::ip::address_v4& ipv4_address) noexcept; /// Construct an address from an IPv6 address. ASIO_DECL address( - const asio::ip::address_v6& ipv6_address) ASIO_NOEXCEPT; + const asio::ip::address_v6& ipv6_address) noexcept; /// Copy constructor. - ASIO_DECL address(const address& other) ASIO_NOEXCEPT; + ASIO_DECL address(const address& other) noexcept; -#if defined(ASIO_HAS_MOVE) /// Move constructor. - ASIO_DECL address(address&& other) ASIO_NOEXCEPT; -#endif // defined(ASIO_HAS_MOVE) + ASIO_DECL address(address&& other) noexcept; /// Assign from another address. - ASIO_DECL address& operator=(const address& other) ASIO_NOEXCEPT; + ASIO_DECL address& operator=(const address& other) noexcept; -#if defined(ASIO_HAS_MOVE) /// Move-assign from another address. - ASIO_DECL address& operator=(address&& other) ASIO_NOEXCEPT; -#endif // defined(ASIO_HAS_MOVE) + ASIO_DECL address& operator=(address&& other) noexcept; /// Assign from an IPv4 address. ASIO_DECL address& operator=( - const asio::ip::address_v4& ipv4_address) ASIO_NOEXCEPT; + const asio::ip::address_v4& ipv4_address) noexcept; /// Assign from an IPv6 address. ASIO_DECL address& operator=( - const asio::ip::address_v6& ipv6_address) ASIO_NOEXCEPT; + const asio::ip::address_v6& ipv6_address) noexcept; /// Get whether the address is an IP version 4 address. - bool is_v4() const ASIO_NOEXCEPT + bool is_v4() const noexcept { return type_ == ipv4; } /// Get whether the address is an IP version 6 address. - bool is_v6() const ASIO_NOEXCEPT + bool is_v6() const noexcept { return type_ == ipv6; } @@ -133,46 +126,46 @@ public: #endif // !defined(ASIO_NO_DEPRECATED) /// Determine whether the address is a loopback address. - ASIO_DECL bool is_loopback() const ASIO_NOEXCEPT; + ASIO_DECL bool is_loopback() const noexcept; /// Determine whether the address is unspecified. - ASIO_DECL bool is_unspecified() const ASIO_NOEXCEPT; + ASIO_DECL bool is_unspecified() const noexcept; /// Determine whether the address is a multicast address. - ASIO_DECL bool is_multicast() const ASIO_NOEXCEPT; + ASIO_DECL bool is_multicast() const noexcept; /// Compare two addresses for equality. ASIO_DECL friend bool operator==(const address& a1, - const address& a2) ASIO_NOEXCEPT; + const address& a2) noexcept; /// Compare two addresses for inequality. friend bool operator!=(const address& a1, - const address& a2) ASIO_NOEXCEPT + const address& a2) noexcept { return !(a1 == a2); } /// Compare addresses for ordering. ASIO_DECL friend bool operator<(const address& a1, - const address& a2) ASIO_NOEXCEPT; + const address& a2) noexcept; /// Compare addresses for ordering. friend bool operator>(const address& a1, - const address& a2) ASIO_NOEXCEPT + const address& a2) noexcept { return a2 < a1; } /// Compare addresses for ordering. friend bool operator<=(const address& a1, - const address& a2) ASIO_NOEXCEPT + const address& a2) noexcept { return !(a2 < a1); } /// Compare addresses for ordering. friend bool operator>=(const address& a1, - const address& a2) ASIO_NOEXCEPT + const address& a2) noexcept { return !(a1 < a2); } @@ -201,7 +194,7 @@ ASIO_DECL address make_address(const char* str); * @relates address */ ASIO_DECL address make_address(const char* str, - asio::error_code& ec) ASIO_NOEXCEPT; + asio::error_code& ec) noexcept; /// Create an address from an IPv4 address string in dotted decimal form, /// or from an IPv6 address in hexadecimal notation. @@ -216,7 +209,7 @@ ASIO_DECL address make_address(const std::string& str); * @relates address */ ASIO_DECL address make_address(const std::string& str, - asio::error_code& ec) ASIO_NOEXCEPT; + asio::error_code& ec) noexcept; #if defined(ASIO_HAS_STRING_VIEW) \ || defined(GENERATING_DOCUMENTATION) @@ -234,7 +227,7 @@ ASIO_DECL address make_address(string_view str); * @relates address */ ASIO_DECL address make_address(string_view str, - asio::error_code& ec) ASIO_NOEXCEPT; + asio::error_code& ec) noexcept; #endif // defined(ASIO_HAS_STRING_VIEW) // || defined(GENERATING_DOCUMENTATION) @@ -262,14 +255,13 @@ std::basic_ostream<Elem, Traits>& operator<<( } // namespace ip } // namespace asio -#if defined(ASIO_HAS_STD_HASH) namespace std { template <> struct hash<asio::ip::address> { std::size_t operator()(const asio::ip::address& addr) - const ASIO_NOEXCEPT + const noexcept { return addr.is_v4() ? std::hash<asio::ip::address_v4>()(addr.to_v4()) @@ -278,7 +270,6 @@ struct hash<asio::ip::address> }; } // namespace std -#endif // defined(ASIO_HAS_STD_HASH) #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/ip/address_v4.hpp b/3rdparty/asio/include/asio/ip/address_v4.hpp index 8babd025d45..ccef6c80cda 100644 --- a/3rdparty/asio/include/asio/ip/address_v4.hpp +++ b/3rdparty/asio/include/asio/ip/address_v4.hpp @@ -2,7 +2,7 @@ // ip/address_v4.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" +#include <functional> #include <string> #include "asio/detail/array.hpp" #include "asio/detail/cstdint.hpp" @@ -24,10 +25,6 @@ #include "asio/detail/winsock_init.hpp" #include "asio/error_code.hpp" -#if defined(ASIO_HAS_STD_HASH) -# include <functional> -#endif // defined(ASIO_HAS_STD_HASH) - #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM) @@ -64,55 +61,68 @@ public: #endif /// Default constructor. - address_v4() ASIO_NOEXCEPT + /** + * Initialises the @c address_v4 object such that: + * @li <tt>to_bytes()</tt> yields <tt>{0, 0, 0, 0}</tt>; and + * @li <tt>to_uint() == 0</tt>. + */ + address_v4() noexcept { addr_.s_addr = 0; } /// Construct an address from raw bytes. + /** + * Initialises the @c address_v4 object such that <tt>to_bytes() == + * bytes</tt>. + * + * @throws out_of_range Thrown if any element in @c bytes is not in the range + * <tt>0 - 0xFF</tt>. Note that no range checking is required for platforms + * where <tt>std::numeric_limits<unsigned char>::max()</tt> is <tt>0xFF</tt>. + */ ASIO_DECL explicit address_v4(const bytes_type& bytes); /// Construct an address from an unsigned integer in host byte order. + /** + * Initialises the @c address_v4 object such that <tt>to_uint() == addr</tt>. + */ ASIO_DECL explicit address_v4(uint_type addr); /// Copy constructor. - address_v4(const address_v4& other) ASIO_NOEXCEPT + address_v4(const address_v4& other) noexcept : addr_(other.addr_) { } -#if defined(ASIO_HAS_MOVE) /// Move constructor. - address_v4(address_v4&& other) ASIO_NOEXCEPT + address_v4(address_v4&& other) noexcept : addr_(other.addr_) { } -#endif // defined(ASIO_HAS_MOVE) /// Assign from another address. - address_v4& operator=(const address_v4& other) ASIO_NOEXCEPT + address_v4& operator=(const address_v4& other) noexcept { addr_ = other.addr_; return *this; } -#if defined(ASIO_HAS_MOVE) /// Move-assign from another address. - address_v4& operator=(address_v4&& other) ASIO_NOEXCEPT + address_v4& operator=(address_v4&& other) noexcept { addr_ = other.addr_; return *this; } -#endif // defined(ASIO_HAS_MOVE) /// Get the address in bytes, in network byte order. - ASIO_DECL bytes_type to_bytes() const ASIO_NOEXCEPT; + ASIO_DECL bytes_type to_bytes() const noexcept; - /// Get the address as an unsigned integer in host byte order - ASIO_DECL uint_type to_uint() const ASIO_NOEXCEPT; + /// Get the address as an unsigned integer in host byte order. + ASIO_DECL uint_type to_uint() const noexcept; #if !defined(ASIO_NO_DEPRECATED) - /// Get the address as an unsigned long in host byte order + /// (Deprecated: Use to_uint().) Get the address as an unsigned long in host + /// byte order. ASIO_DECL unsigned long to_ulong() const; #endif // !defined(ASIO_NO_DEPRECATED) @@ -144,10 +154,23 @@ public: #endif // !defined(ASIO_NO_DEPRECATED) /// Determine whether the address is a loopback address. - ASIO_DECL bool is_loopback() const ASIO_NOEXCEPT; + /** + * This function tests whether the address is in the address block + * <tt>127.0.0.0/8</tt>, which corresponds to the address range + * <tt>127.0.0.0 - 127.255.255.255</tt>. + * + * @returns <tt>(to_uint() & 0xFF000000) == 0x7F000000</tt>. + */ + ASIO_DECL bool is_loopback() const noexcept; /// Determine whether the address is unspecified. - ASIO_DECL bool is_unspecified() const ASIO_NOEXCEPT; + /** + * This function tests whether the address is the unspecified address + * <tt>0.0.0.0</tt>. + * + * @returns <tt>to_uint() == 0</tt>. + */ + ASIO_DECL bool is_unspecified() const noexcept; #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use network_v4 class.) Determine whether the address is a @@ -164,64 +187,109 @@ public: #endif // !defined(ASIO_NO_DEPRECATED) /// Determine whether the address is a multicast address. - ASIO_DECL bool is_multicast() const ASIO_NOEXCEPT; + /** + * This function tests whether the address is in the multicast address block + * <tt>224.0.0.0/4</tt>, which corresponds to the address range + * <tt>224.0.0.0 - 239.255.255.255</tt>. + * + * @returns <tt>(to_uint() & 0xF0000000) == 0xE0000000</tt>. + */ + ASIO_DECL bool is_multicast() const noexcept; /// Compare two addresses for equality. friend bool operator==(const address_v4& a1, - const address_v4& a2) ASIO_NOEXCEPT + const address_v4& a2) noexcept { return a1.addr_.s_addr == a2.addr_.s_addr; } /// Compare two addresses for inequality. friend bool operator!=(const address_v4& a1, - const address_v4& a2) ASIO_NOEXCEPT + const address_v4& a2) noexcept { return a1.addr_.s_addr != a2.addr_.s_addr; } /// Compare addresses for ordering. + /** + * Compares two addresses in host byte order. + * + * @returns <tt>a1.to_uint() < a2.to_uint()</tt>. + */ friend bool operator<(const address_v4& a1, - const address_v4& a2) ASIO_NOEXCEPT + const address_v4& a2) noexcept { return a1.to_uint() < a2.to_uint(); } /// Compare addresses for ordering. + /** + * Compares two addresses in host byte order. + * + * @returns <tt>a1.to_uint() > a2.to_uint()</tt>. + */ friend bool operator>(const address_v4& a1, - const address_v4& a2) ASIO_NOEXCEPT + const address_v4& a2) noexcept { return a1.to_uint() > a2.to_uint(); } /// Compare addresses for ordering. + /** + * Compares two addresses in host byte order. + * + * @returns <tt>a1.to_uint() <= a2.to_uint()</tt>. + */ friend bool operator<=(const address_v4& a1, - const address_v4& a2) ASIO_NOEXCEPT + const address_v4& a2) noexcept { return a1.to_uint() <= a2.to_uint(); } /// Compare addresses for ordering. + /** + * Compares two addresses in host byte order. + * + * @returns <tt>a1.to_uint() >= a2.to_uint()</tt>. + */ friend bool operator>=(const address_v4& a1, - const address_v4& a2) ASIO_NOEXCEPT + const address_v4& a2) noexcept { return a1.to_uint() >= a2.to_uint(); } /// Obtain an address object that represents any address. - static address_v4 any() ASIO_NOEXCEPT + /** + * This functions returns an address that represents the "any" address + * <tt>0.0.0.0</tt>. + * + * @returns A default-constructed @c address_v4 object. + */ + static address_v4 any() noexcept { return address_v4(); } /// Obtain an address object that represents the loopback address. - static address_v4 loopback() ASIO_NOEXCEPT + /** + * This function returns an address that represents the well-known loopback + * address <tt>127.0.0.1</tt>. + * + * @returns <tt>address_v4(0x7F000001)</tt>. + */ + static address_v4 loopback() noexcept { return address_v4(0x7F000001); } /// Obtain an address object that represents the broadcast address. - static address_v4 broadcast() ASIO_NOEXCEPT + /** + * This function returns an address that represents the broadcast address + * <tt>255.255.255.255</tt>. + * + * @returns <tt>address_v4(0xFFFFFFFF)</tt>. + */ + static address_v4 broadcast() noexcept { return address_v4(0xFFFFFFFF); } @@ -272,7 +340,7 @@ ASIO_DECL address_v4 make_address_v4(const char* str); * @relates address_v4 */ ASIO_DECL address_v4 make_address_v4(const char* str, - asio::error_code& ec) ASIO_NOEXCEPT; + asio::error_code& ec) noexcept; /// Create an IPv4 address from an IP address string in dotted decimal form. /** @@ -285,7 +353,7 @@ ASIO_DECL address_v4 make_address_v4(const std::string& str); * @relates address_v4 */ ASIO_DECL address_v4 make_address_v4(const std::string& str, - asio::error_code& ec) ASIO_NOEXCEPT; + asio::error_code& ec) noexcept; #if defined(ASIO_HAS_STRING_VIEW) \ || defined(GENERATING_DOCUMENTATION) @@ -301,7 +369,7 @@ ASIO_DECL address_v4 make_address_v4(string_view str); * @relates address_v4 */ ASIO_DECL address_v4 make_address_v4(string_view str, - asio::error_code& ec) ASIO_NOEXCEPT; + asio::error_code& ec) noexcept; #endif // defined(ASIO_HAS_STRING_VIEW) // || defined(GENERATING_DOCUMENTATION) @@ -329,21 +397,19 @@ std::basic_ostream<Elem, Traits>& operator<<( } // namespace ip } // namespace asio -#if defined(ASIO_HAS_STD_HASH) namespace std { template <> struct hash<asio::ip::address_v4> { std::size_t operator()(const asio::ip::address_v4& addr) - const ASIO_NOEXCEPT + const noexcept { return std::hash<unsigned int>()(addr.to_uint()); } }; } // namespace std -#endif // defined(ASIO_HAS_STD_HASH) #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/ip/address_v4_iterator.hpp b/3rdparty/asio/include/asio/ip/address_v4_iterator.hpp index 1216956f156..5b91f400ac1 100644 --- a/3rdparty/asio/include/asio/ip/address_v4_iterator.hpp +++ b/3rdparty/asio/include/asio/ip/address_v4_iterator.hpp @@ -2,7 +2,7 @@ // ip/address_v4_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -53,65 +53,59 @@ public: typedef std::input_iterator_tag iterator_category; /// Construct an iterator that points to the specified address. - basic_address_iterator(const address_v4& addr) ASIO_NOEXCEPT + basic_address_iterator(const address_v4& addr) noexcept : address_(addr) { } /// Copy constructor. - basic_address_iterator( - const basic_address_iterator& other) ASIO_NOEXCEPT + basic_address_iterator(const basic_address_iterator& other) noexcept : address_(other.address_) { } -#if defined(ASIO_HAS_MOVE) /// Move constructor. - basic_address_iterator(basic_address_iterator&& other) ASIO_NOEXCEPT - : address_(ASIO_MOVE_CAST(address_v4)(other.address_)) + basic_address_iterator(basic_address_iterator&& other) noexcept + : address_(static_cast<address_v4&&>(other.address_)) { } -#endif // defined(ASIO_HAS_MOVE) /// Assignment operator. basic_address_iterator& operator=( - const basic_address_iterator& other) ASIO_NOEXCEPT + const basic_address_iterator& other) noexcept { address_ = other.address_; return *this; } -#if defined(ASIO_HAS_MOVE) /// Move assignment operator. - basic_address_iterator& operator=( - basic_address_iterator&& other) ASIO_NOEXCEPT + basic_address_iterator& operator=(basic_address_iterator&& other) noexcept { - address_ = ASIO_MOVE_CAST(address_v4)(other.address_); + address_ = static_cast<address_v4&&>(other.address_); return *this; } -#endif // defined(ASIO_HAS_MOVE) /// Dereference the iterator. - const address_v4& operator*() const ASIO_NOEXCEPT + const address_v4& operator*() const noexcept { return address_; } /// Dereference the iterator. - const address_v4* operator->() const ASIO_NOEXCEPT + const address_v4* operator->() const noexcept { return &address_; } /// Pre-increment operator. - basic_address_iterator& operator++() ASIO_NOEXCEPT + basic_address_iterator& operator++() noexcept { address_ = address_v4((address_.to_uint() + 1) & 0xFFFFFFFF); return *this; } /// Post-increment operator. - basic_address_iterator operator++(int) ASIO_NOEXCEPT + basic_address_iterator operator++(int) noexcept { basic_address_iterator tmp(*this); ++*this; @@ -119,7 +113,7 @@ public: } /// Pre-decrement operator. - basic_address_iterator& operator--() ASIO_NOEXCEPT + basic_address_iterator& operator--() noexcept { address_ = address_v4((address_.to_uint() - 1) & 0xFFFFFFFF); return *this; diff --git a/3rdparty/asio/include/asio/ip/address_v4_range.hpp b/3rdparty/asio/include/asio/ip/address_v4_range.hpp index 45a1d158902..5fb5e65e2aa 100644 --- a/3rdparty/asio/include/asio/ip/address_v4_range.hpp +++ b/3rdparty/asio/include/asio/ip/address_v4_range.hpp @@ -2,7 +2,7 @@ // ip/address_v4_range.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -38,7 +38,7 @@ public: typedef basic_address_iterator<address_v4> iterator; /// Construct an empty range. - basic_address_range() ASIO_NOEXCEPT + basic_address_range() noexcept : begin_(address_v4()), end_(address_v4()) { @@ -46,74 +46,68 @@ public: /// Construct an range that represents the given range of addresses. explicit basic_address_range(const iterator& first, - const iterator& last) ASIO_NOEXCEPT + const iterator& last) noexcept : begin_(first), end_(last) { } /// Copy constructor. - basic_address_range(const basic_address_range& other) ASIO_NOEXCEPT + basic_address_range(const basic_address_range& other) noexcept : begin_(other.begin_), end_(other.end_) { } -#if defined(ASIO_HAS_MOVE) /// Move constructor. - basic_address_range(basic_address_range&& other) ASIO_NOEXCEPT - : begin_(ASIO_MOVE_CAST(iterator)(other.begin_)), - end_(ASIO_MOVE_CAST(iterator)(other.end_)) + basic_address_range(basic_address_range&& other) noexcept + : begin_(static_cast<iterator&&>(other.begin_)), + end_(static_cast<iterator&&>(other.end_)) { } -#endif // defined(ASIO_HAS_MOVE) /// Assignment operator. - basic_address_range& operator=( - const basic_address_range& other) ASIO_NOEXCEPT + basic_address_range& operator=(const basic_address_range& other) noexcept { begin_ = other.begin_; end_ = other.end_; return *this; } -#if defined(ASIO_HAS_MOVE) /// Move assignment operator. - basic_address_range& operator=( - basic_address_range&& other) ASIO_NOEXCEPT + basic_address_range& operator=(basic_address_range&& other) noexcept { - begin_ = ASIO_MOVE_CAST(iterator)(other.begin_); - end_ = ASIO_MOVE_CAST(iterator)(other.end_); + begin_ = static_cast<iterator&&>(other.begin_); + end_ = static_cast<iterator&&>(other.end_); return *this; } -#endif // defined(ASIO_HAS_MOVE) /// Obtain an iterator that points to the start of the range. - iterator begin() const ASIO_NOEXCEPT + iterator begin() const noexcept { return begin_; } /// Obtain an iterator that points to the end of the range. - iterator end() const ASIO_NOEXCEPT + iterator end() const noexcept { return end_; } /// Determine whether the range is empty. - bool empty() const ASIO_NOEXCEPT + bool empty() const noexcept { return size() == 0; } /// Return the size of the range. - std::size_t size() const ASIO_NOEXCEPT + std::size_t size() const noexcept { return end_->to_uint() - begin_->to_uint(); } /// Find an address in the range. - iterator find(const address_v4& addr) const ASIO_NOEXCEPT + iterator find(const address_v4& addr) const noexcept { return addr >= *begin_ && addr < *end_ ? iterator(addr) : end_; } diff --git a/3rdparty/asio/include/asio/ip/address_v6.hpp b/3rdparty/asio/include/asio/ip/address_v6.hpp index 3d4070f1030..aa650825cf3 100644 --- a/3rdparty/asio/include/asio/ip/address_v6.hpp +++ b/3rdparty/asio/include/asio/ip/address_v6.hpp @@ -2,7 +2,7 @@ // ip/address_v6.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" +#include <functional> #include <string> #include "asio/detail/array.hpp" #include "asio/detail/cstdint.hpp" @@ -25,10 +26,6 @@ #include "asio/error_code.hpp" #include "asio/ip/address_v4.hpp" -#if defined(ASIO_HAS_STD_HASH) -# include <functional> -#endif // defined(ASIO_HAS_STD_HASH) - #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM) @@ -67,34 +64,44 @@ public: #endif /// Default constructor. - ASIO_DECL address_v6() ASIO_NOEXCEPT; + /** + * Initialises the @c address_v6 object such that: + * @li <tt>to_bytes()</tt> yields <tt>{0, 0, ..., 0}</tt>; and + * @li <tt>scope_id() == 0</tt>. + */ + ASIO_DECL address_v6() noexcept; /// Construct an address from raw bytes and scope ID. + /** + * Initialises the @c address_v6 object such that: + * @li <tt>to_bytes() == bytes</tt>; and + * @li <tt>this->scope_id() == scope_id</tt>. + * + * @throws out_of_range Thrown if any element in @c bytes is not in the range + * <tt>0 - 0xFF</tt>. Note that no range checking is required for platforms + * where <tt>std::numeric_limits<unsigned char>::max()</tt> is <tt>0xFF</tt>. + */ ASIO_DECL explicit address_v6(const bytes_type& bytes, scope_id_type scope_id = 0); /// Copy constructor. - ASIO_DECL address_v6(const address_v6& other) ASIO_NOEXCEPT; + ASIO_DECL address_v6(const address_v6& other) noexcept; -#if defined(ASIO_HAS_MOVE) /// Move constructor. - ASIO_DECL address_v6(address_v6&& other) ASIO_NOEXCEPT; -#endif // defined(ASIO_HAS_MOVE) + ASIO_DECL address_v6(address_v6&& other) noexcept; /// Assign from another address. ASIO_DECL address_v6& operator=( - const address_v6& other) ASIO_NOEXCEPT; + const address_v6& other) noexcept; -#if defined(ASIO_HAS_MOVE) /// Move-assign from another address. - ASIO_DECL address_v6& operator=(address_v6&& other) ASIO_NOEXCEPT; -#endif // defined(ASIO_HAS_MOVE) + ASIO_DECL address_v6& operator=(address_v6&& other) noexcept; /// The scope ID of the address. /** * Returns the scope ID associated with the IPv6 address. */ - scope_id_type scope_id() const ASIO_NOEXCEPT + scope_id_type scope_id() const noexcept { return scope_id_; } @@ -102,14 +109,16 @@ public: /// The scope ID of the address. /** * Modifies the scope ID associated with the IPv6 address. + * + * @param id The new scope ID. */ - void scope_id(scope_id_type id) ASIO_NOEXCEPT + void scope_id(scope_id_type id) noexcept { scope_id_ = id; } /// Get the address in bytes, in network byte order. - ASIO_DECL bytes_type to_bytes() const ASIO_NOEXCEPT; + ASIO_DECL bytes_type to_bytes() const noexcept; /// Get the address as a string. ASIO_DECL std::string to_string() const; @@ -142,19 +151,27 @@ public: #endif // !defined(ASIO_NO_DEPRECATED) /// Determine whether the address is a loopback address. - ASIO_DECL bool is_loopback() const ASIO_NOEXCEPT; + /** + * This function tests whether the address is the loopback address + * <tt>::1</tt>. + */ + ASIO_DECL bool is_loopback() const noexcept; /// Determine whether the address is unspecified. - ASIO_DECL bool is_unspecified() const ASIO_NOEXCEPT; + /** + * This function tests whether the address is the loopback address + * <tt>::</tt>. + */ + ASIO_DECL bool is_unspecified() const noexcept; /// Determine whether the address is link local. - ASIO_DECL bool is_link_local() const ASIO_NOEXCEPT; + ASIO_DECL bool is_link_local() const noexcept; /// Determine whether the address is site local. - ASIO_DECL bool is_site_local() const ASIO_NOEXCEPT; + ASIO_DECL bool is_site_local() const noexcept; /// Determine whether the address is a mapped IPv4 address. - ASIO_DECL bool is_v4_mapped() const ASIO_NOEXCEPT; + ASIO_DECL bool is_v4_mapped() const noexcept; #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: No replacement.) Determine whether the address is an @@ -163,67 +180,77 @@ public: #endif // !defined(ASIO_NO_DEPRECATED) /// Determine whether the address is a multicast address. - ASIO_DECL bool is_multicast() const ASIO_NOEXCEPT; + ASIO_DECL bool is_multicast() const noexcept; /// Determine whether the address is a global multicast address. - ASIO_DECL bool is_multicast_global() const ASIO_NOEXCEPT; + ASIO_DECL bool is_multicast_global() const noexcept; /// Determine whether the address is a link-local multicast address. - ASIO_DECL bool is_multicast_link_local() const ASIO_NOEXCEPT; + ASIO_DECL bool is_multicast_link_local() const noexcept; /// Determine whether the address is a node-local multicast address. - ASIO_DECL bool is_multicast_node_local() const ASIO_NOEXCEPT; + ASIO_DECL bool is_multicast_node_local() const noexcept; /// Determine whether the address is a org-local multicast address. - ASIO_DECL bool is_multicast_org_local() const ASIO_NOEXCEPT; + ASIO_DECL bool is_multicast_org_local() const noexcept; /// Determine whether the address is a site-local multicast address. - ASIO_DECL bool is_multicast_site_local() const ASIO_NOEXCEPT; + ASIO_DECL bool is_multicast_site_local() const noexcept; /// Compare two addresses for equality. ASIO_DECL friend bool operator==(const address_v6& a1, - const address_v6& a2) ASIO_NOEXCEPT; + const address_v6& a2) noexcept; /// Compare two addresses for inequality. friend bool operator!=(const address_v6& a1, - const address_v6& a2) ASIO_NOEXCEPT + const address_v6& a2) noexcept { return !(a1 == a2); } /// Compare addresses for ordering. ASIO_DECL friend bool operator<(const address_v6& a1, - const address_v6& a2) ASIO_NOEXCEPT; + const address_v6& a2) noexcept; /// Compare addresses for ordering. friend bool operator>(const address_v6& a1, - const address_v6& a2) ASIO_NOEXCEPT + const address_v6& a2) noexcept { return a2 < a1; } /// Compare addresses for ordering. friend bool operator<=(const address_v6& a1, - const address_v6& a2) ASIO_NOEXCEPT + const address_v6& a2) noexcept { return !(a2 < a1); } /// Compare addresses for ordering. friend bool operator>=(const address_v6& a1, - const address_v6& a2) ASIO_NOEXCEPT + const address_v6& a2) noexcept { return !(a1 < a2); } /// Obtain an address object that represents any address. - static address_v6 any() ASIO_NOEXCEPT + /** + * This functions returns an address that represents the "any" address + * <tt>::</tt>. + * + * @returns A default-constructed @c address_v6 object. + */ + static address_v6 any() noexcept { return address_v6(); } /// Obtain an address object that represents the loopback address. - ASIO_DECL static address_v6 loopback() ASIO_NOEXCEPT; + /** + * This function returns an address that represents the well-known loopback + * address <tt>::1</tt>. + */ + ASIO_DECL static address_v6 loopback() noexcept; #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use make_address_v6().) Create an IPv4-mapped IPv6 address. @@ -264,7 +291,7 @@ ASIO_DECL address_v6 make_address_v6(const char* str); * @relates address_v6 */ ASIO_DECL address_v6 make_address_v6(const char* str, - asio::error_code& ec) ASIO_NOEXCEPT; + asio::error_code& ec) noexcept; /// Createan IPv6 address from an IP address string. /** @@ -277,7 +304,7 @@ ASIO_DECL address_v6 make_address_v6(const std::string& str); * @relates address_v6 */ ASIO_DECL address_v6 make_address_v6(const std::string& str, - asio::error_code& ec) ASIO_NOEXCEPT; + asio::error_code& ec) noexcept; #if defined(ASIO_HAS_STRING_VIEW) \ || defined(GENERATING_DOCUMENTATION) @@ -293,7 +320,7 @@ ASIO_DECL address_v6 make_address_v6(string_view str); * @relates address_v6 */ ASIO_DECL address_v6 make_address_v6(string_view str, - asio::error_code& ec) ASIO_NOEXCEPT; + asio::error_code& ec) noexcept; #endif // defined(ASIO_HAS_STRING_VIEW) // || defined(GENERATING_DOCUMENTATION) @@ -339,14 +366,13 @@ std::basic_ostream<Elem, Traits>& operator<<( } // namespace ip } // namespace asio -#if defined(ASIO_HAS_STD_HASH) namespace std { template <> struct hash<asio::ip::address_v6> { std::size_t operator()(const asio::ip::address_v6& addr) - const ASIO_NOEXCEPT + const noexcept { const asio::ip::address_v6::bytes_type bytes = addr.to_bytes(); std::size_t result = static_cast<std::size_t>(addr.scope_id()); @@ -370,7 +396,6 @@ private: }; } // namespace std -#endif // defined(ASIO_HAS_STD_HASH) #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/ip/address_v6_iterator.hpp b/3rdparty/asio/include/asio/ip/address_v6_iterator.hpp index 5345d206cf5..5116f614f08 100644 --- a/3rdparty/asio/include/asio/ip/address_v6_iterator.hpp +++ b/3rdparty/asio/include/asio/ip/address_v6_iterator.hpp @@ -2,7 +2,7 @@ // ip/address_v6_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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 @@ -54,58 +54,53 @@ public: typedef std::input_iterator_tag iterator_category; /// Construct an iterator that points to the specified address. - basic_address_iterator(const address_v6& addr) ASIO_NOEXCEPT + basic_address_iterator(const address_v6& addr) noexcept : address_(addr) { } /// Copy constructor. basic_address_iterator( - const basic_address_iterator& other) ASIO_NOEXCEPT + const basic_address_iterator& other) noexcept : address_(other.address_) { } -#if defined(ASIO_HAS_MOVE) /// Move constructor. - basic_address_iterator(basic_address_iterator&& other) ASIO_NOEXCEPT - : address_(ASIO_MOVE_CAST(address_v6)(other.address_)) + basic_address_iterator(basic_address_iterator&& other) noexcept + : address_(static_cast<address_v6&&>(other.address_)) { } -#endif // defined(ASIO_HAS_MOVE) /// Assignment operator. basic_address_iterator& operator=( - const basic_address_iterator& other) ASIO_NOEXCEPT + const basic_address_iterator& other) noexcept { address_ = other.address_; return *this; } -#if defined(ASIO_HAS_MOVE) /// Move assignment operator. - basic_address_iterator& operator=( - basic_address_iterator&& other) ASIO_NOEXCEPT + basic_address_iterator& operator=(basic_address_iterator&& other) noexcept { - address_ = ASIO_MOVE_CAST(address_v6)(other.address_); + address_ = static_cast<address_v6&&>(other.address_); return *this; } -#endif // defined(ASIO_HAS_MOVE) /// Dereference the iterator. - const address_v6& operator*() const ASIO_NOEXCEPT + const address_v6& operator*() const noexcept { return address_; } /// Dereference the iterator. - const address_v6* operator->() const ASIO_NOEXCEPT + const address_v6* operator->() const noexcept { return &address_; } /// Pre-increment operator. - basic_address_iterator& operator++() ASIO_NOEXCEPT + basic_address_iterator& operator++() noexcept { for (int i = 15; i >= 0; --i) { @@ -122,7 +117,7 @@ public: } /// Post-increment operator. - basic_address_iterator operator++(int) ASIO_NOEXCEPT + basic_address_iterator operator++(int) noexcept { basic_address_iterator tmp(*this); ++*this; @@ -130,7 +125,7 @@ public: } /// Pre-decrement operator. - basic_address_iterator& operator--() ASIO_NOEXCEPT + basic_address_iterator& operator--() noexcept { for (int i = 15; i >= 0; --i) { diff --git a/3rdparty/asio/include/asio/ip/address_v6_range.hpp b/3rdparty/asio/include/asio/ip/address_v6_range.hpp index ecd9d7cd5a6..7f89773383d 100644 --- a/3rdparty/asio/include/asio/ip/address_v6_range.hpp +++ b/3rdparty/asio/include/asio/ip/address_v6_range.hpp @@ -2,7 +2,7 @@ // ip/address_v6_range.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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 @@ -39,7 +39,7 @@ public: typedef basic_address_iterator<address_v6> iterator; /// Construct an empty range. - basic_address_range() ASIO_NOEXCEPT + basic_address_range() noexcept : begin_(address_v6()), end_(address_v6()) { @@ -47,68 +47,63 @@ public: /// Construct an range that represents the given range of addresses. explicit basic_address_range(const iterator& first, - const iterator& last) ASIO_NOEXCEPT + const iterator& last) noexcept : begin_(first), end_(last) { } /// Copy constructor. - basic_address_range(const basic_address_range& other) ASIO_NOEXCEPT + basic_address_range(const basic_address_range& other) noexcept : begin_(other.begin_), end_(other.end_) { } -#if defined(ASIO_HAS_MOVE) /// Move constructor. - basic_address_range(basic_address_range&& other) ASIO_NOEXCEPT - : begin_(ASIO_MOVE_CAST(iterator)(other.begin_)), - end_(ASIO_MOVE_CAST(iterator)(other.end_)) + basic_address_range(basic_address_range&& other) noexcept + : begin_(static_cast<iterator&&>(other.begin_)), + end_(static_cast<iterator&&>(other.end_)) { } -#endif // defined(ASIO_HAS_MOVE) /// Assignment operator. basic_address_range& operator=( - const basic_address_range& other) ASIO_NOEXCEPT + const basic_address_range& other) noexcept { begin_ = other.begin_; end_ = other.end_; return *this; } -#if defined(ASIO_HAS_MOVE) /// Move assignment operator. - basic_address_range& operator=( - basic_address_range&& other) ASIO_NOEXCEPT + basic_address_range& operator=(basic_address_range&& other) noexcept { - begin_ = ASIO_MOVE_CAST(iterator)(other.begin_); - end_ = ASIO_MOVE_CAST(iterator)(other.end_); + begin_ = static_cast<iterator&&>(other.begin_); + end_ = static_cast<iterator&&>(other.end_); return *this; } -#endif // defined(ASIO_HAS_MOVE) /// Obtain an iterator that points to the start of the range. - iterator begin() const ASIO_NOEXCEPT + iterator begin() const noexcept { return begin_; } /// Obtain an iterator that points to the end of the range. - iterator end() const ASIO_NOEXCEPT + iterator end() const noexcept { return end_; } /// Determine whether the range is empty. - bool empty() const ASIO_NOEXCEPT + bool empty() const noexcept { return begin_ == end_; } /// Find an address in the range. - iterator find(const address_v6& addr) const ASIO_NOEXCEPT + iterator find(const address_v6& addr) const noexcept { return addr >= *begin_ && addr < *end_ ? iterator(addr) : end_; } diff --git a/3rdparty/asio/include/asio/ip/bad_address_cast.hpp b/3rdparty/asio/include/asio/ip/bad_address_cast.hpp index 105c350718d..3d242f07048 100644 --- a/3rdparty/asio/include/asio/ip/bad_address_cast.hpp +++ b/3rdparty/asio/include/asio/ip/bad_address_cast.hpp @@ -2,7 +2,7 @@ // ip/bad_address_cast.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -35,11 +35,21 @@ public: /// Default constructor. bad_address_cast() {} + /// Copy constructor. + bad_address_cast(const bad_address_cast& other) noexcept +#if defined(ASIO_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS + : std::exception(static_cast<const std::exception&>(other)) +#else + : std::bad_cast(static_cast<const std::bad_cast&>(other)) +#endif + { + } + /// Destructor. - virtual ~bad_address_cast() ASIO_NOEXCEPT_OR_NOTHROW {} + virtual ~bad_address_cast() noexcept {} /// Get the message associated with the exception. - virtual const char* what() const ASIO_NOEXCEPT_OR_NOTHROW + virtual const char* what() const noexcept { return "bad address cast"; } diff --git a/3rdparty/asio/include/asio/ip/basic_endpoint.hpp b/3rdparty/asio/include/asio/ip/basic_endpoint.hpp index 10596702bb7..3dfb1248db7 100644 --- a/3rdparty/asio/include/asio/ip/basic_endpoint.hpp +++ b/3rdparty/asio/include/asio/ip/basic_endpoint.hpp @@ -2,7 +2,7 @@ // ip/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,14 +16,11 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" +#include <functional> #include "asio/detail/cstdint.hpp" #include "asio/ip/address.hpp" #include "asio/ip/detail/endpoint.hpp" -#if defined(ASIO_HAS_STD_HASH) -# include <functional> -#endif // defined(ASIO_HAS_STD_HASH) - #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM) @@ -64,7 +61,7 @@ public: #endif /// Default constructor. - basic_endpoint() ASIO_NOEXCEPT + basic_endpoint() noexcept : impl_() { } @@ -86,7 +83,7 @@ public: * @endcode */ basic_endpoint(const InternetProtocol& internet_protocol, - port_type port_num) ASIO_NOEXCEPT + port_type port_num) noexcept : impl_(internet_protocol.family(), port_num) { } @@ -95,43 +92,39 @@ public: /// constructor may be used for accepting connections on a specific interface /// or for making a connection to a remote endpoint. basic_endpoint(const asio::ip::address& addr, - port_type port_num) ASIO_NOEXCEPT + port_type port_num) noexcept : impl_(addr, port_num) { } /// Copy constructor. - basic_endpoint(const basic_endpoint& other) ASIO_NOEXCEPT + basic_endpoint(const basic_endpoint& other) noexcept : impl_(other.impl_) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. - basic_endpoint(basic_endpoint&& other) ASIO_NOEXCEPT + basic_endpoint(basic_endpoint&& other) noexcept : impl_(other.impl_) { } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Assign from another endpoint. - basic_endpoint& operator=(const basic_endpoint& other) ASIO_NOEXCEPT + basic_endpoint& operator=(const basic_endpoint& other) noexcept { impl_ = other.impl_; return *this; } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-assign from another endpoint. - basic_endpoint& operator=(basic_endpoint&& other) ASIO_NOEXCEPT + basic_endpoint& operator=(basic_endpoint&& other) noexcept { impl_ = other.impl_; return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// The protocol associated with the endpoint. - protocol_type protocol() const ASIO_NOEXCEPT + protocol_type protocol() const noexcept { if (impl_.is_v4()) return InternetProtocol::v4(); @@ -139,19 +132,19 @@ public: } /// Get the underlying endpoint in the native type. - data_type* data() ASIO_NOEXCEPT + data_type* data() noexcept { return impl_.data(); } /// Get the underlying endpoint in the native type. - const data_type* data() const ASIO_NOEXCEPT + const data_type* data() const noexcept { return impl_.data(); } /// Get the underlying size of the endpoint in the native type. - std::size_t size() const ASIO_NOEXCEPT + std::size_t size() const noexcept { return impl_.size(); } @@ -163,75 +156,75 @@ public: } /// Get the capacity of the endpoint in the native type. - std::size_t capacity() const ASIO_NOEXCEPT + std::size_t capacity() const noexcept { return impl_.capacity(); } /// Get the port associated with the endpoint. The port number is always in /// the host's byte order. - port_type port() const ASIO_NOEXCEPT + port_type port() const noexcept { return impl_.port(); } /// Set the port associated with the endpoint. The port number is always in /// the host's byte order. - void port(port_type port_num) ASIO_NOEXCEPT + void port(port_type port_num) noexcept { impl_.port(port_num); } /// Get the IP address associated with the endpoint. - asio::ip::address address() const ASIO_NOEXCEPT + asio::ip::address address() const noexcept { return impl_.address(); } /// Set the IP address associated with the endpoint. - void address(const asio::ip::address& addr) ASIO_NOEXCEPT + void address(const asio::ip::address& addr) noexcept { impl_.address(addr); } /// Compare two endpoints for equality. friend bool operator==(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT + const basic_endpoint<InternetProtocol>& e2) noexcept { return e1.impl_ == e2.impl_; } /// Compare two endpoints for inequality. friend bool operator!=(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT + const basic_endpoint<InternetProtocol>& e2) noexcept { return !(e1 == e2); } /// Compare endpoints for ordering. friend bool operator<(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT + const basic_endpoint<InternetProtocol>& e2) noexcept { return e1.impl_ < e2.impl_; } /// Compare endpoints for ordering. friend bool operator>(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT + const basic_endpoint<InternetProtocol>& e2) noexcept { return e2.impl_ < e1.impl_; } /// Compare endpoints for ordering. friend bool operator<=(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT + const basic_endpoint<InternetProtocol>& e2) noexcept { return !(e2 < e1); } /// Compare endpoints for ordering. friend bool operator>=(const basic_endpoint<InternetProtocol>& e1, - const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT + const basic_endpoint<InternetProtocol>& e2) noexcept { return !(e1 < e2); } @@ -265,15 +258,14 @@ std::basic_ostream<Elem, Traits>& operator<<( } // namespace ip } // namespace asio -#if defined(ASIO_HAS_STD_HASH) namespace std { template <typename InternetProtocol> -struct hash<asio::ip::basic_endpoint<InternetProtocol> > +struct hash<asio::ip::basic_endpoint<InternetProtocol>> { std::size_t operator()( const asio::ip::basic_endpoint<InternetProtocol>& ep) - const ASIO_NOEXCEPT + const noexcept { std::size_t hash1 = std::hash<asio::ip::address>()(ep.address()); std::size_t hash2 = std::hash<unsigned short>()(ep.port()); @@ -282,7 +274,6 @@ struct hash<asio::ip::basic_endpoint<InternetProtocol> > }; } // namespace std -#endif // defined(ASIO_HAS_STD_HASH) #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/ip/basic_resolver.hpp b/3rdparty/asio/include/asio/ip/basic_resolver.hpp index cfadba4af9d..4d41bfde090 100644 --- a/3rdparty/asio/include/asio/ip/basic_resolver.hpp +++ b/3rdparty/asio/include/asio/ip/basic_resolver.hpp @@ -2,7 +2,7 @@ // ip/basic_resolver.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,6 +17,7 @@ #include "asio/detail/config.hpp" #include <string> +#include <utility> #include "asio/any_io_executor.hpp" #include "asio/async_result.hpp" #include "asio/detail/handler_type_requirements.hpp" @@ -36,10 +37,6 @@ # include "asio/detail/resolver_service.hpp" #endif -#if defined(ASIO_HAS_MOVE) -# include <utility> -#endif // defined(ASIO_HAS_MOVE) - #include "asio/detail/push_options.hpp" namespace asio { @@ -67,6 +64,9 @@ template <typename InternetProtocol, typename Executor> class basic_resolver : public resolver_base { +private: + class initiate_async_resolve; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -119,14 +119,13 @@ public: */ template <typename ExecutionContext> explicit basic_resolver(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a basic_resolver from another. /** * This constructor moves a resolver from one object to another. @@ -158,9 +157,9 @@ public: */ template <typename Executor1> basic_resolver(basic_resolver<InternetProtocol, Executor1>&& other, - typename constraint< + constraint_t< is_convertible<Executor1, Executor>::value - >::type = 0) + > = 0) : impl_(std::move(other.impl_)) { } @@ -196,16 +195,15 @@ public: * constructed using the @c basic_resolver(const executor_type&) constructor. */ template <typename Executor1> - typename constraint< + constraint_t< is_convertible<Executor1, Executor>::value, basic_resolver& - >::type operator=(basic_resolver<InternetProtocol, Executor1>&& other) + > operator=(basic_resolver<InternetProtocol, Executor1>&& other) { basic_resolver tmp(std::move(other)); impl_ = std::move(tmp.impl_); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destroys the resolver. /** @@ -218,7 +216,7 @@ public: } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + executor_type get_executor() noexcept { return impl_.get_executor(); } @@ -647,38 +645,44 @@ public: /// Asynchronously perform forward resolution of a query to a list of entries. /** * This function is used to asynchronously resolve a query into a list of - * endpoint entries. + * endpoint entries. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param q A query object that determines what endpoints will be returned. * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the resolve completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. + * + * @par Completion Signature + * @code void(asio::error_code, results_type) @endcode */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - results_type)) ResolveHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler, - void (asio::error_code, results_type)) - async_resolve(const query& q, - ASIO_MOVE_ARG(ResolveHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + results_type)) ResolveToken = default_completion_token_t<executor_type>> + auto async_resolve(const query& q, + ResolveToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + asio::async_initiate<ResolveToken, + void (asio::error_code, results_type)>( + declval<initiate_async_resolve>(), token, q)) { - return asio::async_initiate<ResolveHandler, + return asio::async_initiate<ResolveToken, void (asio::error_code, results_type)>( - initiate_async_resolve(this), handler, q); + initiate_async_resolve(this), token, q); } #endif // !defined(ASIO_NO_DEPRECATED) @@ -698,21 +702,26 @@ public: * be an empty string, in which case all resolved endpoints will have a port * number of 0. * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the resolve completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. * + * @par Completion Signature + * @code void(asio::error_code, results_type) @endcode + * * @note On POSIX systems, host names may be locally defined in the file * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name @@ -726,23 +735,25 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - results_type)) ResolveHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler, - void (asio::error_code, results_type)) - async_resolve(ASIO_STRING_VIEW_PARAM host, + results_type)) ResolveToken = default_completion_token_t<executor_type>> + auto async_resolve(ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service, - ASIO_MOVE_ARG(ResolveHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ResolveToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + asio::async_initiate<ResolveToken, + void (asio::error_code, results_type)>( + declval<initiate_async_resolve>(), token, + declval<basic_resolver_query<protocol_type>&>())) { return async_resolve(host, service, resolver_base::flags(), - ASIO_MOVE_CAST(ResolveHandler)(handler)); + static_cast<ResolveToken&&>(token)); } /// Asynchronously perform forward resolution of a query to a list of entries. /** * This function is used to resolve host and service names into a list of - * endpoint entries. + * endpoint entries. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param host A string identifying a location. May be a descriptive name or * a numeric address string. If an empty string and the passive flag has been @@ -760,21 +771,26 @@ public: * remote hosts. See the @ref resolver_base documentation for the set of * available flags. * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the resolve completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. * + * @par Completion Signature + * @code void(asio::error_code, results_type) @endcode + * * @note On POSIX systems, host names may be locally defined in the file * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name @@ -788,28 +804,29 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - results_type)) ResolveHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler, - void (asio::error_code, results_type)) - async_resolve(ASIO_STRING_VIEW_PARAM host, - ASIO_STRING_VIEW_PARAM service, - resolver_base::flags resolve_flags, - ASIO_MOVE_ARG(ResolveHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + results_type)) ResolveToken = default_completion_token_t<executor_type>> + auto async_resolve(ASIO_STRING_VIEW_PARAM host, + ASIO_STRING_VIEW_PARAM service, resolver_base::flags resolve_flags, + ResolveToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + asio::async_initiate<ResolveToken, + void (asio::error_code, results_type)>( + declval<initiate_async_resolve>(), token, + declval<basic_resolver_query<protocol_type>&>())) { basic_resolver_query<protocol_type> q(static_cast<std::string>(host), static_cast<std::string>(service), resolve_flags); - return asio::async_initiate<ResolveHandler, + return asio::async_initiate<ResolveToken, void (asio::error_code, results_type)>( - initiate_async_resolve(this), handler, q); + initiate_async_resolve(this), token, q); } /// Asynchronously perform forward resolution of a query to a list of entries. /** * This function is used to resolve host and service names into a list of - * endpoint entries. + * endpoint entries. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param protocol A protocol object, normally representing either the IPv4 or * IPv6 version of an internet protocol. @@ -825,21 +842,26 @@ public: * be an empty string, in which case all resolved endpoints will have a port * number of 0. * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the resolve completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. * + * @par Completion Signature + * @code void(asio::error_code, results_type) @endcode + * * @note On POSIX systems, host names may be locally defined in the file * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name @@ -853,23 +875,25 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - results_type)) ResolveHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler, - void (asio::error_code, results_type)) - async_resolve(const protocol_type& protocol, + results_type)) ResolveToken = default_completion_token_t<executor_type>> + auto async_resolve(const protocol_type& protocol, ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service, - ASIO_MOVE_ARG(ResolveHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ResolveToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + asio::async_initiate<ResolveToken, + void (asio::error_code, results_type)>( + declval<initiate_async_resolve>(), token, + declval<basic_resolver_query<protocol_type>&>())) { return async_resolve(protocol, host, service, resolver_base::flags(), - ASIO_MOVE_CAST(ResolveHandler)(handler)); + static_cast<ResolveToken&&>(token)); } /// Asynchronously perform forward resolution of a query to a list of entries. /** * This function is used to resolve host and service names into a list of - * endpoint entries. + * endpoint entries. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param protocol A protocol object, normally representing either the IPv4 or * IPv6 version of an internet protocol. @@ -890,21 +914,26 @@ public: * remote hosts. See the @ref resolver_base documentation for the set of * available flags. * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the resolve completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. * + * @par Completion Signature + * @code void(asio::error_code, results_type) @endcode + * * @note On POSIX systems, host names may be locally defined in the file * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name @@ -918,23 +947,24 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - results_type)) ResolveHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler, - void (asio::error_code, results_type)) - async_resolve(const protocol_type& protocol, + results_type)) ResolveToken = default_completion_token_t<executor_type>> + auto async_resolve(const protocol_type& protocol, ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service, resolver_base::flags resolve_flags, - ASIO_MOVE_ARG(ResolveHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + ResolveToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + asio::async_initiate<ResolveToken, + void (asio::error_code, results_type)>( + declval<initiate_async_resolve>(), token, + declval<basic_resolver_query<protocol_type>&>())) { basic_resolver_query<protocol_type> q( protocol, static_cast<std::string>(host), static_cast<std::string>(service), resolve_flags); - return asio::async_initiate<ResolveHandler, + return asio::async_initiate<ResolveToken, void (asio::error_code, results_type)>( - initiate_async_resolve(this), handler, q); + initiate_async_resolve(this), token, q); } /// Perform reverse resolution of an endpoint to a list of entries. @@ -983,45 +1013,51 @@ public: /// entries. /** * This function is used to asynchronously resolve an endpoint into a list of - * endpoint entries. + * endpoint entries. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param e An endpoint object that determines what endpoints will be * returned. * - * @param handler The handler to be called when the resolve operation - * completes. Copies will be made of the handler as required. The function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the resolve completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * resolver::results_type results // Resolved endpoints as a range. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * A successful resolve operation is guaranteed to pass a non-empty range to * the handler. + * + * @par Completion Signature + * @code void(asio::error_code, results_type) @endcode */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - results_type)) ResolveHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler, - void (asio::error_code, results_type)) - async_resolve(const endpoint_type& e, - ASIO_MOVE_ARG(ResolveHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + results_type)) ResolveToken = default_completion_token_t<executor_type>> + auto async_resolve(const endpoint_type& e, + ResolveToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + asio::async_initiate<ResolveToken, + void (asio::error_code, results_type)>( + declval<initiate_async_resolve>(), token, e)) { - return asio::async_initiate<ResolveHandler, + return asio::async_initiate<ResolveToken, void (asio::error_code, results_type)>( - initiate_async_resolve(this), handler, e); + initiate_async_resolve(this), token, e); } private: // Disallow copying and assignment. - basic_resolver(const basic_resolver&) ASIO_DELETED; - basic_resolver& operator=(const basic_resolver&) ASIO_DELETED; + basic_resolver(const basic_resolver&) = delete; + basic_resolver& operator=(const basic_resolver&) = delete; class initiate_async_resolve { @@ -1033,13 +1069,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return self_->get_executor(); } template <typename ResolveHandler, typename Query> - void operator()(ASIO_MOVE_ARG(ResolveHandler) handler, + void operator()(ResolveHandler&& handler, const Query& q) const { // If you get an error on the following line it means that your handler diff --git a/3rdparty/asio/include/asio/ip/basic_resolver_entry.hpp b/3rdparty/asio/include/asio/ip/basic_resolver_entry.hpp index 9f299491911..a65af27af50 100644 --- a/3rdparty/asio/include/asio/ip/basic_resolver_entry.hpp +++ b/3rdparty/asio/include/asio/ip/basic_resolver_entry.hpp @@ -2,7 +2,7 @@ // ip/basic_resolver_entry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/basic_resolver_iterator.hpp b/3rdparty/asio/include/asio/ip/basic_resolver_iterator.hpp index e93cf1f797b..b494f7ae02c 100644 --- a/3rdparty/asio/include/asio/ip/basic_resolver_iterator.hpp +++ b/3rdparty/asio/include/asio/ip/basic_resolver_iterator.hpp @@ -2,7 +2,7 @@ // ip/basic_resolver_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -79,15 +79,13 @@ public: { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. basic_resolver_iterator(basic_resolver_iterator&& other) - : values_(ASIO_MOVE_CAST(values_ptr_type)(other.values_)), + : values_(static_cast<values_ptr_type&&>(other.values_)), index_(other.index_) { other.index_ = 0; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Assignment operator. basic_resolver_iterator& operator=(const basic_resolver_iterator& other) @@ -97,20 +95,18 @@ public: return *this; } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-assignment operator. basic_resolver_iterator& operator=(basic_resolver_iterator&& other) { if (this != &other) { - values_ = ASIO_MOVE_CAST(values_ptr_type)(other.values_); + values_ = static_cast<values_ptr_type&&>(other.values_); index_ = other.index_; other.index_ = 0; } return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Dereference an iterator. const basic_resolver_entry<InternetProtocol>& operator*() const @@ -178,7 +174,7 @@ protected: return (*values_)[index_]; } - typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type; + typedef std::vector<basic_resolver_entry<InternetProtocol>> values_type; typedef asio::detail::shared_ptr<values_type> values_ptr_type; values_ptr_type values_; std::size_t index_; diff --git a/3rdparty/asio/include/asio/ip/basic_resolver_query.hpp b/3rdparty/asio/include/asio/ip/basic_resolver_query.hpp index e0d2dedd7d9..ada5a4f3802 100644 --- a/3rdparty/asio/include/asio/ip/basic_resolver_query.hpp +++ b/3rdparty/asio/include/asio/ip/basic_resolver_query.hpp @@ -2,7 +2,7 @@ // ip/basic_resolver_query.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -212,6 +212,22 @@ public: hints_.ai_next = 0; } + /// Copy construct a @c basic_resolver_query from another. + basic_resolver_query(const basic_resolver_query& other) + : hints_(other.hints_), + host_name_(other.host_name_), + service_name_(other.service_name_) + { + } + + /// Move construct a @c basic_resolver_query from another. + basic_resolver_query(basic_resolver_query&& other) + : hints_(other.hints_), + host_name_(static_cast<std::string&&>(other.host_name_)), + service_name_(static_cast<std::string&&>(other.service_name_)) + { + } + /// Get the hints associated with the query. const asio::detail::addrinfo_type& hints() const { diff --git a/3rdparty/asio/include/asio/ip/basic_resolver_results.hpp b/3rdparty/asio/include/asio/ip/basic_resolver_results.hpp index fb7c4149b93..7a461f13bc4 100644 --- a/3rdparty/asio/include/asio/ip/basic_resolver_results.hpp +++ b/3rdparty/asio/include/asio/ip/basic_resolver_results.hpp @@ -2,7 +2,7 @@ // ip/basic_resolver_results.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -93,14 +93,12 @@ public: { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. basic_resolver_results(basic_resolver_results&& other) : basic_resolver_iterator<InternetProtocol>( - ASIO_MOVE_CAST(basic_resolver_results)(other)) + static_cast<basic_resolver_results&&>(other)) { } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Assignment operator. basic_resolver_results& operator=(const basic_resolver_results& other) @@ -109,15 +107,13 @@ public: return *this; } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-assignment operator. basic_resolver_results& operator=(basic_resolver_results&& other) { basic_resolver_iterator<InternetProtocol>::operator=( - ASIO_MOVE_CAST(basic_resolver_results)(other)); + static_cast<basic_resolver_results&&>(other)); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) #if !defined(GENERATING_DOCUMENTATION) // Create results from an addrinfo list returned by getaddrinfo. @@ -230,19 +226,19 @@ public: #endif // !defined(GENERATING_DOCUMENTATION) /// Get the number of entries in the results range. - size_type size() const ASIO_NOEXCEPT + size_type size() const noexcept { return this->values_ ? this->values_->size() : 0; } /// Get the maximum number of entries permitted in a results range. - size_type max_size() const ASIO_NOEXCEPT + size_type max_size() const noexcept { return this->values_ ? this->values_->max_size() : values_type().max_size(); } /// Determine whether the results range is empty. - bool empty() const ASIO_NOEXCEPT + bool empty() const noexcept { return this->values_ ? this->values_->empty() : true; } @@ -252,7 +248,7 @@ public: { basic_resolver_results tmp(*this); tmp.index_ = 0; - return ASIO_MOVE_CAST(basic_resolver_results)(tmp); + return static_cast<basic_resolver_results&&>(tmp); } /// Obtain an end iterator for the results range. @@ -274,7 +270,7 @@ public: } /// Swap the results range with another. - void swap(basic_resolver_results& that) ASIO_NOEXCEPT + void swap(basic_resolver_results& that) noexcept { if (this != &that) { @@ -300,7 +296,7 @@ public: } private: - typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type; + typedef std::vector<basic_resolver_entry<InternetProtocol>> values_type; }; } // namespace ip diff --git a/3rdparty/asio/include/asio/ip/detail/endpoint.hpp b/3rdparty/asio/include/asio/ip/detail/endpoint.hpp index a19fa48e17f..2c4e3cd43f3 100644 --- a/3rdparty/asio/include/asio/ip/detail/endpoint.hpp +++ b/3rdparty/asio/include/asio/ip/detail/endpoint.hpp @@ -2,7 +2,7 @@ // ip/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -33,43 +33,43 @@ class endpoint { public: // Default constructor. - ASIO_DECL endpoint() ASIO_NOEXCEPT; + ASIO_DECL endpoint() noexcept; // Construct an endpoint using a family and port number. ASIO_DECL endpoint(int family, - unsigned short port_num) ASIO_NOEXCEPT; + unsigned short port_num) noexcept; // Construct an endpoint using an address and port number. ASIO_DECL endpoint(const asio::ip::address& addr, - unsigned short port_num) ASIO_NOEXCEPT; + unsigned short port_num) noexcept; // Copy constructor. - endpoint(const endpoint& other) ASIO_NOEXCEPT + endpoint(const endpoint& other) noexcept : data_(other.data_) { } // Assign from another endpoint. - endpoint& operator=(const endpoint& other) ASIO_NOEXCEPT + endpoint& operator=(const endpoint& other) noexcept { data_ = other.data_; return *this; } // Get the underlying endpoint in the native type. - asio::detail::socket_addr_type* data() ASIO_NOEXCEPT + asio::detail::socket_addr_type* data() noexcept { return &data_.base; } // Get the underlying endpoint in the native type. - const asio::detail::socket_addr_type* data() const ASIO_NOEXCEPT + const asio::detail::socket_addr_type* data() const noexcept { return &data_.base; } // Get the underlying size of the endpoint in the native type. - std::size_t size() const ASIO_NOEXCEPT + std::size_t size() const noexcept { if (is_v4()) return sizeof(asio::detail::sockaddr_in4_type); @@ -81,34 +81,34 @@ public: ASIO_DECL void resize(std::size_t new_size); // Get the capacity of the endpoint in the native type. - std::size_t capacity() const ASIO_NOEXCEPT + std::size_t capacity() const noexcept { return sizeof(data_); } // Get the port associated with the endpoint. - ASIO_DECL unsigned short port() const ASIO_NOEXCEPT; + ASIO_DECL unsigned short port() const noexcept; // Set the port associated with the endpoint. - ASIO_DECL void port(unsigned short port_num) ASIO_NOEXCEPT; + ASIO_DECL void port(unsigned short port_num) noexcept; // Get the IP address associated with the endpoint. - ASIO_DECL asio::ip::address address() const ASIO_NOEXCEPT; + ASIO_DECL asio::ip::address address() const noexcept; // Set the IP address associated with the endpoint. ASIO_DECL void address( - const asio::ip::address& addr) ASIO_NOEXCEPT; + const asio::ip::address& addr) noexcept; // Compare two endpoints for equality. ASIO_DECL friend bool operator==(const endpoint& e1, - const endpoint& e2) ASIO_NOEXCEPT; + const endpoint& e2) noexcept; // Compare endpoints for ordering. ASIO_DECL friend bool operator<(const endpoint& e1, - const endpoint& e2) ASIO_NOEXCEPT; + const endpoint& e2) noexcept; // Determine whether the endpoint is IPv4. - bool is_v4() const ASIO_NOEXCEPT + bool is_v4() const noexcept { return data_.base.sa_family == ASIO_OS_DEF(AF_INET); } diff --git a/3rdparty/asio/include/asio/ip/detail/impl/endpoint.ipp b/3rdparty/asio/include/asio/ip/detail/impl/endpoint.ipp index 2a63996eb72..ef61208e234 100644 --- a/3rdparty/asio/include/asio/ip/detail/impl/endpoint.ipp +++ b/3rdparty/asio/include/asio/ip/detail/impl/endpoint.ipp @@ -2,7 +2,7 @@ // ip/detail/impl/endpoint.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -31,7 +31,7 @@ namespace asio { namespace ip { namespace detail { -endpoint::endpoint() ASIO_NOEXCEPT +endpoint::endpoint() noexcept : data_() { data_.v4.sin_family = ASIO_OS_DEF(AF_INET); @@ -39,7 +39,7 @@ endpoint::endpoint() ASIO_NOEXCEPT data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY); } -endpoint::endpoint(int family, unsigned short port_num) ASIO_NOEXCEPT +endpoint::endpoint(int family, unsigned short port_num) noexcept : data_() { using namespace std; // For memcpy. @@ -69,7 +69,7 @@ endpoint::endpoint(int family, unsigned short port_num) ASIO_NOEXCEPT } endpoint::endpoint(const asio::ip::address& addr, - unsigned short port_num) ASIO_NOEXCEPT + unsigned short port_num) noexcept : data_() { using namespace std; // For memcpy. @@ -106,7 +106,7 @@ void endpoint::resize(std::size_t new_size) } } -unsigned short endpoint::port() const ASIO_NOEXCEPT +unsigned short endpoint::port() const noexcept { if (is_v4()) { @@ -120,7 +120,7 @@ unsigned short endpoint::port() const ASIO_NOEXCEPT } } -void endpoint::port(unsigned short port_num) ASIO_NOEXCEPT +void endpoint::port(unsigned short port_num) noexcept { if (is_v4()) { @@ -134,7 +134,7 @@ void endpoint::port(unsigned short port_num) ASIO_NOEXCEPT } } -asio::ip::address endpoint::address() const ASIO_NOEXCEPT +asio::ip::address endpoint::address() const noexcept { using namespace std; // For memcpy. if (is_v4()) @@ -146,27 +146,23 @@ asio::ip::address endpoint::address() const ASIO_NOEXCEPT else { asio::ip::address_v6::bytes_type bytes; -#if defined(ASIO_HAS_STD_ARRAY) memcpy(bytes.data(), data_.v6.sin6_addr.s6_addr, 16); -#else // defined(ASIO_HAS_STD_ARRAY) - memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16); -#endif // defined(ASIO_HAS_STD_ARRAY) return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id); } } -void endpoint::address(const asio::ip::address& addr) ASIO_NOEXCEPT +void endpoint::address(const asio::ip::address& addr) noexcept { endpoint tmp_endpoint(addr, port()); data_ = tmp_endpoint.data_; } -bool operator==(const endpoint& e1, const endpoint& e2) ASIO_NOEXCEPT +bool operator==(const endpoint& e1, const endpoint& e2) noexcept { return e1.address() == e2.address() && e1.port() == e2.port(); } -bool operator<(const endpoint& e1, const endpoint& e2) ASIO_NOEXCEPT +bool operator<(const endpoint& e1, const endpoint& e2) noexcept { if (e1.address() < e2.address()) return true; diff --git a/3rdparty/asio/include/asio/ip/detail/socket_option.hpp b/3rdparty/asio/include/asio/ip/detail/socket_option.hpp index 87d6bd6c7e9..c9883ae033e 100644 --- a/3rdparty/asio/include/asio/ip/detail/socket_option.hpp +++ b/3rdparty/asio/include/asio/ip/detail/socket_option.hpp @@ -2,7 +2,7 @@ // detail/socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/host_name.hpp b/3rdparty/asio/include/asio/ip/host_name.hpp index ab9f82e394f..f9cb1852cae 100644 --- a/3rdparty/asio/include/asio/ip/host_name.hpp +++ b/3rdparty/asio/include/asio/ip/host_name.hpp @@ -2,7 +2,7 @@ // ip/host_name.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/icmp.hpp b/3rdparty/asio/include/asio/ip/icmp.hpp index f9ae9864d7b..9e4e8e4cb5b 100644 --- a/3rdparty/asio/include/asio/ip/icmp.hpp +++ b/3rdparty/asio/include/asio/ip/icmp.hpp @@ -2,7 +2,7 @@ // ip/icmp.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -46,33 +46,33 @@ public: typedef basic_endpoint<icmp> endpoint; /// Construct to represent the IPv4 ICMP protocol. - static icmp v4() ASIO_NOEXCEPT + static icmp v4() noexcept { return icmp(ASIO_OS_DEF(IPPROTO_ICMP), ASIO_OS_DEF(AF_INET)); } /// Construct to represent the IPv6 ICMP protocol. - static icmp v6() ASIO_NOEXCEPT + static icmp v6() noexcept { return icmp(ASIO_OS_DEF(IPPROTO_ICMPV6), ASIO_OS_DEF(AF_INET6)); } /// Obtain an identifier for the type of the protocol. - int type() const ASIO_NOEXCEPT + int type() const noexcept { return ASIO_OS_DEF(SOCK_RAW); } /// Obtain an identifier for the protocol. - int protocol() const ASIO_NOEXCEPT + int protocol() const noexcept { return protocol_; } /// Obtain an identifier for the protocol family. - int family() const ASIO_NOEXCEPT + int family() const noexcept { return family_; } @@ -97,7 +97,7 @@ public: private: // Construct with a specific family. - explicit icmp(int protocol_id, int protocol_family) ASIO_NOEXCEPT + explicit icmp(int protocol_id, int protocol_family) noexcept : protocol_(protocol_id), family_(protocol_family) { diff --git a/3rdparty/asio/include/asio/ip/impl/address.hpp b/3rdparty/asio/include/asio/ip/impl/address.hpp index 56e391914f6..5780f320067 100644 --- a/3rdparty/asio/include/asio/ip/impl/address.hpp +++ b/3rdparty/asio/include/asio/ip/impl/address.hpp @@ -2,7 +2,7 @@ // ip/impl/address.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/impl/address.ipp b/3rdparty/asio/include/asio/ip/impl/address.ipp index 2e104e92a7b..9893b4ce9c2 100644 --- a/3rdparty/asio/include/asio/ip/impl/address.ipp +++ b/3rdparty/asio/include/asio/ip/impl/address.ipp @@ -2,7 +2,7 @@ // ip/impl/address.ipp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -29,7 +29,7 @@ namespace asio { namespace ip { -address::address() ASIO_NOEXCEPT +address::address() noexcept : type_(ipv4), ipv4_address_(), ipv6_address_() @@ -37,7 +37,7 @@ address::address() ASIO_NOEXCEPT } address::address( - const asio::ip::address_v4& ipv4_address) ASIO_NOEXCEPT + const asio::ip::address_v4& ipv4_address) noexcept : type_(ipv4), ipv4_address_(ipv4_address), ipv6_address_() @@ -45,30 +45,28 @@ address::address( } address::address( - const asio::ip::address_v6& ipv6_address) ASIO_NOEXCEPT + const asio::ip::address_v6& ipv6_address) noexcept : type_(ipv6), ipv4_address_(), ipv6_address_(ipv6_address) { } -address::address(const address& other) ASIO_NOEXCEPT +address::address(const address& other) noexcept : type_(other.type_), ipv4_address_(other.ipv4_address_), ipv6_address_(other.ipv6_address_) { } -#if defined(ASIO_HAS_MOVE) -address::address(address&& other) ASIO_NOEXCEPT +address::address(address&& other) noexcept : type_(other.type_), ipv4_address_(other.ipv4_address_), ipv6_address_(other.ipv6_address_) { } -#endif // defined(ASIO_HAS_MOVE) -address& address::operator=(const address& other) ASIO_NOEXCEPT +address& address::operator=(const address& other) noexcept { type_ = other.type_; ipv4_address_ = other.ipv4_address_; @@ -76,18 +74,16 @@ address& address::operator=(const address& other) ASIO_NOEXCEPT return *this; } -#if defined(ASIO_HAS_MOVE) -address& address::operator=(address&& other) ASIO_NOEXCEPT +address& address::operator=(address&& other) noexcept { type_ = other.type_; ipv4_address_ = other.ipv4_address_; ipv6_address_ = other.ipv6_address_; return *this; } -#endif // defined(ASIO_HAS_MOVE) address& address::operator=( - const asio::ip::address_v4& ipv4_address) ASIO_NOEXCEPT + const asio::ip::address_v4& ipv4_address) noexcept { type_ = ipv4; ipv4_address_ = ipv4_address; @@ -96,7 +92,7 @@ address& address::operator=( } address& address::operator=( - const asio::ip::address_v6& ipv6_address) ASIO_NOEXCEPT + const asio::ip::address_v6& ipv6_address) noexcept { type_ = ipv6; ipv4_address_ = asio::ip::address_v4(); @@ -113,7 +109,7 @@ address make_address(const char* str) } address make_address(const char* str, - asio::error_code& ec) ASIO_NOEXCEPT + asio::error_code& ec) noexcept { asio::ip::address_v6 ipv6_address = asio::ip::make_address_v6(str, ec); @@ -134,7 +130,7 @@ address make_address(const std::string& str) } address make_address(const std::string& str, - asio::error_code& ec) ASIO_NOEXCEPT + asio::error_code& ec) noexcept { return make_address(str.c_str(), ec); } @@ -147,7 +143,7 @@ address make_address(string_view str) } address make_address(string_view str, - asio::error_code& ec) ASIO_NOEXCEPT + asio::error_code& ec) noexcept { return make_address(static_cast<std::string>(str), ec); } @@ -190,28 +186,28 @@ std::string address::to_string(asio::error_code& ec) const } #endif // !defined(ASIO_NO_DEPRECATED) -bool address::is_loopback() const ASIO_NOEXCEPT +bool address::is_loopback() const noexcept { return (type_ == ipv4) ? ipv4_address_.is_loopback() : ipv6_address_.is_loopback(); } -bool address::is_unspecified() const ASIO_NOEXCEPT +bool address::is_unspecified() const noexcept { return (type_ == ipv4) ? ipv4_address_.is_unspecified() : ipv6_address_.is_unspecified(); } -bool address::is_multicast() const ASIO_NOEXCEPT +bool address::is_multicast() const noexcept { return (type_ == ipv4) ? ipv4_address_.is_multicast() : ipv6_address_.is_multicast(); } -bool operator==(const address& a1, const address& a2) ASIO_NOEXCEPT +bool operator==(const address& a1, const address& a2) noexcept { if (a1.type_ != a2.type_) return false; @@ -220,7 +216,7 @@ bool operator==(const address& a1, const address& a2) ASIO_NOEXCEPT return a1.ipv4_address_ == a2.ipv4_address_; } -bool operator<(const address& a1, const address& a2) ASIO_NOEXCEPT +bool operator<(const address& a1, const address& a2) noexcept { if (a1.type_ < a2.type_) return true; diff --git a/3rdparty/asio/include/asio/ip/impl/address_v4.hpp b/3rdparty/asio/include/asio/ip/impl/address_v4.hpp index 8cb22ef0f96..5e29a249ba8 100644 --- a/3rdparty/asio/include/asio/ip/impl/address_v4.hpp +++ b/3rdparty/asio/include/asio/ip/impl/address_v4.hpp @@ -2,7 +2,7 @@ // ip/impl/address_v4.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/impl/address_v4.ipp b/3rdparty/asio/include/asio/ip/impl/address_v4.ipp index 276b399497f..d7803271ac9 100644 --- a/3rdparty/asio/include/asio/ip/impl/address_v4.ipp +++ b/3rdparty/asio/include/asio/ip/impl/address_v4.ipp @@ -2,7 +2,7 @@ // ip/impl/address_v4.ipp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -57,19 +57,15 @@ address_v4::address_v4(address_v4::uint_type addr) static_cast<asio::detail::u_long_type>(addr)); } -address_v4::bytes_type address_v4::to_bytes() const ASIO_NOEXCEPT +address_v4::bytes_type address_v4::to_bytes() const noexcept { using namespace std; // For memcpy. bytes_type bytes; -#if defined(ASIO_HAS_STD_ARRAY) memcpy(bytes.data(), &addr_.s_addr, 4); -#else // defined(ASIO_HAS_STD_ARRAY) - memcpy(bytes.elems, &addr_.s_addr, 4); -#endif // defined(ASIO_HAS_STD_ARRAY) return bytes; } -address_v4::uint_type address_v4::to_uint() const ASIO_NOEXCEPT +address_v4::uint_type address_v4::to_uint() const noexcept { return asio::detail::socket_ops::network_to_host_long(addr_.s_addr); } @@ -108,12 +104,12 @@ std::string address_v4::to_string(asio::error_code& ec) const } #endif // !defined(ASIO_NO_DEPRECATED) -bool address_v4::is_loopback() const ASIO_NOEXCEPT +bool address_v4::is_loopback() const noexcept { return (to_uint() & 0xFF000000) == 0x7F000000; } -bool address_v4::is_unspecified() const ASIO_NOEXCEPT +bool address_v4::is_unspecified() const noexcept { return to_uint() == 0; } @@ -135,7 +131,7 @@ bool address_v4::is_class_c() const } #endif // !defined(ASIO_NO_DEPRECATED) -bool address_v4::is_multicast() const ASIO_NOEXCEPT +bool address_v4::is_multicast() const noexcept { return (to_uint() & 0xF0000000) == 0xE0000000; } @@ -167,7 +163,7 @@ address_v4 make_address_v4(const char* str) } address_v4 make_address_v4(const char* str, - asio::error_code& ec) ASIO_NOEXCEPT + asio::error_code& ec) noexcept { address_v4::bytes_type bytes; if (asio::detail::socket_ops::inet_pton( @@ -182,7 +178,7 @@ address_v4 make_address_v4(const std::string& str) } address_v4 make_address_v4(const std::string& str, - asio::error_code& ec) ASIO_NOEXCEPT + asio::error_code& ec) noexcept { return make_address_v4(str.c_str(), ec); } @@ -195,7 +191,7 @@ address_v4 make_address_v4(string_view str) } address_v4 make_address_v4(string_view str, - asio::error_code& ec) ASIO_NOEXCEPT + asio::error_code& ec) noexcept { return make_address_v4(static_cast<std::string>(str), ec); } diff --git a/3rdparty/asio/include/asio/ip/impl/address_v6.hpp b/3rdparty/asio/include/asio/ip/impl/address_v6.hpp index f65fab73488..b4b53abe069 100644 --- a/3rdparty/asio/include/asio/ip/impl/address_v6.hpp +++ b/3rdparty/asio/include/asio/ip/impl/address_v6.hpp @@ -2,7 +2,7 @@ // ip/impl/address_v6.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/impl/address_v6.ipp b/3rdparty/asio/include/asio/ip/impl/address_v6.ipp index 0021a22d603..8d5b7d1fd09 100644 --- a/3rdparty/asio/include/asio/ip/impl/address_v6.ipp +++ b/3rdparty/asio/include/asio/ip/impl/address_v6.ipp @@ -2,7 +2,7 @@ // ip/impl/address_v6.ipp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -31,7 +31,7 @@ namespace asio { namespace ip { -address_v6::address_v6() ASIO_NOEXCEPT +address_v6::address_v6() noexcept : addr_(), scope_id_(0) { @@ -56,45 +56,37 @@ address_v6::address_v6(const address_v6::bytes_type& bytes, memcpy(addr_.s6_addr, bytes.data(), 16); } -address_v6::address_v6(const address_v6& other) ASIO_NOEXCEPT +address_v6::address_v6(const address_v6& other) noexcept : addr_(other.addr_), scope_id_(other.scope_id_) { } -#if defined(ASIO_HAS_MOVE) -address_v6::address_v6(address_v6&& other) ASIO_NOEXCEPT +address_v6::address_v6(address_v6&& other) noexcept : addr_(other.addr_), scope_id_(other.scope_id_) { } -#endif // defined(ASIO_HAS_MOVE) -address_v6& address_v6::operator=(const address_v6& other) ASIO_NOEXCEPT +address_v6& address_v6::operator=(const address_v6& other) noexcept { addr_ = other.addr_; scope_id_ = other.scope_id_; return *this; } -#if defined(ASIO_HAS_MOVE) -address_v6& address_v6::operator=(address_v6&& other) ASIO_NOEXCEPT +address_v6& address_v6::operator=(address_v6&& other) noexcept { addr_ = other.addr_; scope_id_ = other.scope_id_; return *this; } -#endif // defined(ASIO_HAS_MOVE) -address_v6::bytes_type address_v6::to_bytes() const ASIO_NOEXCEPT +address_v6::bytes_type address_v6::to_bytes() const noexcept { using namespace std; // For memcpy. bytes_type bytes; -#if defined(ASIO_HAS_STD_ARRAY) memcpy(bytes.data(), addr_.s6_addr, 16); -#else // defined(ASIO_HAS_STD_ARRAY) - memcpy(bytes.elems, addr_.s6_addr, 16); -#endif // defined(ASIO_HAS_STD_ARRAY) return bytes; } @@ -138,7 +130,7 @@ address_v4 address_v6::to_v4() const } #endif // !defined(ASIO_NO_DEPRECATED) -bool address_v6::is_loopback() const ASIO_NOEXCEPT +bool address_v6::is_loopback() const noexcept { return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) @@ -150,7 +142,7 @@ bool address_v6::is_loopback() const ASIO_NOEXCEPT && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1)); } -bool address_v6::is_unspecified() const ASIO_NOEXCEPT +bool address_v6::is_unspecified() const noexcept { return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) @@ -162,17 +154,17 @@ bool address_v6::is_unspecified() const ASIO_NOEXCEPT && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0)); } -bool address_v6::is_link_local() const ASIO_NOEXCEPT +bool address_v6::is_link_local() const noexcept { return ((addr_.s6_addr[0] == 0xfe) && ((addr_.s6_addr[1] & 0xc0) == 0x80)); } -bool address_v6::is_site_local() const ASIO_NOEXCEPT +bool address_v6::is_site_local() const noexcept { return ((addr_.s6_addr[0] == 0xfe) && ((addr_.s6_addr[1] & 0xc0) == 0xc0)); } -bool address_v6::is_v4_mapped() const ASIO_NOEXCEPT +bool address_v6::is_v4_mapped() const noexcept { return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0) && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0) @@ -198,37 +190,37 @@ bool address_v6::is_v4_compatible() const } #endif // !defined(ASIO_NO_DEPRECATED) -bool address_v6::is_multicast() const ASIO_NOEXCEPT +bool address_v6::is_multicast() const noexcept { return (addr_.s6_addr[0] == 0xff); } -bool address_v6::is_multicast_global() const ASIO_NOEXCEPT +bool address_v6::is_multicast_global() const noexcept { return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x0e)); } -bool address_v6::is_multicast_link_local() const ASIO_NOEXCEPT +bool address_v6::is_multicast_link_local() const noexcept { return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x02)); } -bool address_v6::is_multicast_node_local() const ASIO_NOEXCEPT +bool address_v6::is_multicast_node_local() const noexcept { return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x01)); } -bool address_v6::is_multicast_org_local() const ASIO_NOEXCEPT +bool address_v6::is_multicast_org_local() const noexcept { return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x08)); } -bool address_v6::is_multicast_site_local() const ASIO_NOEXCEPT +bool address_v6::is_multicast_site_local() const noexcept { return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x05)); } -bool operator==(const address_v6& a1, const address_v6& a2) ASIO_NOEXCEPT +bool operator==(const address_v6& a1, const address_v6& a2) noexcept { using namespace std; // For memcmp. return memcmp(&a1.addr_, &a2.addr_, @@ -236,7 +228,7 @@ bool operator==(const address_v6& a1, const address_v6& a2) ASIO_NOEXCEPT && a1.scope_id_ == a2.scope_id_; } -bool operator<(const address_v6& a1, const address_v6& a2) ASIO_NOEXCEPT +bool operator<(const address_v6& a1, const address_v6& a2) noexcept { using namespace std; // For memcmp. int memcmp_result = memcmp(&a1.addr_, &a2.addr_, @@ -248,7 +240,7 @@ bool operator<(const address_v6& a1, const address_v6& a2) ASIO_NOEXCEPT return a1.scope_id_ < a2.scope_id_; } -address_v6 address_v6::loopback() ASIO_NOEXCEPT +address_v6 address_v6::loopback() noexcept { address_v6 tmp; tmp.addr_.s6_addr[15] = 1; @@ -282,7 +274,7 @@ address_v6 make_address_v6(const char* str) } address_v6 make_address_v6(const char* str, - asio::error_code& ec) ASIO_NOEXCEPT + asio::error_code& ec) noexcept { address_v6::bytes_type bytes; unsigned long scope_id = 0; @@ -298,7 +290,7 @@ address_v6 make_address_v6(const std::string& str) } address_v6 make_address_v6(const std::string& str, - asio::error_code& ec) ASIO_NOEXCEPT + asio::error_code& ec) noexcept { return make_address_v6(str.c_str(), ec); } @@ -311,7 +303,7 @@ address_v6 make_address_v6(string_view str) } address_v6 make_address_v6(string_view str, - asio::error_code& ec) ASIO_NOEXCEPT + asio::error_code& ec) noexcept { return make_address_v6(static_cast<std::string>(str), ec); } diff --git a/3rdparty/asio/include/asio/ip/impl/basic_endpoint.hpp b/3rdparty/asio/include/asio/ip/impl/basic_endpoint.hpp index 7cd90e6f42e..2da96c16547 100644 --- a/3rdparty/asio/include/asio/ip/impl/basic_endpoint.hpp +++ b/3rdparty/asio/include/asio/ip/impl/basic_endpoint.hpp @@ -2,7 +2,7 @@ // ip/impl/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/impl/host_name.ipp b/3rdparty/asio/include/asio/ip/impl/host_name.ipp index 84f5729246c..eb27829fdab 100644 --- a/3rdparty/asio/include/asio/ip/impl/host_name.ipp +++ b/3rdparty/asio/include/asio/ip/impl/host_name.ipp @@ -2,7 +2,7 @@ // ip/impl/host_name.ipp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/impl/network_v4.hpp b/3rdparty/asio/include/asio/ip/impl/network_v4.hpp index ae0defa8836..2199c7da8ca 100644 --- a/3rdparty/asio/include/asio/ip/impl/network_v4.hpp +++ b/3rdparty/asio/include/asio/ip/impl/network_v4.hpp @@ -2,7 +2,7 @@ // ip/impl/network_v4.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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 diff --git a/3rdparty/asio/include/asio/ip/impl/network_v4.ipp b/3rdparty/asio/include/asio/ip/impl/network_v4.ipp index 27f0519acf5..e7e68ed443a 100644 --- a/3rdparty/asio/include/asio/ip/impl/network_v4.ipp +++ b/3rdparty/asio/include/asio/ip/impl/network_v4.ipp @@ -2,7 +2,7 @@ // ip/impl/network_v4.ipp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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 @@ -91,7 +91,7 @@ network_v4::network_v4(const address_v4& addr, const address_v4& mask) } } -address_v4 network_v4::netmask() const ASIO_NOEXCEPT +address_v4 network_v4::netmask() const noexcept { uint32_t nmbits = 0xffffffff; if (prefix_length_ == 0) @@ -101,7 +101,7 @@ address_v4 network_v4::netmask() const ASIO_NOEXCEPT return address_v4(nmbits); } -address_v4_range network_v4::hosts() const ASIO_NOEXCEPT +address_v4_range network_v4::hosts() const noexcept { return is_host() ? address_v4_range(address_, address_v4(address_.to_uint() + 1)) @@ -129,7 +129,9 @@ std::string network_v4::to_string(asio::error_code& ec) const using namespace std; // For sprintf. ec = asio::error_code(); char prefix_len[16]; -#if defined(ASIO_HAS_SECURE_RTL) +#if defined(ASIO_HAS_SNPRINTF) + snprintf(prefix_len, sizeof(prefix_len), "/%u", prefix_length_); +#elif defined(ASIO_HAS_SECURE_RTL) sprintf_s(prefix_len, sizeof(prefix_len), "/%u", prefix_length_); #else // defined(ASIO_HAS_SECURE_RTL) sprintf(prefix_len, "/%u", prefix_length_); diff --git a/3rdparty/asio/include/asio/ip/impl/network_v6.hpp b/3rdparty/asio/include/asio/ip/impl/network_v6.hpp index f159f839b85..69c121813cb 100644 --- a/3rdparty/asio/include/asio/ip/impl/network_v6.hpp +++ b/3rdparty/asio/include/asio/ip/impl/network_v6.hpp @@ -2,7 +2,7 @@ // ip/impl/network_v6.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/impl/network_v6.ipp b/3rdparty/asio/include/asio/ip/impl/network_v6.ipp index 1a4684bf03d..d85cd647e06 100644 --- a/3rdparty/asio/include/asio/ip/impl/network_v6.ipp +++ b/3rdparty/asio/include/asio/ip/impl/network_v6.ipp @@ -2,7 +2,7 @@ // ip/impl/network_v6.ipp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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 @@ -42,7 +42,7 @@ network_v6::network_v6(const address_v6& addr, unsigned short prefix_len) } } -ASIO_DECL address_v6 network_v6::network() const ASIO_NOEXCEPT +ASIO_DECL address_v6 network_v6::network() const noexcept { address_v6::bytes_type bytes(address_.to_bytes()); for (std::size_t i = 0; i < 16; ++i) @@ -55,7 +55,7 @@ ASIO_DECL address_v6 network_v6::network() const ASIO_NOEXCEPT return address_v6(bytes, address_.scope_id()); } -address_v6_range network_v6::hosts() const ASIO_NOEXCEPT +address_v6_range network_v6::hosts() const noexcept { address_v6::bytes_type begin_bytes(address_.to_bytes()); address_v6::bytes_type end_bytes(address_.to_bytes()); @@ -98,7 +98,9 @@ std::string network_v6::to_string(asio::error_code& ec) const using namespace std; // For sprintf. ec = asio::error_code(); char prefix_len[16]; -#if defined(ASIO_HAS_SECURE_RTL) +#if defined(ASIO_HAS_SNPRINTF) + snprintf(prefix_len, sizeof(prefix_len), "/%u", prefix_length_); +#elif defined(ASIO_HAS_SECURE_RTL) sprintf_s(prefix_len, sizeof(prefix_len), "/%u", prefix_length_); #else // defined(ASIO_HAS_SECURE_RTL) sprintf(prefix_len, "/%u", prefix_length_); diff --git a/3rdparty/asio/include/asio/ip/multicast.hpp b/3rdparty/asio/include/asio/ip/multicast.hpp index 1b86351f095..363f5ed81d5 100644 --- a/3rdparty/asio/include/asio/ip/multicast.hpp +++ b/3rdparty/asio/include/asio/ip/multicast.hpp @@ -2,7 +2,7 @@ // ip/multicast.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/network_v4.hpp b/3rdparty/asio/include/asio/ip/network_v4.hpp index 035dea89e79..1c29ebec143 100644 --- a/3rdparty/asio/include/asio/ip/network_v4.hpp +++ b/3rdparty/asio/include/asio/ip/network_v4.hpp @@ -2,7 +2,7 @@ // ip/network_v4.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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 @@ -40,7 +40,7 @@ class network_v4 { public: /// Default constructor. - network_v4() ASIO_NOEXCEPT + network_v4() noexcept : address_(), prefix_length_(0) { @@ -55,78 +55,74 @@ public: const address_v4& mask); /// Copy constructor. - network_v4(const network_v4& other) ASIO_NOEXCEPT + network_v4(const network_v4& other) noexcept : address_(other.address_), prefix_length_(other.prefix_length_) { } -#if defined(ASIO_HAS_MOVE) /// Move constructor. - network_v4(network_v4&& other) ASIO_NOEXCEPT - : address_(ASIO_MOVE_CAST(address_v4)(other.address_)), + network_v4(network_v4&& other) noexcept + : address_(static_cast<address_v4&&>(other.address_)), prefix_length_(other.prefix_length_) { } -#endif // defined(ASIO_HAS_MOVE) /// Assign from another network. - network_v4& operator=(const network_v4& other) ASIO_NOEXCEPT + network_v4& operator=(const network_v4& other) noexcept { address_ = other.address_; prefix_length_ = other.prefix_length_; return *this; } -#if defined(ASIO_HAS_MOVE) /// Move-assign from another network. - network_v4& operator=(network_v4&& other) ASIO_NOEXCEPT + network_v4& operator=(network_v4&& other) noexcept { - address_ = ASIO_MOVE_CAST(address_v4)(other.address_); + address_ = static_cast<address_v4&&>(other.address_); prefix_length_ = other.prefix_length_; return *this; } -#endif // defined(ASIO_HAS_MOVE) /// Obtain the address object specified when the network object was created. - address_v4 address() const ASIO_NOEXCEPT + address_v4 address() const noexcept { return address_; } /// Obtain the prefix length that was specified when the network object was /// created. - unsigned short prefix_length() const ASIO_NOEXCEPT + unsigned short prefix_length() const noexcept { return prefix_length_; } /// Obtain the netmask that was specified when the network object was created. - ASIO_DECL address_v4 netmask() const ASIO_NOEXCEPT; + ASIO_DECL address_v4 netmask() const noexcept; /// Obtain an address object that represents the network address. - address_v4 network() const ASIO_NOEXCEPT + address_v4 network() const 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 ASIO_NOEXCEPT + address_v4 broadcast() const noexcept { return address_v4(network().to_uint() | (netmask().to_uint() ^ 0xFFFFFFFF)); } /// Obtain an address range corresponding to the hosts in the network. - ASIO_DECL address_v4_range hosts() const ASIO_NOEXCEPT; + ASIO_DECL address_v4_range hosts() const noexcept; /// Obtain the true network address, omitting any host bits. - network_v4 canonical() const ASIO_NOEXCEPT + network_v4 canonical() const noexcept { - return network_v4(network(), netmask()); + return network_v4(network(), prefix_length()); } /// Test if network is a valid host address. - bool is_host() const ASIO_NOEXCEPT + bool is_host() const noexcept { return prefix_length_ == 32; } diff --git a/3rdparty/asio/include/asio/ip/network_v6.hpp b/3rdparty/asio/include/asio/ip/network_v6.hpp index 44c0ff36305..942ed9d2f29 100644 --- a/3rdparty/asio/include/asio/ip/network_v6.hpp +++ b/3rdparty/asio/include/asio/ip/network_v6.hpp @@ -2,7 +2,7 @@ // ip/network_v6.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 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 @@ -40,7 +40,7 @@ class network_v6 { public: /// Default constructor. - network_v6() ASIO_NOEXCEPT + network_v6() noexcept : address_(), prefix_length_(0) { @@ -51,66 +51,62 @@ public: unsigned short prefix_len); /// Copy constructor. - network_v6(const network_v6& other) ASIO_NOEXCEPT + network_v6(const network_v6& other) noexcept : address_(other.address_), prefix_length_(other.prefix_length_) { } -#if defined(ASIO_HAS_MOVE) /// Move constructor. - network_v6(network_v6&& other) ASIO_NOEXCEPT - : address_(ASIO_MOVE_CAST(address_v6)(other.address_)), + network_v6(network_v6&& other) noexcept + : address_(static_cast<address_v6&&>(other.address_)), prefix_length_(other.prefix_length_) { } -#endif // defined(ASIO_HAS_MOVE) /// Assign from another network. - network_v6& operator=(const network_v6& other) ASIO_NOEXCEPT + network_v6& operator=(const network_v6& other) noexcept { address_ = other.address_; prefix_length_ = other.prefix_length_; return *this; } -#if defined(ASIO_HAS_MOVE) /// Move-assign from another network. - network_v6& operator=(network_v6&& other) ASIO_NOEXCEPT + network_v6& operator=(network_v6&& other) noexcept { - address_ = ASIO_MOVE_CAST(address_v6)(other.address_); + address_ = static_cast<address_v6&&>(other.address_); prefix_length_ = other.prefix_length_; return *this; } -#endif // defined(ASIO_HAS_MOVE) /// Obtain the address object specified when the network object was created. - address_v6 address() const ASIO_NOEXCEPT + address_v6 address() const noexcept { return address_; } /// Obtain the prefix length that was specified when the network object was /// created. - unsigned short prefix_length() const ASIO_NOEXCEPT + unsigned short prefix_length() const noexcept { return prefix_length_; } /// Obtain an address object that represents the network address. - ASIO_DECL address_v6 network() const ASIO_NOEXCEPT; + ASIO_DECL address_v6 network() const noexcept; /// Obtain an address range corresponding to the hosts in the network. - ASIO_DECL address_v6_range hosts() const ASIO_NOEXCEPT; + ASIO_DECL address_v6_range hosts() const noexcept; /// Obtain the true network address, omitting any host bits. - network_v6 canonical() const ASIO_NOEXCEPT + network_v6 canonical() const noexcept { return network_v6(network(), prefix_length()); } /// Test if network is a valid host address. - bool is_host() const ASIO_NOEXCEPT + bool is_host() const noexcept { return prefix_length_ == 128; } diff --git a/3rdparty/asio/include/asio/ip/resolver_base.hpp b/3rdparty/asio/include/asio/ip/resolver_base.hpp index 06e769c05b8..9fa01ca9107 100644 --- a/3rdparty/asio/include/asio/ip/resolver_base.hpp +++ b/3rdparty/asio/include/asio/ip/resolver_base.hpp @@ -2,7 +2,7 @@ // ip/resolver_base.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/resolver_query_base.hpp b/3rdparty/asio/include/asio/ip/resolver_query_base.hpp index a96068cb3f3..892bc28e006 100644 --- a/3rdparty/asio/include/asio/ip/resolver_query_base.hpp +++ b/3rdparty/asio/include/asio/ip/resolver_query_base.hpp @@ -2,7 +2,7 @@ // ip/resolver_query_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/tcp.hpp b/3rdparty/asio/include/asio/ip/tcp.hpp index df2b99c0f8c..b8319609ddb 100644 --- a/3rdparty/asio/include/asio/ip/tcp.hpp +++ b/3rdparty/asio/include/asio/ip/tcp.hpp @@ -2,7 +2,7 @@ // ip/tcp.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -49,31 +49,31 @@ public: typedef basic_endpoint<tcp> endpoint; /// Construct to represent the IPv4 TCP protocol. - static tcp v4() ASIO_NOEXCEPT + static tcp v4() noexcept { return tcp(ASIO_OS_DEF(AF_INET)); } /// Construct to represent the IPv6 TCP protocol. - static tcp v6() ASIO_NOEXCEPT + static tcp v6() noexcept { return tcp(ASIO_OS_DEF(AF_INET6)); } /// Obtain an identifier for the type of the protocol. - int type() const ASIO_NOEXCEPT + int type() const noexcept { return ASIO_OS_DEF(SOCK_STREAM); } /// Obtain an identifier for the protocol. - int protocol() const ASIO_NOEXCEPT + int protocol() const noexcept { return ASIO_OS_DEF(IPPROTO_TCP); } /// Obtain an identifier for the protocol family. - int family() const ASIO_NOEXCEPT + int family() const noexcept { return family_; } @@ -139,7 +139,7 @@ public: private: // Construct with a specific family. - explicit tcp(int protocol_family) ASIO_NOEXCEPT + explicit tcp(int protocol_family) noexcept : family_(protocol_family) { } diff --git a/3rdparty/asio/include/asio/ip/udp.hpp b/3rdparty/asio/include/asio/ip/udp.hpp index 796de061229..50c667a5371 100644 --- a/3rdparty/asio/include/asio/ip/udp.hpp +++ b/3rdparty/asio/include/asio/ip/udp.hpp @@ -2,7 +2,7 @@ // ip/udp.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -46,31 +46,31 @@ public: typedef basic_endpoint<udp> endpoint; /// Construct to represent the IPv4 UDP protocol. - static udp v4() ASIO_NOEXCEPT + static udp v4() noexcept { return udp(ASIO_OS_DEF(AF_INET)); } /// Construct to represent the IPv6 UDP protocol. - static udp v6() ASIO_NOEXCEPT + static udp v6() noexcept { return udp(ASIO_OS_DEF(AF_INET6)); } /// Obtain an identifier for the type of the protocol. - int type() const ASIO_NOEXCEPT + int type() const noexcept { return ASIO_OS_DEF(SOCK_DGRAM); } /// Obtain an identifier for the protocol. - int protocol() const ASIO_NOEXCEPT + int protocol() const noexcept { return ASIO_OS_DEF(IPPROTO_UDP); } /// Obtain an identifier for the protocol family. - int family() const ASIO_NOEXCEPT + int family() const noexcept { return family_; } @@ -95,7 +95,7 @@ public: private: // Construct with a specific family. - explicit udp(int protocol_family) ASIO_NOEXCEPT + explicit udp(int protocol_family) noexcept : family_(protocol_family) { } diff --git a/3rdparty/asio/include/asio/ip/unicast.hpp b/3rdparty/asio/include/asio/ip/unicast.hpp index a0b78516372..4d68af877bc 100644 --- a/3rdparty/asio/include/asio/ip/unicast.hpp +++ b/3rdparty/asio/include/asio/ip/unicast.hpp @@ -2,7 +2,7 @@ // ip/unicast.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ip/v6_only.hpp b/3rdparty/asio/include/asio/ip/v6_only.hpp index ff93767f3f2..0fc61213bda 100644 --- a/3rdparty/asio/include/asio/ip/v6_only.hpp +++ b/3rdparty/asio/include/asio/ip/v6_only.hpp @@ -2,7 +2,7 @@ // ip/v6_only.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -26,7 +26,7 @@ namespace ip { /// Socket option for determining whether an IPv6 socket supports IPv6 /// communication only. /** - * Implements the IPPROTO_IPV6/IP_V6ONLY socket option. + * Implements the IPPROTO_IPV6/IPV6_V6ONLY socket option. * * @par Examples * Setting the option: diff --git a/3rdparty/asio/include/asio/is_applicable_property.hpp b/3rdparty/asio/include/asio/is_applicable_property.hpp index c0100e0b1f1..20ca981ad02 100644 --- a/3rdparty/asio/include/asio/is_applicable_property.hpp +++ b/3rdparty/asio/include/asio/is_applicable_property.hpp @@ -2,7 +2,7 @@ // is_applicable_property.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -30,11 +30,11 @@ struct is_applicable_property_trait : false_type template <typename T, typename Property> struct is_applicable_property_trait<T, Property, - typename void_type< - typename enable_if< + void_t< + enable_if_t< !!Property::template is_applicable_property_v<T> - >::type - >::type> : true_type + > + >> : true_type { }; @@ -51,7 +51,7 @@ struct is_applicable_property : #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T, typename Property> -ASIO_CONSTEXPR const bool is_applicable_property_v +constexpr const bool is_applicable_property_v = is_applicable_property<T, Property>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) diff --git a/3rdparty/asio/include/asio/is_contiguous_iterator.hpp b/3rdparty/asio/include/asio/is_contiguous_iterator.hpp new file mode 100644 index 00000000000..a120d4d3761 --- /dev/null +++ b/3rdparty/asio/include/asio/is_contiguous_iterator.hpp @@ -0,0 +1,45 @@ +// +// is_contiguous_iterator.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_IS_CONTIGUOUS_ITERATOR_HPP +#define ASIO_IS_CONTIGUOUS_ITERATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <iterator> +#include "asio/detail/type_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// The is_contiguous_iterator class is a traits class that may be used to +/// determine whether a type is a contiguous iterator. +template <typename T> +struct is_contiguous_iterator : +#if defined(ASIO_HAS_STD_CONCEPTS) \ + || defined(GENERATING_DOCUMENTATION) + integral_constant<bool, std::contiguous_iterator<T>> +#else // defined(ASIO_HAS_STD_CONCEPTS) + // || defined(GENERATING_DOCUMENTATION) + is_pointer<T> +#endif // defined(ASIO_HAS_STD_CONCEPTS) + // || defined(GENERATING_DOCUMENTATION) +{ +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_IS_CONTIGUOUS_ITERATOR_HPP diff --git a/3rdparty/asio/include/asio/is_executor.hpp b/3rdparty/asio/include/asio/is_executor.hpp index 0d5d703be35..2c933a3949c 100644 --- a/3rdparty/asio/include/asio/is_executor.hpp +++ b/3rdparty/asio/include/asio/is_executor.hpp @@ -2,7 +2,7 @@ // is_executor.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/is_read_buffered.hpp b/3rdparty/asio/include/asio/is_read_buffered.hpp index aed333249c3..768f70fb7e1 100644 --- a/3rdparty/asio/include/asio/is_read_buffered.hpp +++ b/3rdparty/asio/include/asio/is_read_buffered.hpp @@ -2,7 +2,7 @@ // is_read_buffered.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/is_write_buffered.hpp b/3rdparty/asio/include/asio/is_write_buffered.hpp index b091d9a05bc..1818fd4b2d5 100644 --- a/3rdparty/asio/include/asio/is_write_buffered.hpp +++ b/3rdparty/asio/include/asio/is_write_buffered.hpp @@ -2,7 +2,7 @@ // is_write_buffered.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/local/basic_endpoint.hpp b/3rdparty/asio/include/asio/local/basic_endpoint.hpp index 11a3c9b5a1f..d363f352531 100644 --- a/3rdparty/asio/include/asio/local/basic_endpoint.hpp +++ b/3rdparty/asio/include/asio/local/basic_endpoint.hpp @@ -2,7 +2,7 @@ // local/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Derived from a public domain implementation written by Daniel Casimiro. // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -60,7 +60,7 @@ public: #endif /// Default constructor. - basic_endpoint() ASIO_NOEXCEPT + basic_endpoint() noexcept { } @@ -90,13 +90,11 @@ public: { } -#if defined(ASIO_HAS_MOVE) /// Move constructor. basic_endpoint(basic_endpoint&& other) : impl_(other.impl_) { } -#endif // defined(ASIO_HAS_MOVE) /// Assign from another endpoint. basic_endpoint& operator=(const basic_endpoint& other) @@ -105,14 +103,12 @@ public: return *this; } -#if defined(ASIO_HAS_MOVE) /// Move-assign from another endpoint. basic_endpoint& operator=(basic_endpoint&& other) { impl_ = other.impl_; return *this; } -#endif // defined(ASIO_HAS_MOVE) /// The protocol associated with the endpoint. protocol_type protocol() const diff --git a/3rdparty/asio/include/asio/local/connect_pair.hpp b/3rdparty/asio/include/asio/local/connect_pair.hpp index 0b22ef44780..b8608e40de5 100644 --- a/3rdparty/asio/include/asio/local/connect_pair.hpp +++ b/3rdparty/asio/include/asio/local/connect_pair.hpp @@ -2,7 +2,7 @@ // local/connect_pair.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/local/datagram_protocol.hpp b/3rdparty/asio/include/asio/local/datagram_protocol.hpp index a147eb8c7f4..6bf18a46e49 100644 --- a/3rdparty/asio/include/asio/local/datagram_protocol.hpp +++ b/3rdparty/asio/include/asio/local/datagram_protocol.hpp @@ -2,7 +2,7 @@ // local/datagram_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -45,19 +45,19 @@ class datagram_protocol { public: /// Obtain an identifier for the type of the protocol. - int type() const ASIO_NOEXCEPT + int type() const noexcept { return SOCK_DGRAM; } /// Obtain an identifier for the protocol. - int protocol() const ASIO_NOEXCEPT + int protocol() const noexcept { return 0; } /// Obtain an identifier for the protocol family. - int family() const ASIO_NOEXCEPT + int family() const noexcept { return AF_UNIX; } diff --git a/3rdparty/asio/include/asio/local/detail/endpoint.hpp b/3rdparty/asio/include/asio/local/detail/endpoint.hpp index 699c225d5a6..5e94c3d0aeb 100644 --- a/3rdparty/asio/include/asio/local/detail/endpoint.hpp +++ b/3rdparty/asio/include/asio/local/detail/endpoint.hpp @@ -2,7 +2,7 @@ // local/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Derived from a public domain implementation written by Daniel Casimiro. // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/3rdparty/asio/include/asio/local/detail/impl/endpoint.ipp b/3rdparty/asio/include/asio/local/detail/impl/endpoint.ipp index 8a254ed6da1..55b403e8ed6 100644 --- a/3rdparty/asio/include/asio/local/detail/impl/endpoint.ipp +++ b/3rdparty/asio/include/asio/local/detail/impl/endpoint.ipp @@ -2,7 +2,7 @@ // local/detail/impl/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Derived from a public domain implementation written by Daniel Casimiro. // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/3rdparty/asio/include/asio/local/seq_packet_protocol.hpp b/3rdparty/asio/include/asio/local/seq_packet_protocol.hpp new file mode 100644 index 00000000000..c5a231fe859 --- /dev/null +++ b/3rdparty/asio/include/asio/local/seq_packet_protocol.hpp @@ -0,0 +1,84 @@ +// +// local/seq_packet_protocol.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_LOCAL_SEQ_PACKET_PROTOCOL_HPP +#define ASIO_LOCAL_SEQ_PACKET_PROTOCOL_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_LOCAL_SOCKETS) \ + || defined(GENERATING_DOCUMENTATION) + +#include "asio/basic_socket_acceptor.hpp" +#include "asio/basic_seq_packet_socket.hpp" +#include "asio/detail/socket_types.hpp" +#include "asio/local/basic_endpoint.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace local { + +/// Encapsulates the flags needed for seq_packet UNIX sockets. +/** + * The asio::local::seq_packet_protocol class contains flags necessary + * for sequenced packet UNIX domain sockets. + * + * @par Thread Safety + * @e Distinct @e objects: Safe.@n + * @e Shared @e objects: Safe. + * + * @par Concepts: + * Protocol. + */ +class seq_packet_protocol +{ +public: + /// Obtain an identifier for the type of the protocol. + int type() const noexcept + { + return SOCK_SEQPACKET; + } + + /// Obtain an identifier for the protocol. + int protocol() const noexcept + { + return 0; + } + + /// Obtain an identifier for the protocol family. + int family() const noexcept + { + return AF_UNIX; + } + + /// The type of a UNIX domain endpoint. + typedef basic_endpoint<seq_packet_protocol> endpoint; + + /// The UNIX domain socket type. + typedef basic_seq_packet_socket<seq_packet_protocol> socket; + + /// The UNIX domain acceptor type. + typedef basic_socket_acceptor<seq_packet_protocol> acceptor; +}; + +} // namespace local +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // defined(ASIO_HAS_LOCAL_SOCKETS) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_LOCAL_SEQ_PACKET_PROTOCOL_HPP diff --git a/3rdparty/asio/include/asio/local/stream_protocol.hpp b/3rdparty/asio/include/asio/local/stream_protocol.hpp index 5f39f2cc3c7..4cbad450fc5 100644 --- a/3rdparty/asio/include/asio/local/stream_protocol.hpp +++ b/3rdparty/asio/include/asio/local/stream_protocol.hpp @@ -2,7 +2,7 @@ // local/stream_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -47,19 +47,19 @@ class stream_protocol { public: /// Obtain an identifier for the type of the protocol. - int type() const ASIO_NOEXCEPT + int type() const noexcept { return SOCK_STREAM; } /// Obtain an identifier for the protocol. - int protocol() const ASIO_NOEXCEPT + int protocol() const noexcept { return 0; } /// Obtain an identifier for the protocol family. - int family() const ASIO_NOEXCEPT + int family() const noexcept { return AF_UNIX; } diff --git a/3rdparty/asio/include/asio/multiple_exceptions.hpp b/3rdparty/asio/include/asio/multiple_exceptions.hpp index f66f8e67132..2fd0455a91a 100644 --- a/3rdparty/asio/include/asio/multiple_exceptions.hpp +++ b/3rdparty/asio/include/asio/multiple_exceptions.hpp @@ -2,7 +2,7 @@ // multiple_exceptions.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -21,9 +21,6 @@ namespace asio { -#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \ - || defined(GENERATING_DOCUMENTATION) - /// Exception thrown when there are multiple pending exceptions to rethrow. class multiple_exceptions : public std::exception @@ -31,11 +28,11 @@ class multiple_exceptions public: /// Constructor. ASIO_DECL multiple_exceptions( - std::exception_ptr first) ASIO_NOEXCEPT; + std::exception_ptr first) noexcept; /// Obtain message associated with exception. ASIO_DECL virtual const char* what() const - ASIO_NOEXCEPT_OR_NOTHROW; + noexcept; /// Obtain a pointer to the first exception. ASIO_DECL std::exception_ptr first_exception() const; @@ -44,9 +41,6 @@ private: std::exception_ptr first_; }; -#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR) - // || defined(GENERATING_DOCUMENTATION) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/packaged_task.hpp b/3rdparty/asio/include/asio/packaged_task.hpp index cd47f66d833..68e5b9b175a 100644 --- a/3rdparty/asio/include/asio/packaged_task.hpp +++ b/3rdparty/asio/include/asio/packaged_task.hpp @@ -2,7 +2,7 @@ // packaged_task.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,15 +23,11 @@ #include "asio/async_result.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" #include "asio/detail/push_options.hpp" namespace asio { -#if defined(ASIO_HAS_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> @@ -60,62 +56,6 @@ private: return_type future_; }; -#else // defined(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 ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \ - template <typename Result, \ - ASIO_VARIADIC_TPARAMS(n), typename Signature> \ - class async_result< \ - std::packaged_task<Result(ASIO_VARIADIC_TARGS(n))>, Signature> \ - { \ - public: \ - typedef std::packaged_task< \ - Result(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_; \ - }; \ - /**/ - ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_RESULT_DEF) -#undef ASIO_PRIVATE_ASYNC_RESULT_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/placeholders.hpp b/3rdparty/asio/include/asio/placeholders.hpp index 9c4a7053fdc..21da545fe9e 100644 --- a/3rdparty/asio/include/asio/placeholders.hpp +++ b/3rdparty/asio/include/asio/placeholders.hpp @@ -2,7 +2,7 @@ // placeholders.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,10 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_BOOST_BIND) -# include <boost/bind/arg.hpp> -#endif // defined(ASIO_HAS_BOOST_BIND) +#include "asio/detail/functional.hpp" #include "asio/detail/push_options.hpp" @@ -28,119 +25,46 @@ namespace placeholders { #if defined(GENERATING_DOCUMENTATION) -/// An argument placeholder, for use with boost::bind(), that corresponds to -/// the error argument of a handler for any of the asynchronous functions. +/// An argument placeholder, for use with std::bind() or boost::bind(), that +/// corresponds to the error argument of a handler for any of the asynchronous +/// functions. unspecified error; -/// An argument placeholder, for use with boost::bind(), that corresponds to -/// the bytes_transferred argument of a handler for asynchronous functions such -/// as asio::basic_stream_socket::async_write_some or +/// An argument placeholder, for use with std::bind() or boost::bind(), that +/// corresponds to the bytes_transferred argument of a handler for asynchronous +/// functions such as asio::basic_stream_socket::async_write_some or /// asio::async_write. 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 -/// asio::async_connect. +/// An argument placeholder, for use with std::bind() or boost::bind(), that +/// corresponds to the iterator argument of a handler for asynchronous functions +/// such as 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 -/// asio::basic_resolver::async_resolve. +/// An argument placeholder, for use with std::bind() or boost::bind(), that +/// corresponds to the results argument of a handler for asynchronous functions +/// such as 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 -/// asio::async_connect. +/// An argument placeholder, for use with std::bind() or boost::bind(), that +/// corresponds to the results argument of a handler for asynchronous functions +/// such as 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 -/// asio::signal_set::async_wait. +/// An argument placeholder, for use with std::bind() or boost::bind(), that +/// corresponds to the signal_number argument of a handler for asynchronous +/// functions such as asio::signal_set::async_wait. unspecified signal_number; -#elif defined(ASIO_HAS_BOOST_BIND) -# if defined(__BORLANDC__) || defined(__GNUC__) - -inline boost::arg<1> error() -{ - return boost::arg<1>(); -} - -inline boost::arg<2> bytes_transferred() -{ - return boost::arg<2>(); -} - -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>(); -} - -# else - -namespace detail -{ - template <int Number> - struct placeholder - { - static boost::arg<Number>& get() - { - static boost::arg<Number> result; - return result; - } - }; -} - -# if defined(ASIO_MSVC) && (ASIO_MSVC < 1400) - -static boost::arg<1>& error - = asio::placeholders::detail::placeholder<1>::get(); -static boost::arg<2>& bytes_transferred - = asio::placeholders::detail::placeholder<2>::get(); -static boost::arg<2>& iterator - = asio::placeholders::detail::placeholder<2>::get(); -static boost::arg<2>& results - = asio::placeholders::detail::placeholder<2>::get(); -static boost::arg<2>& endpoint - = asio::placeholders::detail::placeholder<2>::get(); -static boost::arg<2>& signal_number - = asio::placeholders::detail::placeholder<2>::get(); - -# else - -namespace -{ - boost::arg<1>& error - = asio::placeholders::detail::placeholder<1>::get(); - boost::arg<2>& bytes_transferred - = asio::placeholders::detail::placeholder<2>::get(); - boost::arg<2>& iterator - = asio::placeholders::detail::placeholder<2>::get(); - boost::arg<2>& results - = asio::placeholders::detail::placeholder<2>::get(); - boost::arg<2>& endpoint - = asio::placeholders::detail::placeholder<2>::get(); - boost::arg<2>& signal_number - = asio::placeholders::detail::placeholder<2>::get(); -} // namespace - -# endif -# endif +#else + +static constexpr auto& error = std::placeholders::_1; +static constexpr auto& bytes_transferred = std::placeholders::_2; +static constexpr auto& iterator = std::placeholders::_2; +static constexpr auto& results = std::placeholders::_2; +static constexpr auto& endpoint = std::placeholders::_2; +static constexpr auto& signal_number = std::placeholders::_2; + #endif } // namespace placeholders diff --git a/3rdparty/asio/include/asio/posix/basic_descriptor.hpp b/3rdparty/asio/include/asio/posix/basic_descriptor.hpp index e7152798a4e..fa47d6a0949 100644 --- a/3rdparty/asio/include/asio/posix/basic_descriptor.hpp +++ b/3rdparty/asio/include/asio/posix/basic_descriptor.hpp @@ -2,7 +2,7 @@ // posix/basic_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -20,20 +20,22 @@ #if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \ || defined(GENERATING_DOCUMENTATION) +#include <utility> #include "asio/any_io_executor.hpp" #include "asio/async_result.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/io_object_impl.hpp" #include "asio/detail/non_const_lvalue.hpp" -#include "asio/detail/reactive_descriptor_service.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" #include "asio/posix/descriptor_base.hpp" -#if defined(ASIO_HAS_MOVE) -# include <utility> -#endif // defined(ASIO_HAS_MOVE) +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/io_uring_descriptor_service.hpp" +#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) +# include "asio/detail/reactive_descriptor_service.hpp" +#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #include "asio/detail/push_options.hpp" @@ -53,6 +55,9 @@ template <typename Executor = any_io_executor> class basic_descriptor : public descriptor_base { +private: + class initiate_async_wait; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -68,10 +73,13 @@ public: /// The native representation of a descriptor. #if defined(GENERATING_DOCUMENTATION) typedef implementation_defined native_handle_type; -#else +#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT) + typedef detail::io_uring_descriptor_service::native_handle_type + native_handle_type; +#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) typedef detail::reactive_descriptor_service::native_handle_type native_handle_type; -#endif +#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) /// A descriptor is always the lowest layer. typedef basic_descriptor lowest_layer_type; @@ -99,10 +107,10 @@ public: */ template <typename ExecutionContext> explicit basic_descriptor(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : impl_(0, 0, context) { } @@ -146,9 +154,9 @@ public: template <typename ExecutionContext> basic_descriptor(ExecutionContext& context, const native_handle_type& native_descriptor, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -157,7 +165,6 @@ public: asio::detail::throw_error(ec, "assign"); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a descriptor from another. /** * This constructor moves a descriptor from one object to another. @@ -169,7 +176,7 @@ public: * constructed using the @c basic_descriptor(const executor_type&) * constructor. */ - basic_descriptor(basic_descriptor&& other) ASIO_NOEXCEPT + basic_descriptor(basic_descriptor&& other) noexcept : impl_(std::move(other.impl_)) { } @@ -190,10 +197,57 @@ public: impl_ = std::move(other.impl_); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + // All descriptors have access to each other's implementations. + template <typename Executor1> + friend class basic_descriptor; + + /// Move-construct a basic_descriptor from a descriptor of another executor + /// type. + /** + * This constructor moves a descriptor from one object to another. + * + * @param other The other basic_descriptor object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_descriptor(const executor_type&) + * constructor. + */ + template <typename Executor1> + basic_descriptor(basic_descriptor<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign a basic_descriptor from a descriptor of another executor type. + /** + * This assignment operator moves a descriptor from one object to another. + * + * @param other The other basic_descriptor object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_descriptor(const executor_type&) + * constructor. + */ + template <typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_descriptor& + > operator=(basic_descriptor<Executor1> && other) + { + basic_descriptor tmp(std::move(other)); + impl_ = std::move(tmp.impl_); + return *this; + } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + const executor_type& get_executor() noexcept { return impl_.get_executor(); } @@ -589,21 +643,28 @@ public: /// write, or to have pending error conditions. /** * This function is used to perform an asynchronous wait for a descriptor to - * enter a ready to read, write or error condition state. + * enter a ready to read, write or error condition state. It is an initiating + * function for an @ref asynchronous_operation, and always returns + * immediately. * * @param w Specifies the desired descriptor state. * - * @param handler The handler to be called when the wait operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the wait completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error // Result of operation + * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code) @endcode + * * @par Example * @code * void wait_handler(const asio::error_code& error) @@ -635,15 +696,15 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) - WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler, - void (asio::error_code)) - async_wait(wait_type w, - ASIO_MOVE_ARG(WaitHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return async_initiate<WaitHandler, void (asio::error_code)>( - initiate_async_wait(this), handler, w); + WaitToken = default_completion_token_t<executor_type>> + auto async_wait(wait_type w, + WaitToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WaitToken, void (asio::error_code)>( + declval<initiate_async_wait>(), token, w)) + { + return async_initiate<WaitToken, void (asio::error_code)>( + initiate_async_wait(this), token, w); } protected: @@ -657,12 +718,16 @@ protected: { } +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT) + detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_; +#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT) detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_; +#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) private: // Disallow copying and assignment. - basic_descriptor(const basic_descriptor&) ASIO_DELETED; - basic_descriptor& operator=(const basic_descriptor&) ASIO_DELETED; + basic_descriptor(const basic_descriptor&) = delete; + basic_descriptor& operator=(const basic_descriptor&) = delete; class initiate_async_wait { @@ -674,13 +739,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WaitHandler> - void operator()(ASIO_MOVE_ARG(WaitHandler) handler, wait_type w) const + void operator()(WaitHandler&& handler, wait_type w) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a WaitHandler. diff --git a/3rdparty/asio/include/asio/posix/basic_stream_descriptor.hpp b/3rdparty/asio/include/asio/posix/basic_stream_descriptor.hpp index 7bf4b361020..9868dee1259 100644 --- a/3rdparty/asio/include/asio/posix/basic_stream_descriptor.hpp +++ b/3rdparty/asio/include/asio/posix/basic_stream_descriptor.hpp @@ -2,7 +2,7 @@ // posix/basic_stream_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -48,6 +48,10 @@ template <typename Executor = any_io_executor> class basic_stream_descriptor : public basic_descriptor<Executor> { +private: + class initiate_async_write_some; + class initiate_async_read_some; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -91,10 +95,10 @@ public: */ template <typename ExecutionContext> explicit basic_stream_descriptor(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : basic_descriptor<Executor>(context) { } @@ -134,14 +138,13 @@ public: template <typename ExecutionContext> basic_stream_descriptor(ExecutionContext& context, const native_handle_type& native_descriptor, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_descriptor<Executor>(context, native_descriptor) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a stream descriptor from another. /** * This constructor moves a stream descriptor from one object to another. @@ -153,7 +156,7 @@ public: * constructed using the @c basic_stream_descriptor(const executor_type&) * constructor. */ - basic_stream_descriptor(basic_stream_descriptor&& other) ASIO_NOEXCEPT + basic_stream_descriptor(basic_stream_descriptor&& other) noexcept : basic_descriptor<Executor>(std::move(other)) { } @@ -175,7 +178,50 @@ public: basic_descriptor<Executor>::operator=(std::move(other)); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Move-construct a basic_stream_descriptor from a descriptor of another + /// executor type. + /** + * This constructor moves a descriptor from one object to another. + * + * @param other The other basic_stream_descriptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_descriptor(const executor_type&) + * constructor. + */ + template <typename Executor1> + basic_stream_descriptor(basic_stream_descriptor<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_descriptor<Executor>(std::move(other)) + { + } + + /// Move-assign a basic_stream_descriptor from a descriptor of another + /// executor type. + /** + * This assignment operator moves a descriptor from one object to another. + * + * @param other The other basic_stream_descriptor object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_descriptor(const executor_type&) + * constructor. + */ + template <typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_stream_descriptor& + > operator=(basic_stream_descriptor<Executor1> && other) + { + basic_descriptor<Executor>::operator=(std::move(other)); + return *this; + } /// Write some data to the descriptor. /** @@ -241,25 +287,31 @@ public: /// Start an asynchronous write. /** * This function is used to asynchronously write data to the stream - * descriptor. The function call always returns immediately. + * descriptor. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param buffers One or more data buffers to be written to the descriptor. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. + * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes. @@ -285,17 +337,17 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_write_some(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_write_some(const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + initiate_async_write_some(this), token, buffers)) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_write_some(this), handler, buffers); + initiate_async_write_some(this), token, buffers); } /// Read some data from the descriptor. @@ -364,25 +416,31 @@ public: /// Start an asynchronous read. /** * This function is used to asynchronously read data from the stream - * descriptor. The function call always returns immediately. + * descriptor. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param buffers One or more buffers into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. + * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the * requested amount of data is read before the asynchronous operation @@ -409,17 +467,17 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_read_some(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_read_some(const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_read_some>(), token, buffers)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_read_some(this), handler, buffers); + initiate_async_read_some(this), token, buffers); } private: @@ -433,13 +491,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, const ConstBufferSequence& buffers) const { // If you get an error on the following line it means that your handler @@ -466,13 +524,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, const MutableBufferSequence& buffers) const { // If you get an error on the following line it means that your handler diff --git a/3rdparty/asio/include/asio/posix/descriptor.hpp b/3rdparty/asio/include/asio/posix/descriptor.hpp index 891daa6be68..57b5b2522fd 100644 --- a/3rdparty/asio/include/asio/posix/descriptor.hpp +++ b/3rdparty/asio/include/asio/posix/descriptor.hpp @@ -2,7 +2,7 @@ // posix/descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/posix/descriptor_base.hpp b/3rdparty/asio/include/asio/posix/descriptor_base.hpp index 0f1541abc1f..7bc3bc1e8f6 100644 --- a/3rdparty/asio/include/asio/posix/descriptor_base.hpp +++ b/3rdparty/asio/include/asio/posix/descriptor_base.hpp @@ -2,7 +2,7 @@ // posix/descriptor_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/posix/stream_descriptor.hpp b/3rdparty/asio/include/asio/posix/stream_descriptor.hpp index b07fb035def..4855f10777e 100644 --- a/3rdparty/asio/include/asio/posix/stream_descriptor.hpp +++ b/3rdparty/asio/include/asio/posix/stream_descriptor.hpp @@ -2,7 +2,7 @@ // posix/stream_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/post.hpp b/3rdparty/asio/include/asio/post.hpp index f7e93489349..6b534dfae4a 100644 --- a/3rdparty/asio/include/asio/post.hpp +++ b/3rdparty/asio/include/asio/post.hpp @@ -2,7 +2,7 @@ // post.hpp // ~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -17,10 +17,13 @@ #include "asio/detail/config.hpp" #include "asio/async_result.hpp" +#include "asio/detail/initiate_post.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution_context.hpp" +#include "asio/execution/blocking.hpp" #include "asio/execution/executor.hpp" #include "asio/is_executor.hpp" +#include "asio/require.hpp" #include "asio/detail/push_options.hpp" @@ -35,27 +38,53 @@ namespace asio { * The use of @c post(), rather than @ref defer(), indicates the caller's * preference that the function object be eagerly queued for execution. * - * This function has the following effects: + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Constructs a function object handler of type @c Handler, initialized - * with <tt>handler(forward<CompletionToken>(token))</tt>. + * @returns This function returns <tt>async_initiate<NullaryToken, + * void()>(Init{}, token)</tt>, where @c Init is a function object type defined + * as: * - * @li Constructs an object @c result of type <tt>async_result<Handler></tt>, - * initializing the object as <tt>result(handler)</tt>. + * @code class Init + * { + * public: + * template <typename CompletionHandler> + * void operator()(CompletionHandler&& completion_handler) const; + * }; @endcode * - * @li Obtains the handler's associated executor object @c ex by performing - * <tt>get_associated_executor(handler)</tt>. + * The function call operator of @c Init: * - * @li Obtains the handler's associated allocator object @c alloc by performing - * <tt>get_associated_allocator(handler)</tt>. - * - * @li Performs <tt>ex.post(std::move(handler), alloc)</tt>. + * @li Obtains the handler's associated executor object @c ex of type @c Ex by + * performing @code auto ex = get_associated_executor(handler); @endcode * - * @li Returns <tt>result.get()</tt>. + * @li Obtains the handler's associated allocator object @c alloc by performing + * @code auto alloc = get_associated_allocator(handler); @endcode + * + * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs + * @code prefer( + * require(ex, execution::blocking.never), + * execution::relationship.fork, + * execution::allocator(alloc) + * ).execute(std::forward<CompletionHandler>(completion_handler)); @endcode + * + * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs + * @code ex.post( + * std::forward<CompletionHandler>(completion_handler), + * alloc); @endcode + * + * @par Completion Signature + * @code void() @endcode */ -template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( - ASIO_MOVE_ARG(CompletionToken) token); +template <ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken> +inline auto post(NullaryToken&& token) + -> decltype( + async_initiate<NullaryToken, void()>( + declval<detail::initiate_post>(), token)) +{ + return async_initiate<NullaryToken, void()>( + detail::initiate_post(), token); +} /// Submits a completion token or function object for execution. /** @@ -66,61 +95,119 @@ ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( * The use of @c post(), rather than @ref defer(), indicates the caller's * preference that the function object be eagerly queued for execution. * - * This function has the following effects: + * @param ex The target executor. * - * @li Constructs a function object handler of type @c Handler, initialized - * with <tt>handler(forward<CompletionToken>(token))</tt>. + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode * - * @li Constructs an object @c result of type <tt>async_result<Handler></tt>, - * initializing the object as <tt>result(handler)</tt>. + * @returns This function returns <tt>async_initiate<NullaryToken, + * void()>(Init{ex}, token)</tt>, where @c Init is a function object type + * defined as: * - * @li Obtains the handler's associated executor object @c ex1 by performing - * <tt>get_associated_executor(handler)</tt>. - * - * @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>. + * @code class Init + * { + * public: + * using executor_type = Executor; + * explicit Init(const Executor& ex) : ex_(ex) {} + * executor_type get_executor() const noexcept { return ex_; } + * template <typename CompletionHandler> + * void operator()(CompletionHandler&& completion_handler) const; + * private: + * Executor ex_; // exposition only + * }; @endcode * - * @li 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>. + * The function call operator of @c Init: * - * @li Performs <tt>Executor(ex).post(std::move(f), alloc)</tt>. + * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by + * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode * - * @li Returns <tt>result.get()</tt>. + * @li Obtains the handler's associated allocator object @c alloc by performing + * @code auto alloc = get_associated_allocator(handler); @endcode + * + * @li If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a + * function object @c f with a member @c executor_ that is initialised with + * <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c + * handler_ that is a decay-copy of @c completion_handler, and a function call + * operator that performs: + * @code auto a = get_associated_allocator(handler_); + * prefer(executor_, execution::allocator(a)).execute(std::move(handler_)); + * @endcode + * + * @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a + * function object @c f with a member @c work_ that is initialised with + * <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of + * @c completion_handler, and a function call operator that performs: + * @code auto a = get_associated_allocator(handler_); + * work_.get_executor().dispatch(std::move(handler_), a); + * work_.reset(); @endcode + * + * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs + * @code prefer( + * require(ex, execution::blocking.never), + * execution::relationship.fork, + * execution::allocator(alloc) + * ).execute(std::move(f)); @endcode + * + * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs + * @code ex.post(std::move(f), alloc); @endcode + * + * @par Completion Signature + * @code void() @endcode */ template <typename Executor, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( - const Executor& ex, - ASIO_MOVE_ARG(CompletionToken) token - ASIO_DEFAULT_COMPLETION_TOKEN(Executor), - typename constraint< - execution::is_executor<Executor>::value || is_executor<Executor>::value - >::type = 0); + ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken + = default_completion_token_t<Executor>> +inline auto post(const Executor& ex, + NullaryToken&& token = default_completion_token_t<Executor>(), + constraint_t< + (execution::is_executor<Executor>::value + && can_require<Executor, execution::blocking_t::never_t>::value) + || is_executor<Executor>::value + > = 0) + -> decltype( + async_initiate<NullaryToken, void()>( + declval<detail::initiate_post_with_executor<Executor>>(), token)) +{ + return async_initiate<NullaryToken, void()>( + detail::initiate_post_with_executor<Executor>(ex), token); +} /// Submits a completion token or function object for execution. /** - * @returns <tt>post(ctx.get_executor(), forward<CompletionToken>(token))</tt>. + * @param ctx An execution context, from which the target executor is obtained. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler. The function signature of the completion handler must be: + * @code void handler(); @endcode + * + * @returns <tt>post(ctx.get_executor(), forward<NullaryToken>(token))</tt>. + * + * @par Completion Signature + * @code void() @endcode */ template <typename ExecutionContext, - ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename ExecutionContext::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post( - ExecutionContext& ctx, - ASIO_MOVE_ARG(CompletionToken) token - ASIO_DEFAULT_COMPLETION_TOKEN( - typename ExecutionContext::executor_type), - typename constraint<is_convertible< - ExecutionContext&, execution_context&>::value>::type = 0); + ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken + = default_completion_token_t<typename ExecutionContext::executor_type>> +inline auto post(ExecutionContext& ctx, + NullaryToken&& token = default_completion_token_t< + typename ExecutionContext::executor_type>(), + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) + -> decltype( + async_initiate<NullaryToken, void()>( + declval<detail::initiate_post_with_executor< + typename ExecutionContext::executor_type>>(), token)) +{ + return async_initiate<NullaryToken, void()>( + detail::initiate_post_with_executor< + typename ExecutionContext::executor_type>( + ctx.get_executor()), token); +} } // namespace asio #include "asio/detail/pop_options.hpp" -#include "asio/impl/post.hpp" - #endif // ASIO_POST_HPP diff --git a/3rdparty/asio/include/asio/prefer.hpp b/3rdparty/asio/include/asio/prefer.hpp index 504392cd5d1..3b13d4123bf 100644 --- a/3rdparty/asio/include/asio/prefer.hpp +++ b/3rdparty/asio/include/asio/prefer.hpp @@ -2,7 +2,7 @@ // prefer.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -118,10 +118,10 @@ struct prefer_result namespace asio_prefer_fn { -using asio::conditional; -using asio::decay; +using asio::conditional_t; +using asio::decay_t; using asio::declval; -using asio::enable_if; +using asio::enable_if_t; using asio::is_applicable_property; using asio::traits::prefer_free; using asio::traits::prefer_member; @@ -149,195 +149,187 @@ template <typename Impl, typename T, typename Properties, typename = void, typename = void, typename = void> struct call_traits { - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr overload_type overload = ill_formed; + static constexpr bool is_noexcept = false; typedef void result_type; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_preferable - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_preferable + >, + enable_if_t< static_require<T, Property>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = identity); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - -#if defined(ASIO_HAS_MOVE) - typedef ASIO_MOVE_ARG(T) result_type; -#else // defined(ASIO_HAS_MOVE) - typedef ASIO_MOVE_ARG(typename decay<T>::type) result_type; -#endif // defined(ASIO_HAS_MOVE) + static constexpr overload_type overload = identity; + static constexpr bool is_noexcept = true; + + typedef T&& result_type; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_preferable - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_preferable + >, + enable_if_t< !static_require<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< require_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type> : + >> : require_member<typename Impl::template proxy<T>::type, Property> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_member); + static constexpr overload_type overload = call_require_member; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_preferable - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_preferable + >, + enable_if_t< !static_require<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !require_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< require_free<T, Property>::is_valid - >::type> : + >> : require_free<T, Property> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_free); + static constexpr overload_type overload = call_require_free; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_preferable - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_preferable + >, + enable_if_t< !static_require<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !require_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !require_free<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type> : + >> : prefer_member<typename Impl::template proxy<T>::type, Property> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_member); + static constexpr overload_type overload = call_prefer_member; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_preferable - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_preferable + >, + enable_if_t< !static_require<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !require_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !require_free<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< prefer_free<T, Property>::is_valid - >::type> : + >> : prefer_free<T, Property> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_free); + static constexpr overload_type overload = call_prefer_free; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_preferable - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_preferable + >, + enable_if_t< !static_require<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !require_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !require_free<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !prefer_free<T, Property>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = identity); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - -#if defined(ASIO_HAS_MOVE) - typedef ASIO_MOVE_ARG(T) result_type; -#else // defined(ASIO_HAS_MOVE) - typedef ASIO_MOVE_ARG(typename decay<T>::type) result_type; -#endif // defined(ASIO_HAS_MOVE) + static constexpr overload_type overload = identity; + static constexpr bool is_noexcept = true; + + typedef T&& result_type; }; template <typename Impl, typename T, typename P0, typename P1> struct call_traits<Impl, T, void(P0, P1), - typename enable_if< + enable_if_t< call_traits<Impl, T, void(P0)>::overload != ill_formed - >::type, - typename enable_if< + >, + enable_if_t< call_traits< Impl, typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::overload != ill_formed - >::type> + >> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = two_props); + static constexpr overload_type overload = two_props; - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = + static constexpr bool is_noexcept = ( call_traits<Impl, T, void(P0)>::is_noexcept && @@ -346,51 +338,51 @@ struct call_traits<Impl, T, void(P0, P1), typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::is_noexcept - )); + ); - typedef typename decay< + typedef decay_t< typename call_traits< Impl, typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::result_type - >::type result_type; + > result_type; }; template <typename Impl, typename T, typename P0, - typename P1, typename ASIO_ELLIPSIS PN> -struct call_traits<Impl, T, void(P0, P1, PN ASIO_ELLIPSIS), - typename enable_if< + typename P1, typename... PN> +struct call_traits<Impl, T, void(P0, P1, PN...), + enable_if_t< call_traits<Impl, T, void(P0)>::overload != ill_formed - >::type, - typename enable_if< + >, + enable_if_t< call_traits< Impl, typename call_traits<Impl, T, void(P0)>::result_type, - void(P1, PN ASIO_ELLIPSIS) + void(P1, PN...) >::overload != ill_formed - >::type> + >> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = n_props); + static constexpr overload_type overload = n_props; - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = + static constexpr bool is_noexcept = ( call_traits<Impl, T, void(P0)>::is_noexcept && call_traits< Impl, typename call_traits<Impl, T, void(P0)>::result_type, - void(P1, PN ASIO_ELLIPSIS) + void(P1, PN...) >::is_noexcept - )); + ); - typedef typename decay< + typedef decay_t< typename call_traits< Impl, typename call_traits<Impl, T, void(P0)>::result_type, - void(P1, PN ASIO_ELLIPSIS) + void(P1, PN...) >::result_type - >::type result_type; + > result_type; }; struct impl @@ -403,29 +395,25 @@ struct impl struct type { template <typename P> - auto require(ASIO_MOVE_ARG(P) p) + auto require(P&& p) noexcept( noexcept( - declval<typename conditional<true, T, P>::type>().require( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().require(static_cast<P&&>(p)) ) ) -> decltype( - declval<typename conditional<true, T, P>::type>().require( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().require(static_cast<P&&>(p)) ); template <typename P> - auto prefer(ASIO_MOVE_ARG(P) p) + auto prefer(P&& p) noexcept( noexcept( - declval<typename conditional<true, T, P>::type>().prefer( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().prefer(static_cast<P&&>(p)) ) ) -> decltype( - declval<typename conditional<true, T, P>::type>().prefer( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().prefer(static_cast<P&&>(p)) ); }; #else // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) @@ -436,122 +424,85 @@ struct impl }; template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == identity, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property)) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&&) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return ASIO_MOVE_CAST(T)(t); + return static_cast<T&&>(t); } template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == call_require_member, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property) p) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&& p) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return ASIO_MOVE_CAST(T)(t).require( - ASIO_MOVE_CAST(Property)(p)); + return static_cast<T&&>(t).require(static_cast<Property&&>(p)); } template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == call_require_free, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property) p) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&& p) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return require( - ASIO_MOVE_CAST(T)(t), - ASIO_MOVE_CAST(Property)(p)); + return require(static_cast<T&&>(t), static_cast<Property&&>(p)); } template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == call_prefer_member, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property) p) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&& p) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return ASIO_MOVE_CAST(T)(t).prefer( - ASIO_MOVE_CAST(Property)(p)); + return static_cast<T&&>(t).prefer(static_cast<Property&&>(p)); } template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == call_prefer_free, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property) p) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&& p) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return prefer( - ASIO_MOVE_CAST(T)(t), - ASIO_MOVE_CAST(Property)(p)); + return prefer(static_cast<T&&>(t), static_cast<Property&&>(p)); } template <typename T, typename P0, typename P1> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(P0, P1)>::overload == two_props, typename call_traits<impl, T, void(P0, P1)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(P0) p0, - ASIO_MOVE_ARG(P1) p1) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(P0, P1)>::is_noexcept)) + > + operator()(T&& t, P0&& p0, P1&& p1) const + noexcept(call_traits<impl, T, void(P0, P1)>::is_noexcept) { return (*this)( - (*this)( - ASIO_MOVE_CAST(T)(t), - ASIO_MOVE_CAST(P0)(p0)), - ASIO_MOVE_CAST(P1)(p1)); + (*this)(static_cast<T&&>(t), static_cast<P0&&>(p0)), + static_cast<P1&&>(p1)); } template <typename T, typename P0, typename P1, - typename ASIO_ELLIPSIS PN> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< - call_traits<impl, T, - void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props, - typename call_traits<impl, T, - void(P0, P1, PN ASIO_ELLIPSIS)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(P0) p0, - ASIO_MOVE_ARG(P1) p1, - ASIO_MOVE_ARG(PN) ASIO_ELLIPSIS pn) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept)) + typename... PN> + ASIO_NODISCARD constexpr enable_if_t< + call_traits<impl, T, void(P0, P1, PN...)>::overload == n_props, + typename call_traits<impl, T, void(P0, P1, PN...)>::result_type + > + operator()(T&& t, P0&& p0, P1&& p1, PN&&... pn) const + noexcept(call_traits<impl, T, void(P0, P1, PN...)>::is_noexcept) { return (*this)( - (*this)( - ASIO_MOVE_CAST(T)(t), - ASIO_MOVE_CAST(P0)(p0)), - ASIO_MOVE_CAST(P1)(p1), - ASIO_MOVE_CAST(PN)(pn) ASIO_ELLIPSIS); + (*this)(static_cast<T&&>(t), static_cast<P0&&>(p0)), + static_cast<P1&&>(p1), static_cast<PN&&>(pn)...); } }; @@ -568,15 +519,13 @@ const T static_instance<T>::instance = {}; namespace asio { namespace { -static ASIO_CONSTEXPR const asio_prefer_fn::impl& +static constexpr const asio_prefer_fn::impl& prefer = asio_prefer_fn::static_instance<>::instance; } // namespace typedef asio_prefer_fn::impl prefer_t; -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename T, typename... Properties> struct can_prefer : integral_constant<bool, @@ -586,54 +535,14 @@ struct can_prefer : { }; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T, typename P0 = void, - typename P1 = void, typename P2 = void> -struct can_prefer : - integral_constant<bool, - asio_prefer_fn::call_traits< - prefer_t, T, void(P0, P1, P2)>::overload - != asio_prefer_fn::ill_formed> -{ -}; - -template <typename T, typename P0, typename P1> -struct can_prefer<T, P0, P1> : - integral_constant<bool, - asio_prefer_fn::call_traits< - prefer_t, T, void(P0, P1)>::overload - != asio_prefer_fn::ill_formed> -{ -}; - -template <typename T, typename P0> -struct can_prefer<T, P0> : - integral_constant<bool, - asio_prefer_fn::call_traits< - prefer_t, T, void(P0)>::overload - != asio_prefer_fn::ill_formed> -{ -}; - -template <typename T> -struct can_prefer<T> : - false_type -{ -}; - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - #if defined(ASIO_HAS_VARIABLE_TEMPLATES) -template <typename T, typename ASIO_ELLIPSIS Properties> +template <typename T, typename... Properties> constexpr bool can_prefer_v - = can_prefer<T, Properties ASIO_ELLIPSIS>::value; + = can_prefer<T, Properties...>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename T, typename... Properties> struct is_nothrow_prefer : integral_constant<bool, @@ -642,51 +551,13 @@ struct is_nothrow_prefer : { }; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T, typename P0 = void, - typename P1 = void, typename P2 = void> -struct is_nothrow_prefer : - integral_constant<bool, - asio_prefer_fn::call_traits< - prefer_t, T, void(P0, P1, P2)>::is_noexcept> -{ -}; - -template <typename T, typename P0, typename P1> -struct is_nothrow_prefer<T, P0, P1> : - integral_constant<bool, - asio_prefer_fn::call_traits< - prefer_t, T, void(P0, P1)>::is_noexcept> -{ -}; - -template <typename T, typename P0> -struct is_nothrow_prefer<T, P0> : - integral_constant<bool, - asio_prefer_fn::call_traits< - prefer_t, T, void(P0)>::is_noexcept> -{ -}; - -template <typename T> -struct is_nothrow_prefer<T> : - false_type -{ -}; - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - #if defined(ASIO_HAS_VARIABLE_TEMPLATES) -template <typename T, typename ASIO_ELLIPSIS Properties> -constexpr bool is_nothrow_prefer_v - = is_nothrow_prefer<T, Properties ASIO_ELLIPSIS>::value; +template <typename T, typename... Properties> +constexpr bool is_nothrow_prefer_v = is_nothrow_prefer<T, Properties...>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename T, typename... Properties> struct prefer_result { @@ -694,36 +565,8 @@ struct prefer_result prefer_t, T, void(Properties...)>::result_type type; }; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T, typename P0 = void, - typename P1 = void, typename P2 = void> -struct prefer_result -{ - typedef typename asio_prefer_fn::call_traits< - prefer_t, T, void(P0, P1, P2)>::result_type type; -}; - -template <typename T, typename P0, typename P1> -struct prefer_result<T, P0, P1> -{ - typedef typename asio_prefer_fn::call_traits< - prefer_t, T, void(P0, P1)>::result_type type; -}; - -template <typename T, typename P0> -struct prefer_result<T, P0> -{ - typedef typename asio_prefer_fn::call_traits< - prefer_t, T, void(P0)>::result_type type; -}; - -template <typename T> -struct prefer_result<T> -{ -}; - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) +template <typename T, typename... Properties> +using prefer_result_t = typename prefer_result<T, Properties...>::type; } // namespace asio diff --git a/3rdparty/asio/include/asio/prepend.hpp b/3rdparty/asio/include/asio/prepend.hpp new file mode 100644 index 00000000000..972b47fd300 --- /dev/null +++ b/3rdparty/asio/include/asio/prepend.hpp @@ -0,0 +1,66 @@ +// +// prepend.hpp +// ~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_PREPEND_HPP +#define ASIO_PREPEND_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include <tuple> +#include "asio/detail/type_traits.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// Completion token type used to specify that the completion handler +/// arguments should be passed additional values before the results of the +/// operation. +template <typename CompletionToken, typename... Values> +class prepend_t +{ +public: + /// Constructor. + template <typename T, typename... V> + constexpr explicit prepend_t(T&& completion_token, V&&... values) + : token_(static_cast<T&&>(completion_token)), + values_(static_cast<V&&>(values)...) + { + } + +//private: + CompletionToken token_; + std::tuple<Values...> values_; +}; + +/// Completion token type used to specify that the completion handler +/// arguments should be passed additional values before the results of the +/// operation. +template <typename CompletionToken, typename... Values> +ASIO_NODISCARD inline constexpr +prepend_t<decay_t<CompletionToken>, decay_t<Values>...> +prepend(CompletionToken&& completion_token, + Values&&... values) +{ + return prepend_t<decay_t<CompletionToken>, decay_t<Values>...>( + static_cast<CompletionToken&&>(completion_token), + static_cast<Values&&>(values)...); +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#include "asio/impl/prepend.hpp" + +#endif // ASIO_PREPEND_HPP diff --git a/3rdparty/asio/include/asio/query.hpp b/3rdparty/asio/include/asio/query.hpp index 2312b60320d..c27d26a4030 100644 --- a/3rdparty/asio/include/asio/query.hpp +++ b/3rdparty/asio/include/asio/query.hpp @@ -2,7 +2,7 @@ // query.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -100,10 +100,10 @@ struct query_result namespace asio_query_fn { -using asio::conditional; -using asio::decay; +using asio::conditional_t; +using asio::decay_t; using asio::declval; -using asio::enable_if; +using asio::enable_if_t; using asio::is_applicable_property; using asio::traits::query_free; using asio::traits::query_member; @@ -123,66 +123,66 @@ template <typename Impl, typename T, typename Properties, typename = void, typename = void, typename = void, typename = void> struct call_traits { - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr overload_type overload = ill_formed; + static constexpr bool is_noexcept = false; typedef void result_type; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< + >, + enable_if_t< static_query<T, Property>::is_valid - >::type> : + >> : static_query<T, Property> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = static_value); + static constexpr overload_type overload = static_value; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< + >, + enable_if_t< !static_query<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< query_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type> : + >> : query_member<typename Impl::template proxy<T>::type, Property> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); + static constexpr overload_type overload = call_member; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< + >, + enable_if_t< !static_query<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !query_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< query_free<T, Property>::is_valid - >::type> : + >> : query_free<T, Property> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); + static constexpr overload_type overload = call_free; }; struct impl @@ -194,16 +194,14 @@ struct impl struct type { template <typename P> - auto query(ASIO_MOVE_ARG(P) p) + auto query(P&& p) noexcept( noexcept( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ) ) -> decltype( - declval<typename conditional<true, T, P>::type>().query( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p)) ); }; #else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) @@ -212,48 +210,36 @@ struct impl }; template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == static_value, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T), - ASIO_MOVE_ARG(Property)) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&&, Property&&) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return static_query< - typename decay<T>::type, - typename decay<Property>::type - >::value(); + return static_query<decay_t<T>, decay_t<Property>>::value(); } template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == call_member, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property) p) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&& p) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return ASIO_MOVE_CAST(T)(t).query(ASIO_MOVE_CAST(Property)(p)); + return static_cast<T&&>(t).query(static_cast<Property&&>(p)); } template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == call_free, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property) p) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&& p) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return query(ASIO_MOVE_CAST(T)(t), ASIO_MOVE_CAST(Property)(p)); + return query(static_cast<T&&>(t), static_cast<Property&&>(p)); } }; @@ -270,7 +256,7 @@ const T static_instance<T>::instance = {}; namespace asio { namespace { -static ASIO_CONSTEXPR const asio_query_fn::impl& +static constexpr const asio_query_fn::impl& query = asio_query_fn::static_instance<>::instance; } // namespace @@ -288,8 +274,7 @@ struct can_query : #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T, typename Property> -constexpr bool can_query_v - = can_query<T, Property>::value; +constexpr bool can_query_v = can_query<T, Property>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) @@ -303,8 +288,7 @@ struct is_nothrow_query : #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T, typename Property> -constexpr bool is_nothrow_query_v - = is_nothrow_query<T, Property>::value; +constexpr bool is_nothrow_query_v = is_nothrow_query<T, Property>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) @@ -315,6 +299,9 @@ struct query_result query_t, T, void(Property)>::result_type type; }; +template <typename T, typename Property> +using query_result_t = typename query_result<T, Property>::type; + } // namespace asio #endif // defined(GENERATING_DOCUMENTATION) diff --git a/3rdparty/asio/include/asio/random_access_file.hpp b/3rdparty/asio/include/asio/random_access_file.hpp new file mode 100644 index 00000000000..c638e336394 --- /dev/null +++ b/3rdparty/asio/include/asio/random_access_file.hpp @@ -0,0 +1,35 @@ +// +// random_access_file.hpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_RANDOM_ACCESS_FILE_HPP +#define ASIO_RANDOM_ACCESS_FILE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_FILE) \ + || defined(GENERATING_DOCUMENTATION) + +#include "asio/basic_random_access_file.hpp" + +namespace asio { + +/// Typedef for the typical usage of a random-access file. +typedef basic_random_access_file<> random_access_file; + +} // namespace asio + +#endif // defined(ASIO_HAS_FILE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_RANDOM_ACCESS_FILE_HPP diff --git a/3rdparty/asio/include/asio/read.hpp b/3rdparty/asio/include/asio/read.hpp index 3d666adb8d3..0eb966af36f 100644 --- a/3rdparty/asio/include/asio/read.hpp +++ b/3rdparty/asio/include/asio/read.hpp @@ -2,7 +2,7 @@ // read.hpp // ~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,6 +19,7 @@ #include <cstddef> #include "asio/async_result.hpp" #include "asio/buffer.hpp" +#include "asio/completion_condition.hpp" #include "asio/error.hpp" #if !defined(ASIO_NO_EXTENSIONS) @@ -28,6 +29,15 @@ #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { + +template <typename> class initiate_async_read; +#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) +template <typename> class initiate_async_read_dynbuf_v1; +#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1) +template <typename> class initiate_async_read_dynbuf_v2; + +} // namespace detail /** * @defgroup read asio::read @@ -75,9 +85,9 @@ namespace asio { */ template <typename SyncReadStream, typename MutableBufferSequence> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, - typename constraint< + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type = 0); + > = 0); /// Attempt to read a certain amount of data from a stream before returning. /** @@ -118,9 +128,9 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, template <typename SyncReadStream, typename MutableBufferSequence> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, asio::error_code& ec, - typename constraint< + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type = 0); + > = 0); /// Attempt to read a certain amount of data from a stream before returning. /** @@ -172,9 +182,9 @@ template <typename SyncReadStream, typename MutableBufferSequence, typename CompletionCondition> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition, - typename constraint< + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type = 0); + > = 0); /// Attempt to read a certain amount of data from a stream before returning. /** @@ -219,9 +229,9 @@ template <typename SyncReadStream, typename MutableBufferSequence, typename CompletionCondition> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type = 0); + > = 0); #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -254,13 +264,13 @@ std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers, */ template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + DynamicBuffer_v1&& buffers, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); /// Attempt to read a certain amount of data from a stream before returning. /** @@ -290,14 +300,14 @@ std::size_t read(SyncReadStream& s, */ template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); /// Attempt to read a certain amount of data from a stream before returning. /** @@ -338,14 +348,14 @@ std::size_t read(SyncReadStream& s, template <typename SyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t read(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, CompletionCondition completion_condition, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); /// Attempt to read a certain amount of data from a stream before returning. /** @@ -387,14 +397,14 @@ std::size_t read(SyncReadStream& s, template <typename SyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t read(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM) @@ -572,9 +582,9 @@ std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b, */ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /// Attempt to read a certain amount of data from a stream before returning. /** @@ -605,9 +615,9 @@ std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /// Attempt to read a certain amount of data from a stream before returning. /** @@ -649,9 +659,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2, typename CompletionCondition> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /// Attempt to read a certain amount of data from a stream before returning. /** @@ -694,9 +704,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2, typename CompletionCondition> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /*@}*/ /** @@ -711,9 +721,9 @@ std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, /// stream. /** * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: + * data from a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The supplied buffers are full. That is, the bytes transferred is equal to * the sum of the buffer sizes. @@ -733,25 +743,30 @@ std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, * of the buffer sizes indicates the maximum number of bytes to read from the * stream. Although the buffers object may be copied as necessary, ownership of * the underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To read into a single data buffer use the @ref buffer function as follows: * @code @@ -780,26 +795,27 @@ std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers, */ template <typename AsyncReadStream, typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read<AsyncReadStream>>(), + token, buffers, transfer_all())); /// Start an asynchronous operation to read a certain amount of data from a /// stream. /** * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: + * data from a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The supplied buffers are full. That is, the bytes transferred is equal to * the sum of the buffer sizes. @@ -813,7 +829,7 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, * of the buffer sizes indicates the maximum number of bytes to read from the * stream. Although the buffers object may be copied as necessary, ownership of * the underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object @@ -829,23 +845,28 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, * return value indicates the maximum number of bytes to be read on the next * call to the stream's async_read_some function. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To read into a single data buffer use the @ref buffer function as follows: * @code asio::async_read(s, @@ -870,19 +891,21 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, template <typename AsyncReadStream, typename MutableBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< is_mutable_buffer_sequence<MutableBufferSequence>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read<AsyncReadStream>>(), + token, buffers, + static_cast<CompletionCondition&&>(completion_condition))); #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -890,9 +913,9 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, /// stream. /** * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: + * data from a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The specified dynamic buffer sequence is full (that is, it has reached * maximum size). @@ -911,25 +934,30 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note This overload is equivalent to calling: * @code asio::async_read( * s, buffers, @@ -949,30 +977,30 @@ async_read(AsyncReadStream& s, const MutableBufferSequence& buffers, */ template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read(AsyncReadStream& s, DynamicBuffer_v1&& buffers, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), transfer_all())); /// Start an asynchronous operation to read a certain amount of data from a /// stream. /** * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: + * data from a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The specified dynamic buffer sequence is full (that is, it has reached * maximum size). @@ -991,7 +1019,7 @@ async_read(AsyncReadStream& s, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object @@ -1007,23 +1035,28 @@ async_read(AsyncReadStream& s, * return value indicates the maximum number of bytes to be read on the next * call to the stream's async_read_some function. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -1038,23 +1071,24 @@ async_read(AsyncReadStream& s, template <typename AsyncReadStream, typename DynamicBuffer_v1, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read(AsyncReadStream& s, DynamicBuffer_v1&& buffers, CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition))); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM) @@ -1063,9 +1097,9 @@ async_read(AsyncReadStream& s, /// stream. /** * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: + * data from a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The supplied buffer is full (that is, it has reached maximum size). * @@ -1082,25 +1116,30 @@ async_read(AsyncReadStream& s, * * @param b A basic_streambuf object into which the data will be read. Ownership * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. + * remains valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note This overload is equivalent to calling: * @code asio::async_read( * s, b, @@ -1120,23 +1159,24 @@ async_read(AsyncReadStream& s, */ template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type)); + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), transfer_all())); /// Start an asynchronous operation to read a certain amount of data from a /// stream. /** * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: + * data from a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The supplied buffer is full (that is, it has reached maximum size). * @@ -1153,7 +1193,7 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, * * @param b A basic_streambuf object into which the data will be read. Ownership * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. + * remains valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object @@ -1169,23 +1209,28 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, * return value indicates the maximum number of bytes to be read on the next * call to the stream's async_read_some function. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -1200,16 +1245,18 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, template <typename AsyncReadStream, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type)); + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), + static_cast<CompletionCondition&&>(completion_condition))); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS) @@ -1219,9 +1266,9 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, /// stream. /** * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: + * data from a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The specified dynamic buffer sequence is full (that is, it has reached * maximum size). @@ -1240,25 +1287,30 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note This overload is equivalent to calling: * @code asio::async_read( * s, buffers, @@ -1278,26 +1330,27 @@ async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b, */ template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), transfer_all())); /// Start an asynchronous operation to read a certain amount of data from a /// stream. /** * This function is used to asynchronously read a certain number of bytes of - * data from a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions is - * true: + * data from a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The specified dynamic buffer sequence is full (that is, it has reached * maximum size). @@ -1316,7 +1369,7 @@ async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object @@ -1332,23 +1385,28 @@ async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, * return value indicates the maximum number of bytes to be read on the next * call to the stream's async_read_some function. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes copied into the - * // buffers. If an error occurred, - * // this will be the number of - * // bytes successfully transferred - * // prior to the error. + * // Number of bytes copied into the buffers. If an error + * // occurred, this will be the number of bytes successfully + * // transferred prior to the error. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -1363,19 +1421,21 @@ async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, template <typename AsyncReadStream, typename DynamicBuffer_v2, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition))); /*@}*/ diff --git a/3rdparty/asio/include/asio/read_at.hpp b/3rdparty/asio/include/asio/read_at.hpp index 2b94845c581..09a0b22e12e 100644 --- a/3rdparty/asio/include/asio/read_at.hpp +++ b/3rdparty/asio/include/asio/read_at.hpp @@ -2,7 +2,7 @@ // read_at.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include <cstddef> #include "asio/async_result.hpp" +#include "asio/completion_condition.hpp" #include "asio/detail/cstdint.hpp" #include "asio/error.hpp" @@ -28,6 +29,14 @@ #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { + +template <typename> class initiate_async_read_at; +#if !defined(ASIO_NO_IOSTREAM) +template <typename> class initiate_async_read_at_streambuf; +#endif // !defined(ASIO_NO_IOSTREAM) + +} // namespace detail /** * @defgroup read_at asio::read_at @@ -403,9 +412,10 @@ std::size_t read_at(SyncRandomAccessReadDevice& d, /// specified offset. /** * This function is used to asynchronously read a certain number of bytes of - * data from a random access device at the specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: + * data from a random access device at the specified offset. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. The asynchronous operation will continue until one of the + * following conditions is true: * * @li The supplied buffers are full. That is, the bytes transferred is equal to * the sum of the buffer sizes. @@ -424,11 +434,13 @@ std::size_t read_at(SyncRandomAccessReadDevice& d, * of the buffer sizes indicates the maximum number of bytes to read from the * device. Although the buffers object may be copied as necessary, ownership of * the underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -439,10 +451,13 @@ std::size_t read_at(SyncRandomAccessReadDevice& d, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To read into a single data buffer use the @ref buffer function as follows: * @code @@ -471,24 +486,26 @@ std::size_t read_at(SyncRandomAccessReadDevice& d, */ template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncRandomAccessReadDevice::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, - const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncRandomAccessReadDevice::executor_type)); + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncRandomAccessReadDevice::executor_type>> +auto async_read_at(AsyncRandomAccessReadDevice& d, + uint64_t offset, const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t< + typename AsyncRandomAccessReadDevice::executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice>>(), + token, offset, buffers, transfer_all())); /// Start an asynchronous operation to read a certain amount of data at the /// specified offset. /** * This function is used to asynchronously read a certain number of bytes of - * data from a random access device at the specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: + * data from a random access device at the specified offset. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. The asynchronous operation will continue until one of the + * following conditions is true: * * @li The supplied buffers are full. That is, the bytes transferred is equal to * the sum of the buffer sizes. @@ -504,7 +521,7 @@ async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, * of the buffer sizes indicates the maximum number of bytes to read from the * device. Although the buffers object may be copied as necessary, ownership of * the underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object @@ -520,9 +537,11 @@ async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, * return value indicates the maximum number of bytes to be read on the next * call to the device's async_read_some_at function. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -533,10 +552,13 @@ async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To read into a single data buffer use the @ref buffer function as follows: * @code asio::async_read_at(d, 42, @@ -561,17 +583,19 @@ async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncRandomAccessReadDevice::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_at(AsyncRandomAccessReadDevice& d, + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncRandomAccessReadDevice::executor_type>> +auto async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, const MutableBufferSequence& buffers, CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncRandomAccessReadDevice::executor_type)); + ReadToken&& token = default_completion_token_t< + typename AsyncRandomAccessReadDevice::executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice>>(), + token, offset, buffers, + static_cast<CompletionCondition&&>(completion_condition))); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM) @@ -580,9 +604,10 @@ async_read_at(AsyncRandomAccessReadDevice& d, /// specified offset. /** * This function is used to asynchronously read a certain number of bytes of - * data from a random access device at the specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: + * data from a random access device at the specified offset. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. The asynchronous operation will continue until one of the + * following conditions is true: * * @li An error occurred. * @@ -596,11 +621,13 @@ async_read_at(AsyncRandomAccessReadDevice& d, * * @param b A basic_streambuf object into which the data will be read. Ownership * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. + * remains valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -611,10 +638,13 @@ async_read_at(AsyncRandomAccessReadDevice& d, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note This overload is equivalent to calling: * @code asio::async_read_at( * d, 42, b, @@ -634,24 +664,27 @@ async_read_at(AsyncRandomAccessReadDevice& d, */ template <typename AsyncRandomAccessReadDevice, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncRandomAccessReadDevice::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_at(AsyncRandomAccessReadDevice& d, + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncRandomAccessReadDevice::executor_type>> +auto async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, basic_streambuf<Allocator>& b, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncRandomAccessReadDevice::executor_type)); + ReadToken&& token = default_completion_token_t< + typename AsyncRandomAccessReadDevice::executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_at_streambuf< + AsyncRandomAccessReadDevice>>(), + token, offset, &b, transfer_all())); /// Start an asynchronous operation to read a certain amount of data at the /// specified offset. /** * This function is used to asynchronously read a certain number of bytes of - * data from a random access device at the specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: + * data from a random access device at the specified offset. It is an + * initiating function for an @ref asynchronous_operation, and always returns + * immediately. The asynchronous operation will continue until one of the + * following conditions is true: * * @li The completion_condition function object returns 0. * @@ -665,7 +698,7 @@ async_read_at(AsyncRandomAccessReadDevice& d, * * @param b A basic_streambuf object into which the data will be read. Ownership * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. + * remains valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the read operation is complete. The signature of the function object @@ -681,9 +714,11 @@ async_read_at(AsyncRandomAccessReadDevice& d, * return value indicates the maximum number of bytes to be read on the next * call to the device's async_read_some_at function. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -694,10 +729,13 @@ async_read_at(AsyncRandomAccessReadDevice& d, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -712,17 +750,19 @@ async_read_at(AsyncRandomAccessReadDevice& d, template <typename AsyncRandomAccessReadDevice, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncRandomAccessReadDevice::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_at(AsyncRandomAccessReadDevice& d, - uint64_t offset, basic_streambuf<Allocator>& b, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncRandomAccessReadDevice::executor_type)); + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncRandomAccessReadDevice::executor_type>> +auto async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset, + basic_streambuf<Allocator>& b, CompletionCondition completion_condition, + ReadToken&& token = default_completion_token_t< + typename AsyncRandomAccessReadDevice::executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_at_streambuf< + AsyncRandomAccessReadDevice>>(), + token, offset, &b, + static_cast<CompletionCondition&&>(completion_condition))); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS) diff --git a/3rdparty/asio/include/asio/read_until.hpp b/3rdparty/asio/include/asio/read_until.hpp index bb1767ed6a6..97abbdbf0ea 100644 --- a/3rdparty/asio/include/asio/read_until.hpp +++ b/3rdparty/asio/include/asio/read_until.hpp @@ -2,7 +2,7 @@ // read_until.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -32,19 +32,34 @@ #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { -namespace detail +char (&has_result_type_helper(...))[2]; + +template <typename T> +char has_result_type_helper(T*, typename T::result_type* = 0); + +template <typename T> +struct has_result_type { - char (&has_result_type_helper(...))[2]; + enum { value = (sizeof((has_result_type_helper)((T*)(0))) == 1) }; +}; - template <typename T> - char has_result_type_helper(T*, typename T::result_type* = 0); +#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) +template <typename> class initiate_async_read_until_delim_v1; +template <typename> class initiate_async_read_until_delim_string_v1; +#if defined(ASIO_HAS_BOOST_REGEX) +template <typename> class initiate_async_read_until_expr_v1; +#endif // defined(ASIO_HAS_BOOST_REGEX) +template <typename> class initiate_async_read_until_match_v1; +#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1) +template <typename> class initiate_async_read_until_delim_v2; +template <typename> class initiate_async_read_until_delim_string_v2; +#if defined(ASIO_HAS_BOOST_REGEX) +template <typename> class initiate_async_read_until_expr_v2; +#endif // defined(ASIO_HAS_BOOST_REGEX) +template <typename> class initiate_async_read_until_match_v2; - template <typename T> - struct has_result_type - { - enum { value = (sizeof((has_result_type_helper)((T*)(0))) == 1) }; - }; } // namespace detail /// Type trait used to determine whether a type can be used as a match condition @@ -58,8 +73,7 @@ struct is_match_condition #else enum { - value = asio::is_function< - typename asio::remove_pointer<T>::type>::value + value = asio::is_function<remove_pointer_t<T>>::value || detail::has_result_type<T>::value }; #endif @@ -132,13 +146,13 @@ struct is_match_condition */ template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + DynamicBuffer_v1&& buffers, char delim, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter. @@ -176,14 +190,14 @@ std::size_t read_until(SyncReadStream& s, */ template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, char delim, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter. @@ -238,14 +252,14 @@ std::size_t read_until(SyncReadStream& s, */ template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, ASIO_STRING_VIEW_PARAM delim, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter. @@ -283,15 +297,15 @@ std::size_t read_until(SyncReadStream& s, */ template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \ @@ -351,16 +365,15 @@ std::size_t read_until(SyncReadStream& s, * 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_v1> -std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - const boost::regex& expr, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); +template <typename SyncReadStream, typename DynamicBuffer_v1, typename Traits> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v1&& buffers, + const boost::basic_regex<char, Traits>& expr, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); /// Read data into a dynamic buffer sequence until some part of the data it /// contains matches a regular expression. @@ -398,16 +411,15 @@ std::size_t read_until(SyncReadStream& s, * 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_v1> -std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - const boost::regex& expr, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); +template <typename SyncReadStream, typename DynamicBuffer_v1, typename Traits> +std::size_t read_until(SyncReadStream& s, DynamicBuffer_v1&& buffers, + const boost::basic_regex<char, Traits>& expr, asio::error_code& ec, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); #endif // defined(ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION) @@ -517,17 +529,17 @@ std::size_t read_until(SyncReadStream& s, template <typename SyncReadStream, typename DynamicBuffer_v1, typename MatchCondition> std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, MatchCondition match_condition, - typename constraint< + constraint_t< is_match_condition<MatchCondition>::value - >::type = 0, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + > = 0, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); /// Read data into a dynamic buffer sequence until a function object indicates a /// match. @@ -585,17 +597,17 @@ std::size_t read_until(SyncReadStream& s, template <typename SyncReadStream, typename DynamicBuffer_v1, typename MatchCondition> std::size_t read_until(SyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, MatchCondition match_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_match_condition<MatchCondition>::value - >::type = 0, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + > = 0, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); #if !defined(ASIO_NO_IOSTREAM) @@ -827,9 +839,10 @@ std::size_t read_until(SyncReadStream& s, * This data may be the start of a new line, to be extracted by a subsequent * @c read_until operation. */ -template <typename SyncReadStream, typename Allocator> +template <typename SyncReadStream, typename Allocator, typename Traits> std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf<Allocator>& b, const boost::regex& expr); + asio::basic_streambuf<Allocator>& b, + const boost::basic_regex<char, Traits>& expr); /// Read data into a streambuf until some part of the data it contains matches /// a regular expression. @@ -864,9 +877,10 @@ std::size_t read_until(SyncReadStream& s, * application will typically leave that data in the streambuf for a subsequent * read_until operation to examine. */ -template <typename SyncReadStream, typename Allocator> +template <typename SyncReadStream, typename Allocator, typename Traits> std::size_t read_until(SyncReadStream& s, - asio::basic_streambuf<Allocator>& b, const boost::regex& expr, + asio::basic_streambuf<Allocator>& b, + const boost::basic_regex<char, Traits>& expr, asio::error_code& ec); #endif // defined(ASIO_HAS_BOOST_REGEX) @@ -975,7 +989,7 @@ std::size_t read_until(SyncReadStream& s, template <typename SyncReadStream, typename Allocator, typename MatchCondition> std::size_t read_until(SyncReadStream& s, asio::basic_streambuf<Allocator>& b, MatchCondition match_condition, - typename constraint<is_match_condition<MatchCondition>::value>::type = 0); + constraint_t<is_match_condition<MatchCondition>::value> = 0); /// Read data into a streambuf until a function object indicates a match. /** @@ -1032,7 +1046,7 @@ template <typename SyncReadStream, typename Allocator, typename MatchCondition> std::size_t read_until(SyncReadStream& s, asio::basic_streambuf<Allocator>& b, MatchCondition match_condition, asio::error_code& ec, - typename constraint<is_match_condition<MatchCondition>::value>::type = 0); + constraint_t<is_match_condition<MatchCondition>::value> = 0); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS) @@ -1093,9 +1107,9 @@ std::size_t read_until(SyncReadStream& s, */ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter. @@ -1134,9 +1148,9 @@ std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim, template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter. @@ -1192,9 +1206,9 @@ std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter. @@ -1233,9 +1247,9 @@ std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \ @@ -1295,12 +1309,12 @@ std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, * 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_v2> +template <typename SyncReadStream, typename DynamicBuffer_v2, typename Traits> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, - const boost::regex& expr, - typename constraint< + const boost::basic_regex<char, Traits>& expr, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /// Read data into a dynamic buffer sequence until some part of the data it /// contains matches a regular expression. @@ -1338,12 +1352,12 @@ std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, * 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_v2> +template <typename SyncReadStream, typename DynamicBuffer_v2, typename Traits> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, - const boost::regex& expr, asio::error_code& ec, - typename constraint< + const boost::basic_regex<char, Traits>& expr, asio::error_code& ec, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); #endif // defined(ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION) @@ -1454,12 +1468,12 @@ template <typename SyncReadStream, typename DynamicBuffer_v2, typename MatchCondition> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, MatchCondition match_condition, - typename constraint< + constraint_t< is_match_condition<MatchCondition>::value - >::type = 0, - typename constraint< + > = 0, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /// Read data into a dynamic buffer sequence until a function object indicates a /// match. @@ -1518,12 +1532,12 @@ template <typename SyncReadStream, typename DynamicBuffer_v2, typename MatchCondition> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, MatchCondition match_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_match_condition<MatchCondition>::value - >::type = 0, - typename constraint< + > = 0, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); #endif // !defined(ASIO_NO_EXTENSIONS) @@ -1545,9 +1559,9 @@ std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains the - * specified delimiter. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * specified delimiter. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The get area of the dynamic buffer sequence contains the specified * delimiter. @@ -1568,27 +1582,31 @@ std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param delim The delimiter character. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, * * // The number of bytes in the dynamic buffer sequence's * // get area up to and including the delimiter. - * // 0 if an error occurred. * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond the delimiter. An application * will typically leave that data in the dynamic buffer sequence for a @@ -1635,31 +1653,32 @@ std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, */ template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, + DynamicBuffer_v1&& buffers, char delim, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_v1<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), delim)); /// Start an asynchronous operation to read data into a dynamic buffer sequence /// until it contains a specified delimiter. /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains the - * specified delimiter. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * specified delimiter. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The get area of the dynamic buffer sequence contains the specified * delimiter. @@ -1680,27 +1699,31 @@ async_read_until(AsyncReadStream& s, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param delim The delimiter string. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, * * // The number of bytes in the dynamic buffer sequence's * // get area up to and including the delimiter. - * // 0 if an error occurred. * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond the delimiter. An application * will typically leave that data in the dynamic buffer sequence for a @@ -1747,23 +1770,26 @@ async_read_until(AsyncReadStream& s, */ template <typename AsyncReadStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, + DynamicBuffer_v1&& buffers, ASIO_STRING_VIEW_PARAM delim, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_string_v1< + AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), + static_cast<std::string>(delim))); #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \ @@ -1774,9 +1800,10 @@ async_read_until(AsyncReadStream& s, /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains some - * data that matches a regular expression. The function call always returns - * immediately. The asynchronous operation will continue until one of the - * following conditions is true: + * data that matches a regular expression. It is an initiating function for an + * @ref asynchronous_operation, and always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: * * @li A substring of the dynamic buffer sequence's get area matches the regular * expression. @@ -1798,13 +1825,15 @@ async_read_until(AsyncReadStream& s, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param expr The regular expression. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -1816,10 +1845,13 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond that which matched the regular * expression. An application will typically leave that data in the dynamic @@ -1865,25 +1897,25 @@ async_read_until(AsyncReadStream& s, * if they are also supported by the @c AsyncReadStream type's * @c async_read_some operation. */ -template <typename AsyncReadStream, typename DynamicBuffer_v1, +template <typename AsyncReadStream, typename DynamicBuffer_v1, typename Traits, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - const boost::regex& expr, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, DynamicBuffer_v1&& buffers, + const boost::basic_regex<char, Traits>& expr, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_expr_v1<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), expr)); #endif // defined(ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION) @@ -1894,9 +1926,9 @@ async_read_until(AsyncReadStream& s, * This function is used to asynchronously read data into the specified dynamic * buffer sequence until a user-defined match condition function object, when * applied to the data contained in the dynamic buffer sequence, indicates a - * successful match. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * successful match. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The match condition function object returns a std::pair where the second * element evaluates to true. @@ -1917,7 +1949,7 @@ async_read_until(AsyncReadStream& s, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param match_condition The function object to be called to determine whether * a match exists. The signature of the function object must be: @@ -1934,9 +1966,11 @@ async_read_until(AsyncReadStream& s, * @c second member of the return value is true if a match has been found, false * otherwise. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -1947,8 +1981,8 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * @note After a successful async_read_until operation, the dynamic buffer @@ -1956,6 +1990,9 @@ async_read_until(AsyncReadStream& s, * object. An application will typically leave that data in the dynamic buffer * sequence for a subsequent async_read_until operation to examine. * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The default implementation of the @c is_match_condition type trait * evaluates to true for function pointers and function objects with a * @c result_type typedef. It must be specialised for other user-defined @@ -2030,26 +2067,27 @@ async_read_until(AsyncReadStream& s, template <typename AsyncReadStream, typename DynamicBuffer_v1, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - MatchCondition match_condition, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, + DynamicBuffer_v1&& buffers, MatchCondition match_condition, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< is_match_condition<MatchCondition>::value - >::type = 0, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + > = 0, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_match_v1<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), + match_condition)); #if !defined(ASIO_NO_IOSTREAM) @@ -2058,8 +2096,9 @@ async_read_until(AsyncReadStream& s, /** * This function is used to asynchronously read data into the specified * streambuf until the streambuf's get area contains the specified delimiter. - * The function call always returns immediately. The asynchronous operation - * will continue until one of the following conditions is true: + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. The asynchronous operation will continue until one of + * the following conditions is true: * * @li The get area of the streambuf contains the specified delimiter. * @@ -2078,13 +2117,15 @@ async_read_until(AsyncReadStream& s, * * @param b A streambuf object into which the data will be read. Ownership of * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. + * valid until the completion handler is called. * * @param delim The delimiter character. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -2095,10 +2136,13 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note After a successful async_read_until operation, the streambuf may * contain additional data beyond the delimiter. An application will typically * leave that data in the streambuf for a subsequent async_read_until operation @@ -2144,24 +2188,26 @@ async_read_until(AsyncReadStream& s, */ template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b, char delim, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type)); + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_v1<AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), delim)); /// Start an asynchronous operation to read data into a streambuf until it /// contains a specified delimiter. /** * This function is used to asynchronously read data into the specified * streambuf until the streambuf's get area contains the specified delimiter. - * The function call always returns immediately. The asynchronous operation - * will continue until one of the following conditions is true: + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. The asynchronous operation will continue until one of + * the following conditions is true: * * @li The get area of the streambuf contains the specified delimiter. * @@ -2180,13 +2226,15 @@ async_read_until(AsyncReadStream& s, * * @param b A streambuf object into which the data will be read. Ownership of * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. + * valid until the completion handler is called. * * @param delim The delimiter string. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -2197,10 +2245,13 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note After a successful async_read_until operation, the streambuf may * contain additional data beyond the delimiter. An application will typically * leave that data in the streambuf for a subsequent async_read_until operation @@ -2246,17 +2297,20 @@ async_read_until(AsyncReadStream& s, */ template <typename AsyncReadStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, asio::basic_streambuf<Allocator>& b, ASIO_STRING_VIEW_PARAM delim, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type)); + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_string_v1< + AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), + static_cast<std::string>(delim))); #if defined(ASIO_HAS_BOOST_REGEX) \ || defined(GENERATING_DOCUMENTATION) @@ -2266,9 +2320,9 @@ async_read_until(AsyncReadStream& s, /** * This function is used to asynchronously read data into the specified * streambuf until the streambuf's get area contains some data that matches a - * regular expression. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * regular expression. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li A substring of the streambuf's get area matches the regular expression. * @@ -2288,13 +2342,15 @@ async_read_until(AsyncReadStream& s, * * @param b A streambuf object into which the data will be read. Ownership of * the streambuf is retained by the caller, which must guarantee that it remains - * valid until the handler is called. + * valid until the completion handler is called. * * @param expr The regular expression. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -2306,10 +2362,13 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note After a successful async_read_until operation, the streambuf may * contain additional data beyond that which matched the regular expression. An * application will typically leave that data in the streambuf for a subsequent @@ -2354,18 +2413,20 @@ async_read_until(AsyncReadStream& s, * if they are also supported by the @c AsyncReadStream type's * @c async_read_some operation. */ -template <typename AsyncReadStream, typename Allocator, +template <typename AsyncReadStream, typename Allocator, typename Traits, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - asio::basic_streambuf<Allocator>& b, const boost::regex& expr, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type)); + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, + asio::basic_streambuf<Allocator>& b, + const boost::basic_regex<char, Traits>& expr, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_expr_v1<AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), expr)); #endif // defined(ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION) @@ -2375,9 +2436,10 @@ async_read_until(AsyncReadStream& s, /** * This function is used to asynchronously read data into the specified * streambuf until a user-defined match condition function object, when applied - * to the data contained in the streambuf, indicates a successful match. The - * function call always returns immediately. The asynchronous operation will - * continue until one of the following conditions is true: + * to the data contained in the streambuf, indicates a successful match. It is + * an initiating function for an @ref asynchronous_operation, and always + * returns immediately. The asynchronous operation will continue until one of + * the following conditions is true: * * @li The match condition function object returns a std::pair where the second * element evaluates to true. @@ -2412,9 +2474,11 @@ async_read_until(AsyncReadStream& s, * @c second member of the return value is true if a match has been found, false * otherwise. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -2425,8 +2489,8 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * @note After a successful async_read_until operation, the streambuf may @@ -2434,6 +2498,9 @@ async_read_until(AsyncReadStream& s, * application will typically leave that data in the streambuf for a subsequent * async_read_until operation to examine. * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The default implementation of the @c is_match_condition type trait * evaluates to true for function pointers and function objects with a * @c result_type typedef. It must be specialised for other user-defined @@ -2506,18 +2573,18 @@ async_read_until(AsyncReadStream& s, */ template <typename AsyncReadStream, typename Allocator, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, - asio::basic_streambuf<Allocator>& b, - MatchCondition match_condition, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint<is_match_condition<MatchCondition>::value>::type = 0); + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, + asio::basic_streambuf<Allocator>& b, MatchCondition match_condition, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t<is_match_condition<MatchCondition>::value> = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_match_v1<AsyncReadStream>>(), + token, basic_streambuf_ref<Allocator>(b), match_condition)); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS) @@ -2528,9 +2595,9 @@ async_read_until(AsyncReadStream& s, /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains the - * specified delimiter. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * specified delimiter. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The get area of the dynamic buffer sequence contains the specified * delimiter. @@ -2551,13 +2618,15 @@ async_read_until(AsyncReadStream& s, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param delim The delimiter character. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -2568,10 +2637,13 @@ async_read_until(AsyncReadStream& s, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond the delimiter. An application * will typically leave that data in the dynamic buffer sequence for a @@ -2618,27 +2690,28 @@ async_read_until(AsyncReadStream& s, */ template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, char delim, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, char delim, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_v2<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), delim)); /// Start an asynchronous operation to read data into a dynamic buffer sequence /// until it contains a specified delimiter. /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains the - * specified delimiter. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * specified delimiter. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The get area of the dynamic buffer sequence contains the specified * delimiter. @@ -2659,27 +2732,31 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, char delim, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param delim The delimiter string. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, * * // The number of bytes in the dynamic buffer sequence's * // get area up to and including the delimiter. - * // 0 if an error occurred. * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond the delimiter. An application * will typically leave that data in the dynamic buffer sequence for a @@ -2726,19 +2803,22 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, char delim, */ template <typename AsyncReadStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_delim_string_v2< + AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), + static_cast<std::string>(delim))); #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \ @@ -2749,9 +2829,10 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, /** * This function is used to asynchronously read data into the specified dynamic * buffer sequence until the dynamic buffer sequence's get area contains some - * data that matches a regular expression. The function call always returns - * immediately. The asynchronous operation will continue until one of the - * following conditions is true: + * data that matches a regular expression. It is an initiating function for an + * @ref asynchronous_operation, and always returns immediately. The + * asynchronous operation will continue until one of the following conditions + * is true: * * @li A substring of the dynamic buffer sequence's get area matches the regular * expression. @@ -2773,13 +2854,15 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param expr The regular expression. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -2791,10 +2874,13 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note After a successful async_read_until operation, the dynamic buffer * sequence may contain additional data beyond that which matched the regular * expression. An application will typically leave that data in the dynamic @@ -2840,21 +2926,22 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, * if they are also supported by the @c AsyncReadStream type's * @c async_read_some operation. */ -template <typename AsyncReadStream, typename DynamicBuffer_v2, +template <typename AsyncReadStream, typename DynamicBuffer_v2, typename Traits, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, - const boost::regex& expr, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, + const boost::basic_regex<char, Traits>& expr, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_expr_v2<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), expr)); #endif // defined(ASIO_HAS_BOOST_REGEX) // || defined(GENERATING_DOCUMENTATION) @@ -2865,9 +2952,9 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, * This function is used to asynchronously read data into the specified dynamic * buffer sequence until a user-defined match condition function object, when * applied to the data contained in the dynamic buffer sequence, indicates a - * successful match. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * successful match. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li The match condition function object returns a std::pair where the second * element evaluates to true. @@ -2888,7 +2975,7 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, * @param buffers The dynamic buffer sequence into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param match_condition The function object to be called to determine whether * a match exists. The signature of the function object must be: @@ -2905,9 +2992,11 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, * @c second member of the return value is true if a match has been found, false * otherwise. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -2918,8 +3007,8 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * * @note After a successful async_read_until operation, the dynamic buffer @@ -2927,6 +3016,9 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, * object. An application will typically leave that data in the dynamic buffer * sequence for a subsequent async_read_until operation to examine. * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The default implementation of the @c is_match_condition type trait * evaluates to true for function pointers and function objects with a * @c result_type typedef. It must be specialised for other user-defined @@ -3001,22 +3093,23 @@ async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, template <typename AsyncReadStream, typename DynamicBuffer_v2, typename MatchCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncReadStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) -async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, - MatchCondition match_condition, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncReadStream::executor_type), - typename constraint< + std::size_t)) ReadToken = default_completion_token_t< + typename AsyncReadStream::executor_type>> +auto async_read_until(AsyncReadStream& s, + DynamicBuffer_v2 buffers, MatchCondition match_condition, + ReadToken&& token = default_completion_token_t< + typename AsyncReadStream::executor_type>(), + constraint_t< is_match_condition<MatchCondition>::value - >::type = 0, - typename constraint< + > = 0, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_read_until_match_v2<AsyncReadStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), match_condition)); #endif // !defined(ASIO_NO_EXTENSIONS) diff --git a/3rdparty/asio/include/asio/readable_pipe.hpp b/3rdparty/asio/include/asio/readable_pipe.hpp new file mode 100644 index 00000000000..19101c28702 --- /dev/null +++ b/3rdparty/asio/include/asio/readable_pipe.hpp @@ -0,0 +1,35 @@ +// +// readable_pipe.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_READABLE_PIPE_HPP +#define ASIO_READABLE_PIPE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PIPE) \ + || defined(GENERATING_DOCUMENTATION) + +#include "asio/basic_readable_pipe.hpp" + +namespace asio { + +/// Typedef for the typical usage of a readable pipe. +typedef basic_readable_pipe<> readable_pipe; + +} // namespace asio + +#endif // defined(ASIO_HAS_PIPE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_READABLE_PIPE_HPP diff --git a/3rdparty/asio/include/asio/recycling_allocator.hpp b/3rdparty/asio/include/asio/recycling_allocator.hpp new file mode 100644 index 00000000000..b3986c0242e --- /dev/null +++ b/3rdparty/asio/include/asio/recycling_allocator.hpp @@ -0,0 +1,138 @@ +// +// recycling_allocator.hpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_RECYCLING_ALLOCATOR_HPP +#define ASIO_RECYCLING_ALLOCATOR_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/recycling_allocator.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// An allocator that caches memory blocks in thread-local storage for reuse. +/** + * The @recycling_allocator uses a simple strategy where a limited number of + * small memory blocks are cached in thread-local storage, if the current + * thread is running an @c io_context or is part of a @c thread_pool. + */ +template <typename T> +class recycling_allocator +{ +public: + /// The type of object allocated by the recycling allocator. + typedef T value_type; + + /// Rebind the allocator to another value_type. + template <typename U> + struct rebind + { + /// The rebound @c allocator type. + typedef recycling_allocator<U> other; + }; + + /// Default constructor. + constexpr recycling_allocator() noexcept + { + } + + /// Converting constructor. + template <typename U> + constexpr recycling_allocator( + const recycling_allocator<U>&) noexcept + { + } + + /// Equality operator. Always returns true. + constexpr bool operator==( + const recycling_allocator&) const noexcept + { + return true; + } + + /// Inequality operator. Always returns false. + constexpr bool operator!=( + const recycling_allocator&) const noexcept + { + return false; + } + + /// Allocate memory for the specified number of values. + T* allocate(std::size_t n) + { + return detail::recycling_allocator<T>().allocate(n); + } + + /// Deallocate memory for the specified number of values. + void deallocate(T* p, std::size_t n) + { + detail::recycling_allocator<T>().deallocate(p, n); + } +}; + +/// A proto-allocator that caches memory blocks in thread-local storage for +/// reuse. +/** + * The @recycling_allocator uses a simple strategy where a limited number of + * small memory blocks are cached in thread-local storage, if the current + * thread is running an @c io_context or is part of a @c thread_pool. + */ +template <> +class recycling_allocator<void> +{ +public: + /// No values are allocated by a proto-allocator. + typedef void value_type; + + /// Rebind the allocator to another value_type. + template <typename U> + struct rebind + { + /// The rebound @c allocator type. + typedef recycling_allocator<U> other; + }; + + /// Default constructor. + constexpr recycling_allocator() noexcept + { + } + + /// Converting constructor. + template <typename U> + constexpr recycling_allocator( + const recycling_allocator<U>&) noexcept + { + } + + /// Equality operator. Always returns true. + constexpr bool operator==( + const recycling_allocator&) const noexcept + { + return true; + } + + /// Inequality operator. Always returns false. + constexpr bool operator!=( + const recycling_allocator&) const noexcept + { + return false; + } +}; + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_RECYCLING_ALLOCATOR_HPP diff --git a/3rdparty/asio/include/asio/redirect_error.hpp b/3rdparty/asio/include/asio/redirect_error.hpp index 57389dd97af..524bd0b99a1 100644 --- a/3rdparty/asio/include/asio/redirect_error.hpp +++ b/3rdparty/asio/include/asio/redirect_error.hpp @@ -2,7 +2,7 @@ // redirect_error.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -23,7 +23,7 @@ namespace asio { -/// Completion token type used to specify that an error produced by an +/// A @ref completion_token adapter used to specify that an error produced by an /// asynchronous operation is captured to an error_code variable. /** * The redirect_error_t class is used to indicate that any error_code produced @@ -35,9 +35,8 @@ class redirect_error_t public: /// Constructor. template <typename T> - redirect_error_t(ASIO_MOVE_ARG(T) completion_token, - asio::error_code& ec) - : token_(ASIO_MOVE_CAST(T)(completion_token)), + redirect_error_t(T&& completion_token, asio::error_code& ec) + : token_(static_cast<T&&>(completion_token)), ec_(ec) { } @@ -47,14 +46,13 @@ public: asio::error_code& ec_; }; -/// Create a completion token to capture error_code values to a variable. +/// Adapt a @ref completion_token to capture error_code values to a variable. template <typename CompletionToken> -inline redirect_error_t<typename decay<CompletionToken>::type> redirect_error( - ASIO_MOVE_ARG(CompletionToken) completion_token, - asio::error_code& ec) +inline redirect_error_t<decay_t<CompletionToken>> redirect_error( + CompletionToken&& completion_token, asio::error_code& ec) { - return redirect_error_t<typename decay<CompletionToken>::type>( - ASIO_MOVE_CAST(CompletionToken)(completion_token), ec); + return redirect_error_t<decay_t<CompletionToken>>( + static_cast<CompletionToken&&>(completion_token), ec); } } // namespace asio diff --git a/3rdparty/asio/include/asio/registered_buffer.hpp b/3rdparty/asio/include/asio/registered_buffer.hpp new file mode 100644 index 00000000000..f563277b30a --- /dev/null +++ b/3rdparty/asio/include/asio/registered_buffer.hpp @@ -0,0 +1,344 @@ +// +// registered_buffer.hpp +// ~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_REGISTERED_BUFFER_HPP +#define ASIO_REGISTERED_BUFFER_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/buffer.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { +namespace detail { + +class buffer_registration_base; + +} // namespace detail + +class const_registered_buffer; + +/// Type used to identify a registered buffer. +class registered_buffer_id +{ +public: + /// The native buffer identifier type. + typedef int native_handle_type; + + /// Default constructor creates an invalid registered buffer identifier. + registered_buffer_id() noexcept + : scope_(0), + index_(-1) + { + } + + /// Get the native buffer identifier type. + native_handle_type native_handle() const noexcept + { + return index_; + } + + /// Compare two IDs for equality. + friend bool operator==(const registered_buffer_id& lhs, + const registered_buffer_id& rhs) noexcept + { + return lhs.scope_ == rhs.scope_ && lhs.index_ == rhs.index_; + } + + /// Compare two IDs for equality. + friend bool operator!=(const registered_buffer_id& lhs, + const registered_buffer_id& rhs) noexcept + { + return lhs.scope_ != rhs.scope_ || lhs.index_ != rhs.index_; + } + +private: + friend class detail::buffer_registration_base; + + // Hidden constructor used by buffer registration. + registered_buffer_id(const void* scope, int index) noexcept + : scope_(scope), + index_(index) + { + } + + const void* scope_; + int index_; +}; + +/// Holds a registered buffer over modifiable data. +/** + * Satisfies the @c MutableBufferSequence type requirements. + */ +class mutable_registered_buffer +{ +public: + /// Default constructor creates an invalid registered buffer. + mutable_registered_buffer() noexcept + : buffer_(), + id_() + { + } + + /// Get the underlying mutable buffer. + const mutable_buffer& buffer() const noexcept + { + return buffer_; + } + + /// Get a pointer to the beginning of the memory range. + /** + * @returns <tt>buffer().data()</tt>. + */ + void* data() const noexcept + { + return buffer_.data(); + } + + /// Get the size of the memory range. + /** + * @returns <tt>buffer().size()</tt>. + */ + std::size_t size() const noexcept + { + return buffer_.size(); + } + + /// Get the registered buffer identifier. + const registered_buffer_id& id() const noexcept + { + return id_; + } + + /// Move the start of the buffer by the specified number of bytes. + mutable_registered_buffer& operator+=(std::size_t n) noexcept + { + buffer_ += n; + return *this; + } + +private: + friend class detail::buffer_registration_base; + + // Hidden constructor used by buffer registration and operators. + mutable_registered_buffer(const mutable_buffer& b, + const registered_buffer_id& i) noexcept + : buffer_(b), + id_(i) + { + } + +#if !defined(GENERATING_DOCUMENTATION) + friend mutable_registered_buffer buffer( + const mutable_registered_buffer& b, std::size_t n) noexcept; +#endif // !defined(GENERATING_DOCUMENTATION) + + mutable_buffer buffer_; + registered_buffer_id id_; +}; + +/// Holds a registered buffer over non-modifiable data. +/** + * Satisfies the @c ConstBufferSequence type requirements. + */ +class const_registered_buffer +{ +public: + /// Default constructor creates an invalid registered buffer. + const_registered_buffer() noexcept + : buffer_(), + id_() + { + } + + /// Construct a non-modifiable buffer from a modifiable one. + const_registered_buffer( + const mutable_registered_buffer& b) noexcept + : buffer_(b.buffer()), + id_(b.id()) + { + } + + /// Get the underlying constant buffer. + const const_buffer& buffer() const noexcept + { + return buffer_; + } + + /// Get a pointer to the beginning of the memory range. + /** + * @returns <tt>buffer().data()</tt>. + */ + const void* data() const noexcept + { + return buffer_.data(); + } + + /// Get the size of the memory range. + /** + * @returns <tt>buffer().size()</tt>. + */ + std::size_t size() const noexcept + { + return buffer_.size(); + } + + /// Get the registered buffer identifier. + const registered_buffer_id& id() const noexcept + { + return id_; + } + + /// Move the start of the buffer by the specified number of bytes. + const_registered_buffer& operator+=(std::size_t n) noexcept + { + buffer_ += n; + return *this; + } + +private: + // Hidden constructor used by operators. + const_registered_buffer(const const_buffer& b, + const registered_buffer_id& i) noexcept + : buffer_(b), + id_(i) + { + } + +#if !defined(GENERATING_DOCUMENTATION) + friend const_registered_buffer buffer( + const const_registered_buffer& b, std::size_t n) noexcept; +#endif // !defined(GENERATING_DOCUMENTATION) + + const_buffer buffer_; + registered_buffer_id id_; +}; + +/** @addtogroup buffer_sequence_begin */ + +/// Get an iterator to the first element in a buffer sequence. +inline const mutable_buffer* buffer_sequence_begin( + const mutable_registered_buffer& b) noexcept +{ + return &b.buffer(); +} + +/// Get an iterator to the first element in a buffer sequence. +inline const const_buffer* buffer_sequence_begin( + const const_registered_buffer& b) noexcept +{ + return &b.buffer(); +} + +/** @} */ +/** @addtogroup buffer_sequence_end */ + +/// Get an iterator to one past the end element in a buffer sequence. +inline const mutable_buffer* buffer_sequence_end( + const mutable_registered_buffer& b) noexcept +{ + return &b.buffer() + 1; +} + +/// Get an iterator to one past the end element in a buffer sequence. +inline const const_buffer* buffer_sequence_end( + const const_registered_buffer& b) noexcept +{ + return &b.buffer() + 1; +} + +/** @} */ +/** @addtogroup buffer */ + +/// Obtain a buffer representing the entire registered buffer. +inline mutable_registered_buffer buffer( + const mutable_registered_buffer& b) noexcept +{ + return b; +} + +/// Obtain a buffer representing the entire registered buffer. +inline const_registered_buffer buffer( + const const_registered_buffer& b) noexcept +{ + return b; +} + +/// Obtain a buffer representing part of a registered buffer. +inline mutable_registered_buffer buffer( + const mutable_registered_buffer& b, std::size_t n) noexcept +{ + return mutable_registered_buffer(buffer(b.buffer_, n), b.id_); +} + +/// Obtain a buffer representing part of a registered buffer. +inline const_registered_buffer buffer( + const const_registered_buffer& b, std::size_t n) noexcept +{ + return const_registered_buffer(buffer(b.buffer_, n), b.id_); +} + +/** @} */ + +/// Create a new modifiable registered buffer that is offset from the start of +/// another. +/** + * @relates mutable_registered_buffer + */ +inline mutable_registered_buffer operator+( + const mutable_registered_buffer& b, std::size_t n) noexcept +{ + mutable_registered_buffer tmp(b); + tmp += n; + return tmp; +} + +/// Create a new modifiable buffer that is offset from the start of another. +/** + * @relates mutable_registered_buffer + */ +inline mutable_registered_buffer operator+(std::size_t n, + const mutable_registered_buffer& b) noexcept +{ + return b + n; +} + +/// Create a new non-modifiable registered buffer that is offset from the start +/// of another. +/** + * @relates const_registered_buffer + */ +inline const_registered_buffer operator+(const const_registered_buffer& b, + std::size_t n) noexcept +{ + const_registered_buffer tmp(b); + tmp += n; + return tmp; +} + +/// Create a new non-modifiable buffer that is offset from the start of another. +/** + * @relates const_registered_buffer + */ +inline const_registered_buffer operator+(std::size_t n, + const const_registered_buffer& b) noexcept +{ + return b + n; +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_REGISTERED_BUFFER_HPP diff --git a/3rdparty/asio/include/asio/require.hpp b/3rdparty/asio/include/asio/require.hpp index c8b40fce959..609e54fcaa3 100644 --- a/3rdparty/asio/include/asio/require.hpp +++ b/3rdparty/asio/include/asio/require.hpp @@ -2,7 +2,7 @@ // require.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -107,10 +107,10 @@ struct require_result namespace asio_require_fn { -using asio::conditional; -using asio::decay; +using asio::conditional_t; +using asio::decay_t; using asio::declval; -using asio::enable_if; +using asio::enable_if_t; using asio::is_applicable_property; using asio::traits::require_free; using asio::traits::require_member; @@ -132,99 +132,95 @@ template <typename Impl, typename T, typename Properties, typename = void, typename = void, typename = void, typename = void, typename = void> struct call_traits { - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr overload_type overload = ill_formed; + static constexpr bool is_noexcept = false; typedef void result_type; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_requirable - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_requirable + >, + enable_if_t< static_require<T, Property>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = identity); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - -#if defined(ASIO_HAS_MOVE) - typedef ASIO_MOVE_ARG(T) result_type; -#else // defined(ASIO_HAS_MOVE) - typedef ASIO_MOVE_ARG(typename decay<T>::type) result_type; -#endif // defined(ASIO_HAS_MOVE) + static constexpr overload_type overload = identity; + static constexpr bool is_noexcept = true; + + typedef T&& result_type; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_requirable - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_requirable + >, + enable_if_t< !static_require<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< require_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type> : + >> : require_member<typename Impl::template proxy<T>::type, Property> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); + static constexpr overload_type overload = call_member; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_requirable - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_requirable + >, + enable_if_t< !static_require<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !require_member<typename Impl::template proxy<T>::type, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< require_free<T, Property>::is_valid - >::type> : + >> : require_free<T, Property> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); + static constexpr overload_type overload = call_free; }; template <typename Impl, typename T, typename P0, typename P1> struct call_traits<Impl, T, void(P0, P1), - typename enable_if< + enable_if_t< call_traits<Impl, T, void(P0)>::overload != ill_formed - >::type, - typename enable_if< + >, + enable_if_t< call_traits< Impl, typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::overload != ill_formed - >::type> + >> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = two_props); + static constexpr overload_type overload = two_props; - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = + static constexpr bool is_noexcept = ( call_traits<Impl, T, void(P0)>::is_noexcept && @@ -233,51 +229,51 @@ struct call_traits<Impl, T, void(P0, P1), typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::is_noexcept - )); + ); - typedef typename decay< + typedef decay_t< typename call_traits< Impl, typename call_traits<Impl, T, void(P0)>::result_type, void(P1) >::result_type - >::type result_type; + > result_type; }; template <typename Impl, typename T, typename P0, - typename P1, typename ASIO_ELLIPSIS PN> -struct call_traits<Impl, T, void(P0, P1, PN ASIO_ELLIPSIS), - typename enable_if< + typename P1, typename... PN> +struct call_traits<Impl, T, void(P0, P1, PN...), + enable_if_t< call_traits<Impl, T, void(P0)>::overload != ill_formed - >::type, - typename enable_if< + >, + enable_if_t< call_traits< Impl, typename call_traits<Impl, T, void(P0)>::result_type, - void(P1, PN ASIO_ELLIPSIS) + void(P1, PN...) >::overload != ill_formed - >::type> + >> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = n_props); + static constexpr overload_type overload = n_props; - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = + static constexpr bool is_noexcept = ( call_traits<Impl, T, void(P0)>::is_noexcept && call_traits< Impl, typename call_traits<Impl, T, void(P0)>::result_type, - void(P1, PN ASIO_ELLIPSIS) + void(P1, PN...) >::is_noexcept - )); + ); - typedef typename decay< + typedef decay_t< typename call_traits< Impl, typename call_traits<Impl, T, void(P0)>::result_type, - void(P1, PN ASIO_ELLIPSIS) + void(P1, PN...) >::result_type - >::type result_type; + > result_type; }; struct impl @@ -289,16 +285,14 @@ struct impl struct type { template <typename P> - auto require(ASIO_MOVE_ARG(P) p) + auto require(P&& p) noexcept( noexcept( - declval<typename conditional<true, T, P>::type>().require( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().require(static_cast<P&&>(p)) ) ) -> decltype( - declval<typename conditional<true, T, P>::type>().require( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().require(static_cast<P&&>(p)) ); }; #else // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) @@ -307,91 +301,63 @@ struct impl }; template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == identity, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property)) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&&) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return ASIO_MOVE_CAST(T)(t); + return static_cast<T&&>(t); } template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == call_member, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property) p) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&& p) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return ASIO_MOVE_CAST(T)(t).require( - ASIO_MOVE_CAST(Property)(p)); + return static_cast<T&&>(t).require(static_cast<Property&&>(p)); } template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == call_free, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property) p) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&& p) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return require( - ASIO_MOVE_CAST(T)(t), - ASIO_MOVE_CAST(Property)(p)); + return require(static_cast<T&&>(t), static_cast<Property&&>(p)); } template <typename T, typename P0, typename P1> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(P0, P1)>::overload == two_props, typename call_traits<impl, T, void(P0, P1)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(P0) p0, - ASIO_MOVE_ARG(P1) p1) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(P0, P1)>::is_noexcept)) + > + operator()(T&& t, P0&& p0, P1&& p1) const + noexcept(call_traits<impl, T, void(P0, P1)>::is_noexcept) { return (*this)( - (*this)( - ASIO_MOVE_CAST(T)(t), - ASIO_MOVE_CAST(P0)(p0)), - ASIO_MOVE_CAST(P1)(p1)); + (*this)(static_cast<T&&>(t), static_cast<P0&&>(p0)), + static_cast<P1&&>(p1)); } template <typename T, typename P0, typename P1, - typename ASIO_ELLIPSIS PN> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< - call_traits<impl, T, - void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props, - typename call_traits<impl, T, - void(P0, P1, PN ASIO_ELLIPSIS)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(P0) p0, - ASIO_MOVE_ARG(P1) p1, - ASIO_MOVE_ARG(PN) ASIO_ELLIPSIS pn) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept)) + typename... PN> + ASIO_NODISCARD constexpr enable_if_t< + call_traits<impl, T, void(P0, P1, PN...)>::overload == n_props, + typename call_traits<impl, T, void(P0, P1, PN...)>::result_type + > + operator()(T&& t, P0&& p0, P1&& p1, PN&&... pn) const + noexcept(call_traits<impl, T, void(P0, P1, PN...)>::is_noexcept) { return (*this)( - (*this)( - ASIO_MOVE_CAST(T)(t), - ASIO_MOVE_CAST(P0)(p0)), - ASIO_MOVE_CAST(P1)(p1), - ASIO_MOVE_CAST(PN)(pn) ASIO_ELLIPSIS); + (*this)(static_cast<T&&>(t), static_cast<P0&&>(p0)), + static_cast<P1&&>(p1), static_cast<PN&&>(pn)...); } }; @@ -408,15 +374,13 @@ const T static_instance<T>::instance = {}; namespace asio { namespace { -static ASIO_CONSTEXPR const asio_require_fn::impl& +static constexpr const asio_require_fn::impl& require = asio_require_fn::static_instance<>::instance; } // namespace typedef asio_require_fn::impl require_t; -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename T, typename... Properties> struct can_require : integral_constant<bool, @@ -426,51 +390,14 @@ struct can_require : { }; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T, typename P0 = void, - typename P1 = void, typename P2 = void> -struct can_require : - integral_constant<bool, - asio_require_fn::call_traits<require_t, T, void(P0, P1, P2)>::overload - != asio_require_fn::ill_formed> -{ -}; - -template <typename T, typename P0, typename P1> -struct can_require<T, P0, P1> : - integral_constant<bool, - asio_require_fn::call_traits<require_t, T, void(P0, P1)>::overload - != asio_require_fn::ill_formed> -{ -}; - -template <typename T, typename P0> -struct can_require<T, P0> : - integral_constant<bool, - asio_require_fn::call_traits<require_t, T, void(P0)>::overload - != asio_require_fn::ill_formed> -{ -}; - -template <typename T> -struct can_require<T> : - false_type -{ -}; - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - #if defined(ASIO_HAS_VARIABLE_TEMPLATES) -template <typename T, typename ASIO_ELLIPSIS Properties> +template <typename T, typename... Properties> constexpr bool can_require_v - = can_require<T, Properties ASIO_ELLIPSIS>::value; + = can_require<T, Properties...>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename T, typename... Properties> struct is_nothrow_require : integral_constant<bool, @@ -479,51 +406,14 @@ struct is_nothrow_require : { }; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T, typename P0 = void, - typename P1 = void, typename P2 = void> -struct is_nothrow_require : - integral_constant<bool, - asio_require_fn::call_traits< - require_t, T, void(P0, P1, P2)>::is_noexcept> -{ -}; - -template <typename T, typename P0, typename P1> -struct is_nothrow_require<T, P0, P1> : - integral_constant<bool, - asio_require_fn::call_traits< - require_t, T, void(P0, P1)>::is_noexcept> -{ -}; - -template <typename T, typename P0> -struct is_nothrow_require<T, P0> : - integral_constant<bool, - asio_require_fn::call_traits< - require_t, T, void(P0)>::is_noexcept> -{ -}; - -template <typename T> -struct is_nothrow_require<T> : - false_type -{ -}; - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - #if defined(ASIO_HAS_VARIABLE_TEMPLATES) -template <typename T, typename ASIO_ELLIPSIS Properties> +template <typename T, typename... Properties> constexpr bool is_nothrow_require_v - = is_nothrow_require<T, Properties ASIO_ELLIPSIS>::value; + = is_nothrow_require<T, Properties...>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename T, typename... Properties> struct require_result { @@ -531,36 +421,8 @@ struct require_result require_t, T, void(Properties...)>::result_type type; }; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T, typename P0 = void, - typename P1 = void, typename P2 = void> -struct require_result -{ - typedef typename asio_require_fn::call_traits< - require_t, T, void(P0, P1, P2)>::result_type type; -}; - -template <typename T, typename P0, typename P1> -struct require_result<T, P0, P1> -{ - typedef typename asio_require_fn::call_traits< - require_t, T, void(P0, P1)>::result_type type; -}; - -template <typename T, typename P0> -struct require_result<T, P0> -{ - typedef typename asio_require_fn::call_traits< - require_t, T, void(P0)>::result_type type; -}; - -template <typename T> -struct require_result<T> -{ -}; - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) +template <typename T, typename... Properties> +using require_result_t = typename require_result<T, Properties...>::type; } // namespace asio diff --git a/3rdparty/asio/include/asio/require_concept.hpp b/3rdparty/asio/include/asio/require_concept.hpp index 1238d6b6158..b735b669952 100644 --- a/3rdparty/asio/include/asio/require_concept.hpp +++ b/3rdparty/asio/include/asio/require_concept.hpp @@ -2,7 +2,7 @@ // require_concept.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -107,10 +107,10 @@ struct require_concept_result namespace asio_require_concept_fn { -using asio::conditional; -using asio::decay; +using asio::conditional_t; +using asio::decay_t; using asio::declval; -using asio::enable_if; +using asio::enable_if_t; using asio::is_applicable_property; using asio::traits::require_concept_free; using asio::traits::require_concept_member; @@ -130,85 +130,85 @@ template <typename Impl, typename T, typename Properties, typename = void, typename = void, typename = void, typename = void, typename = void> struct call_traits { - ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr overload_type overload = ill_formed; + static constexpr bool is_noexcept = false; typedef void result_type; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_requirable_concept - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_requirable_concept + >, + enable_if_t< static_require_concept<T, Property>::is_valid - >::type> + >> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = identity); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef ASIO_MOVE_ARG(T) result_type; + static constexpr overload_type overload = identity; + static constexpr bool is_noexcept = true; + typedef T&& result_type; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_requirable_concept - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_requirable_concept + >, + enable_if_t< !static_require_concept<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< require_concept_member< typename Impl::template proxy<T>::type, Property >::is_valid - >::type> : + >> : require_concept_member< typename Impl::template proxy<T>::type, Property > { - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); + static constexpr overload_type overload = call_member; }; template <typename Impl, typename T, typename Property> struct call_traits<Impl, T, void(Property), - typename enable_if< + enable_if_t< is_applicable_property< - typename decay<T>::type, - typename decay<Property>::type + decay_t<T>, + decay_t<Property> >::value - >::type, - typename enable_if< - decay<Property>::type::is_requirable_concept - >::type, - typename enable_if< + >, + enable_if_t< + decay_t<Property>::is_requirable_concept + >, + enable_if_t< !static_require_concept<T, Property>::is_valid - >::type, - typename enable_if< + >, + enable_if_t< !require_concept_member< typename Impl::template proxy<T>::type, Property >::is_valid - >::type, - typename enable_if< + >, + enable_if_t< require_concept_free<T, Property>::is_valid - >::type> : + >> : require_concept_free<T, Property> { - ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); + static constexpr overload_type overload = call_free; }; struct impl @@ -220,16 +220,16 @@ struct impl struct type { template <typename P> - auto require_concept(ASIO_MOVE_ARG(P) p) + auto require_concept(P&& p) noexcept( noexcept( - declval<typename conditional<true, T, P>::type>().require_concept( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().require_concept( + static_cast<P&&>(p)) ) ) -> decltype( - declval<typename conditional<true, T, P>::type>().require_concept( - ASIO_MOVE_CAST(P)(p)) + declval<conditional_t<true, T, P>>().require_concept( + static_cast<P&&>(p)) ); }; #else // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT) @@ -238,48 +238,36 @@ struct impl }; template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == identity, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property)) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&&) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return ASIO_MOVE_CAST(T)(t); + return static_cast<T&&>(t); } template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == call_member, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property) p) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&& p) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return ASIO_MOVE_CAST(T)(t).require_concept( - ASIO_MOVE_CAST(Property)(p)); + return static_cast<T&&>(t).require_concept(static_cast<Property&&>(p)); } template <typename T, typename Property> - ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if< + ASIO_NODISCARD constexpr enable_if_t< call_traits<impl, T, void(Property)>::overload == call_free, typename call_traits<impl, T, void(Property)>::result_type - >::type - operator()( - ASIO_MOVE_ARG(T) t, - ASIO_MOVE_ARG(Property) p) const - ASIO_NOEXCEPT_IF(( - call_traits<impl, T, void(Property)>::is_noexcept)) + > + operator()(T&& t, Property&& p) const + noexcept(call_traits<impl, T, void(Property)>::is_noexcept) { - return require_concept( - ASIO_MOVE_CAST(T)(t), - ASIO_MOVE_CAST(Property)(p)); + return require_concept(static_cast<T&&>(t), static_cast<Property&&>(p)); } }; @@ -296,7 +284,7 @@ const T static_instance<T>::instance = {}; namespace asio { namespace { -static ASIO_CONSTEXPR const asio_require_concept_fn::impl& +static constexpr const asio_require_concept_fn::impl& require_concept = asio_require_concept_fn::static_instance<>::instance; } // namespace @@ -315,8 +303,7 @@ struct can_require_concept : #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template <typename T, typename Property> -constexpr bool can_require_concept_v - = can_require_concept<T, Property>::value; +constexpr bool can_require_concept_v = can_require_concept<T, Property>::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) @@ -343,6 +330,10 @@ struct require_concept_result require_concept_t, T, void(Property)>::result_type type; }; +template <typename T, typename Property> +using require_concept_result_t = + typename require_concept_result<T, Property>::type; + } // namespace asio #endif // defined(GENERATING_DOCUMENTATION) diff --git a/3rdparty/asio/include/asio/serial_port.hpp b/3rdparty/asio/include/asio/serial_port.hpp index bc5c552c23e..61e893769bf 100644 --- a/3rdparty/asio/include/asio/serial_port.hpp +++ b/3rdparty/asio/include/asio/serial_port.hpp @@ -2,7 +2,7 @@ // serial_port.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/3rdparty/asio/include/asio/serial_port_base.hpp b/3rdparty/asio/include/asio/serial_port_base.hpp index 6d4b047124c..479d69796e7 100644 --- a/3rdparty/asio/include/asio/serial_port_base.hpp +++ b/3rdparty/asio/include/asio/serial_port_base.hpp @@ -2,7 +2,7 @@ // serial_port_base.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2008 Rep Invariant Systems, Inc. (info@repinvariant.com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/3rdparty/asio/include/asio/signal_set.hpp b/3rdparty/asio/include/asio/signal_set.hpp index 24cd8bfd4f2..b2e189d01d7 100644 --- a/3rdparty/asio/include/asio/signal_set.hpp +++ b/3rdparty/asio/include/asio/signal_set.hpp @@ -2,7 +2,7 @@ // signal_set.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/signal_set_base.hpp b/3rdparty/asio/include/asio/signal_set_base.hpp new file mode 100644 index 00000000000..9863a1598a3 --- /dev/null +++ b/3rdparty/asio/include/asio/signal_set_base.hpp @@ -0,0 +1,171 @@ +// +// signal_set_base.hpp +// ~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_SIGNAL_SET_BASE_HPP +#define ASIO_SIGNAL_SET_BASE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" +#include "asio/detail/socket_types.hpp" + +#include "asio/detail/push_options.hpp" + +namespace asio { + +/// The signal_set_base class is used as a base for the basic_signal_set class +/// templates so that we have a common place to define the flags enum. +class signal_set_base +{ +public: +# if defined(GENERATING_DOCUMENTATION) + /// Enumeration representing the different types of flags that may specified + /// when adding a signal to a set. + enum flags + { + /// Bitmask representing no flags. + none = 0, + + /// Affects the behaviour of interruptible functions such that, if the + /// function would have failed with error::interrupted when interrupted by + /// the specified signal, the function shall instead be restarted and not + /// fail with error::interrupted. + restart = implementation_defined, + + /// Do not generate SIGCHLD when child processes stop or stopped child + /// processes continue. + no_child_stop = implementation_defined, + + /// Do not transform child processes into zombies when they terminate. + no_child_wait = implementation_defined, + + /// Special value to indicate that the signal registration does not care + /// which flags are set, and so will not conflict with any prior + /// registrations of the same signal. + dont_care = -1 + }; + + /// Portability typedef. + typedef flags flags_t; + +#else // defined(GENERATING_DOCUMENTATION) + + enum class flags : int + { + none = 0, + restart = ASIO_OS_DEF(SA_RESTART), + no_child_stop = ASIO_OS_DEF(SA_NOCLDSTOP), + no_child_wait = ASIO_OS_DEF(SA_NOCLDWAIT), + dont_care = -1 + }; + + typedef flags flags_t; + +#endif // defined(GENERATING_DOCUMENTATION) + +protected: + /// Protected destructor to prevent deletion through this type. + ~signal_set_base() + { + } +}; + +/// Negation operator. +/** + * @relates signal_set_base::flags + */ +inline constexpr bool operator!(signal_set_base::flags_t x) +{ + return static_cast<int>(x) == 0; +} + +/// Bitwise and operator. +/** + * @relates signal_set_base::flags + */ +inline constexpr signal_set_base::flags_t operator&( + signal_set_base::flags_t x, signal_set_base::flags_t y) +{ + return static_cast<signal_set_base::flags_t>( + static_cast<int>(x) & static_cast<int>(y)); +} + +/// Bitwise or operator. +/** + * @relates signal_set_base::flags + */ +inline constexpr signal_set_base::flags_t operator|( + signal_set_base::flags_t x, signal_set_base::flags_t y) +{ + return static_cast<signal_set_base::flags_t>( + static_cast<int>(x) | static_cast<int>(y)); +} + +/// Bitwise xor operator. +/** + * @relates signal_set_base::flags + */ +inline constexpr signal_set_base::flags_t operator^( + signal_set_base::flags_t x, signal_set_base::flags_t y) +{ + return static_cast<signal_set_base::flags_t>( + static_cast<int>(x) ^ static_cast<int>(y)); +} + +/// Bitwise negation operator. +/** + * @relates signal_set_base::flags + */ +inline constexpr signal_set_base::flags_t operator~( + signal_set_base::flags_t x) +{ + return static_cast<signal_set_base::flags_t>(~static_cast<int>(x)); +} + +/// Bitwise and-assignment operator. +/** + * @relates signal_set_base::flags + */ +inline signal_set_base::flags_t& operator&=( + signal_set_base::flags_t& x, signal_set_base::flags_t y) +{ + x = x & y; + return x; +} + +/// Bitwise or-assignment operator. +/** + * @relates signal_set_base::flags + */ +inline signal_set_base::flags_t& operator|=( + signal_set_base::flags_t& x, signal_set_base::flags_t y) +{ + x = x | y; + return x; +} + +/// Bitwise xor-assignment operator. +/** + * @relates signal_set_base::flags + */ +inline signal_set_base::flags_t& operator^=( + signal_set_base::flags_t& x, signal_set_base::flags_t y) +{ + x = x ^ y; + return x; +} + +} // namespace asio + +#include "asio/detail/pop_options.hpp" + +#endif // ASIO_SIGNAL_SET_BASE_HPP diff --git a/3rdparty/asio/include/asio/socket_base.hpp b/3rdparty/asio/include/asio/socket_base.hpp index e43790cc8b7..5d509790d3d 100644 --- a/3rdparty/asio/include/asio/socket_base.hpp +++ b/3rdparty/asio/include/asio/socket_base.hpp @@ -2,7 +2,7 @@ // socket_base.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/spawn.hpp b/3rdparty/asio/include/asio/spawn.hpp index 780de6b7284..eeacb49de6d 100644 --- a/3rdparty/asio/include/asio/spawn.hpp +++ b/3rdparty/asio/include/asio/spawn.hpp @@ -2,7 +2,7 @@ // spawn.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,28 +16,162 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" -#include <boost/coroutine/all.hpp> #include "asio/any_io_executor.hpp" -#include "asio/bind_executor.hpp" +#include "asio/cancellation_signal.hpp" +#include "asio/cancellation_state.hpp" +#include "asio/detail/exception.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/type_traits.hpp" -#include "asio/detail/wrapped_handler.hpp" #include "asio/io_context.hpp" #include "asio/is_executor.hpp" #include "asio/strand.hpp" +#if defined(ASIO_HAS_BOOST_COROUTINE) +# include <boost/coroutine/all.hpp> +#endif // defined(ASIO_HAS_BOOST_COROUTINE) + #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { + +// Base class for all spawn()-ed thread implementations. +class spawned_thread_base +{ +public: + spawned_thread_base() + : owner_(0), + has_context_switched_(false), + throw_if_cancelled_(false), + terminal_(false) + { + } + + virtual ~spawned_thread_base() {} + virtual void resume() = 0; + virtual void suspend_with(void (*fn)(void*), void* arg) = 0; + virtual void destroy() = 0; + + void attach(spawned_thread_base** owner) + { + owner_ = owner; + *owner_ = this; + } + + void detach() + { + if (owner_) + *owner_ = 0; + owner_ = 0; + } + + void suspend() + { + suspend_with(0, 0); + } + + template <typename F> + void suspend_with(F f) + { + suspend_with(&spawned_thread_base::call<F>, &f); + } + + cancellation_slot get_cancellation_slot() const noexcept + { + return cancellation_state_.slot(); + } -/// Context object the represents the currently executing coroutine. + cancellation_state get_cancellation_state() const noexcept + { + return cancellation_state_; + } + + void reset_cancellation_state() + { + cancellation_state_ = cancellation_state(parent_cancellation_slot_); + } + + template <typename Filter> + void reset_cancellation_state(Filter filter) + { + cancellation_state_ = cancellation_state( + parent_cancellation_slot_, filter, filter); + } + + template <typename InFilter, typename OutFilter> + void reset_cancellation_state(InFilter in_filter, OutFilter out_filter) + { + cancellation_state_ = cancellation_state( + parent_cancellation_slot_, in_filter, out_filter); + } + + cancellation_type_t cancelled() const noexcept + { + return cancellation_state_.cancelled(); + } + + bool has_context_switched() const noexcept + { + return has_context_switched_; + } + + bool throw_if_cancelled() const noexcept + { + return throw_if_cancelled_; + } + + void throw_if_cancelled(bool value) noexcept + { + throw_if_cancelled_ = value; + } + +protected: + spawned_thread_base** owner_; // Points to data member in active handler. + asio::cancellation_slot parent_cancellation_slot_; + asio::cancellation_state cancellation_state_; + bool has_context_switched_; + bool throw_if_cancelled_; + bool terminal_; + +private: + // Disallow copying and assignment. + spawned_thread_base(const spawned_thread_base&) = delete; + spawned_thread_base& operator=(const spawned_thread_base&) = delete; + + template <typename F> + static void call(void* f) + { + (*static_cast<F*>(f))(); + } +}; + + +template <typename T> +struct spawn_signature +{ + typedef void type(exception_ptr, T); +}; + +template <> +struct spawn_signature<void> +{ + typedef void type(exception_ptr); +}; + +template <typename Executor> +class initiate_spawn; + +} // namespace detail + +/// A @ref completion_token that represents the currently executing coroutine. /** - * The basic_yield_context class is used to represent the currently executing - * stackful coroutine. A basic_yield_context may be passed as a handler to an - * asynchronous operation. For example: + * The basic_yield_context class is a completion token type that is used to + * represent the currently executing stackful coroutine. A basic_yield_context + * object may be passed as a completion token to an asynchronous operation. For + * example: * - * @code template <typename Handler> - * void my_coroutine(basic_yield_context<Handler> yield) + * @code template <typename Executor> + * void my_coroutine(basic_yield_context<Executor> yield) * { * ... * std::size_t n = my_socket.async_read_some(buffer, yield); @@ -48,67 +182,112 @@ namespace asio { * current coroutine. The coroutine is resumed when the asynchronous operation * completes, and the result of the operation is returned. */ -template <typename Handler> +template <typename Executor> class basic_yield_context { public: - /// The coroutine callee type, used by the implementation. + /// The executor type associated with the yield context. + typedef Executor executor_type; + + /// The cancellation slot type associated with the yield context. + typedef cancellation_slot cancellation_slot_type; + + /// Construct a yield context from another yield context type. /** - * When using Boost.Coroutine v1, this type is: - * @code typename coroutine<void()> @endcode - * When using Boost.Coroutine v2 (unidirectional coroutines), this type is: - * @code push_coroutine<void> @endcode + * Requires that OtherExecutor be convertible to Executor. */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined callee_type; -#elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2) - typedef boost::coroutines::push_coroutine<void> callee_type; -#else - typedef boost::coroutines::coroutine<void()> callee_type; -#endif - - /// The coroutine caller type, used by the implementation. + template <typename OtherExecutor> + basic_yield_context(const basic_yield_context<OtherExecutor>& other, + constraint_t< + is_convertible<OtherExecutor, Executor>::value + > = 0) + : spawned_thread_(other.spawned_thread_), + executor_(other.executor_), + ec_(other.ec_) + { + } + + /// Get the executor associated with the yield context. + executor_type get_executor() const noexcept + { + return executor_; + } + + /// Get the cancellation slot associated with the coroutine. + cancellation_slot_type get_cancellation_slot() const noexcept + { + return spawned_thread_->get_cancellation_slot(); + } + + /// Get the cancellation state associated with the coroutine. + cancellation_state get_cancellation_state() const noexcept + { + return spawned_thread_->get_cancellation_state(); + } + + /// Reset the cancellation state associated with the coroutine. /** - * When using Boost.Coroutine v1, this type is: - * @code typename coroutine<void()>::caller_type @endcode - * When using Boost.Coroutine v2 (unidirectional coroutines), this type is: - * @code pull_coroutine<void> @endcode + * Let <tt>P</tt> be the cancellation slot associated with the current + * coroutine's @ref spawn completion handler. Assigns a new + * asio::cancellation_state object <tt>S</tt>, constructed as + * <tt>S(P)</tt>, into the current coroutine's cancellation state object. */ -#if defined(GENERATING_DOCUMENTATION) - typedef implementation_defined caller_type; -#elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2) - typedef boost::coroutines::pull_coroutine<void> caller_type; -#else - typedef boost::coroutines::coroutine<void()>::caller_type caller_type; -#endif - - /// Construct a yield context to represent the specified coroutine. + void reset_cancellation_state() const + { + spawned_thread_->reset_cancellation_state(); + } + + /// Reset the cancellation state associated with the coroutine. /** - * Most applications do not need to use this constructor. Instead, the - * spawn() function passes a yield context as an argument to the coroutine - * function. + * Let <tt>P</tt> be the cancellation slot associated with the current + * coroutine's @ref spawn completion handler. Assigns a new + * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P, + * std::forward<Filter>(filter))</tt>, into the current coroutine's + * cancellation state object. */ - basic_yield_context( - const detail::weak_ptr<callee_type>& coro, - caller_type& ca, Handler& handler) - : coro_(coro), - ca_(ca), - handler_(handler), - ec_(0) + template <typename Filter> + void reset_cancellation_state(Filter&& filter) const { + spawned_thread_->reset_cancellation_state( + static_cast<Filter&&>(filter)); } - /// Construct a yield context from another yield context type. + /// Reset the cancellation state associated with the coroutine. /** - * Requires that OtherHandler be convertible to Handler. + * Let <tt>P</tt> be the cancellation slot associated with the current + * coroutine's @ref spawn completion handler. Assigns a new + * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P, + * std::forward<InFilter>(in_filter), + * std::forward<OutFilter>(out_filter))</tt>, into the current coroutine's + * cancellation state object. */ - template <typename OtherHandler> - basic_yield_context(const basic_yield_context<OtherHandler>& other) - : coro_(other.coro_), - ca_(other.ca_), - handler_(other.handler_), - ec_(other.ec_) + template <typename InFilter, typename OutFilter> + void reset_cancellation_state(InFilter&& in_filter, + OutFilter&& out_filter) const + { + spawned_thread_->reset_cancellation_state( + static_cast<InFilter&&>(in_filter), + static_cast<OutFilter&&>(out_filter)); + } + + /// Determine whether the current coroutine has been cancelled. + cancellation_type_t cancelled() const noexcept { + return spawned_thread_->cancelled(); + } + + /// Determine whether the coroutine throws if trying to suspend when it has + /// been cancelled. + bool throw_if_cancelled() const noexcept + { + return spawned_thread_->throw_if_cancelled(); + } + + /// Set whether the coroutine throws if trying to suspend when it has been + /// cancelled. + void throw_if_cancelled(bool value) const noexcept + { + spawned_thread_->throw_if_cancelled(value); } /// Return a yield context that sets the specified error_code. @@ -118,8 +297,8 @@ public: * operator may be used to specify an error_code object that should instead be * set with the asynchronous operation's result. For example: * - * @code template <typename Handler> - * void my_coroutine(basic_yield_context<Handler> yield) + * @code template <typename Executor> + * void my_coroutine(basic_yield_context<Executor> yield) * { * ... * std::size_t n = my_socket.async_read_some(buffer, yield[ec]); @@ -137,22 +316,25 @@ public: return tmp; } -#if defined(GENERATING_DOCUMENTATION) -private: -#endif // defined(GENERATING_DOCUMENTATION) - detail::weak_ptr<callee_type> coro_; - caller_type& ca_; - Handler handler_; +#if !defined(GENERATING_DOCUMENTATION) +//private: + basic_yield_context(detail::spawned_thread_base* spawned_thread, + const Executor& ex) + : spawned_thread_(spawned_thread), + executor_(ex), + ec_(0) + { + } + + detail::spawned_thread_base* spawned_thread_; + Executor executor_; asio::error_code* ec_; +#endif // !defined(GENERATING_DOCUMENTATION) }; -#if defined(GENERATING_DOCUMENTATION) -/// Context object that represents the currently executing coroutine. -typedef basic_yield_context<unspecified> yield_context; -#else // defined(GENERATING_DOCUMENTATION) -typedef basic_yield_context< - executor_binder<void(*)(), any_io_executor> > yield_context; -#endif // defined(GENERATING_DOCUMENTATION) +/// A @ref completion_token object that represents the currently executing +/// coroutine. +typedef basic_yield_context<any_io_executor> yield_context; /** * @defgroup spawn asio::spawn @@ -163,7 +345,7 @@ typedef basic_yield_context< * library. This function enables programs to implement asynchronous logic in a * synchronous manner, as illustrated by the following example: * - * @code asio::spawn(my_strand, do_echo); + * @code asio::spawn(my_strand, do_echo, asio::detached); * * // ... * @@ -190,23 +372,363 @@ typedef basic_yield_context< */ /*@{*/ -/// Start a new stackful coroutine, calling the specified handler when it -/// completes. +/// Start a new stackful coroutine that executes on a given executor. +/** + * This function is used to launch a new stackful coroutine. + * + * @param ex Identifies the executor that will run the stackful coroutine. + * + * @param function The coroutine function. The function must be callable the + * signature: + * @code void function(basic_yield_context<Executor> yield); @endcode + * + * @param token The @ref completion_token that will handle the notification + * that the coroutine has completed. If the return type @c R of @c function is + * @c void, the function signature of the completion handler must be: + * + * @code void handler(std::exception_ptr); @endcode + * Otherwise, the function signature of the completion handler must be: + * @code void handler(std::exception_ptr, R); @endcode + * + * @par Completion Signature + * @code void(std::exception_ptr, R) @endcode + * where @c R is the return type of the function object. + * + * @par Per-Operation Cancellation + * The new thread of execution is created with a cancellation state that + * supports @c cancellation_type::terminal values only. To change the + * cancellation state, call the basic_yield_context member function + * @c reset_cancellation_state. + */ +template <typename Executor, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type) + CompletionToken = default_completion_token_t<Executor>> +auto spawn(const Executor& ex, F&& function, + CompletionToken&& token = default_completion_token_t<Executor>(), +#if defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + !is_same< + decay_t<CompletionToken>, + boost::coroutines::attributes + >::value + > = 0, +#endif // defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + > = 0) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type>( + declval<detail::initiate_spawn<Executor>>(), + token, static_cast<F&&>(function))); + +/// Start a new stackful coroutine that executes on a given execution context. +/** + * This function is used to launch a new stackful coroutine. + * + * @param ctx Identifies the execution context that will run the stackful + * coroutine. + * + * @param function The coroutine function. The function must be callable the + * signature: + * @code void function(basic_yield_context<Executor> yield); @endcode + * + * @param token The @ref completion_token that will handle the notification + * that the coroutine has completed. If the return type @c R of @c function is + * @c void, the function signature of the completion handler must be: + * + * @code void handler(std::exception_ptr); @endcode + * Otherwise, the function signature of the completion handler must be: + * @code void handler(std::exception_ptr, R); @endcode + * + * @par Completion Signature + * @code void(std::exception_ptr, R) @endcode + * where @c R is the return type of the function object. + * + * @par Per-Operation Cancellation + * The new thread of execution is created with a cancellation state that + * supports @c cancellation_type::terminal values only. To change the + * cancellation state, call the basic_yield_context member function + * @c reset_cancellation_state. + */ +template <typename ExecutionContext, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context< + typename ExecutionContext::executor_type>)>>::type) + CompletionToken = default_completion_token_t< + typename ExecutionContext::executor_type>> +auto spawn(ExecutionContext& ctx, F&& function, + CompletionToken&& token + = default_completion_token_t<typename ExecutionContext::executor_type>(), +#if defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + !is_same< + decay_t<CompletionToken>, + boost::coroutines::attributes + >::value + > = 0, +#endif // defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context< + typename ExecutionContext::executor_type>)>>::type>( + declval<detail::initiate_spawn< + typename ExecutionContext::executor_type>>(), + token, static_cast<F&&>(function))); + +/// Start a new stackful coroutine, inheriting the executor of another. +/** + * This function is used to launch a new stackful coroutine. + * + * @param ctx Identifies the current coroutine as a parent of the new + * coroutine. This specifies that the new coroutine should inherit the executor + * of the parent. For example, if the parent coroutine is executing in a + * particular strand, then the new coroutine will execute in the same strand. + * + * @param function The coroutine function. The function must be callable the + * signature: + * @code void function(basic_yield_context<Executor> yield); @endcode + * + * @param token The @ref completion_token that will handle the notification + * that the coroutine has completed. If the return type @c R of @c function is + * @c void, the function signature of the completion handler must be: + * + * @code void handler(std::exception_ptr); @endcode + * Otherwise, the function signature of the completion handler must be: + * @code void handler(std::exception_ptr, R); @endcode + * + * @par Completion Signature + * @code void(std::exception_ptr, R) @endcode + * where @c R is the return type of the function object. + * + * @par Per-Operation Cancellation + * The new thread of execution is created with a cancellation state that + * supports @c cancellation_type::terminal values only. To change the + * cancellation state, call the basic_yield_context member function + * @c reset_cancellation_state. + */ +template <typename Executor, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type) + CompletionToken = default_completion_token_t<Executor>> +auto spawn(const basic_yield_context<Executor>& ctx, F&& function, + CompletionToken&& token = default_completion_token_t<Executor>(), +#if defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + !is_same< + decay_t<CompletionToken>, + boost::coroutines::attributes + >::value + > = 0, +#endif // defined(ASIO_HAS_BOOST_COROUTINE) + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + > = 0) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type>( + declval<detail::initiate_spawn<Executor>>(), + token, static_cast<F&&>(function))); + +#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER) \ + || defined(GENERATING_DOCUMENTATION) + +/// Start a new stackful coroutine that executes on a given executor. +/** + * This function is used to launch a new stackful coroutine using the + * specified stack allocator. + * + * @param ex Identifies the executor that will run the stackful coroutine. + * + * @param stack_allocator Denotes the allocator to be used to allocate the + * underlying coroutine's stack. The type must satisfy the stack-allocator + * concept defined by the Boost.Context library. + * + * @param function The coroutine function. The function must be callable the + * signature: + * @code void function(basic_yield_context<Executor> yield); @endcode + * + * @param token The @ref completion_token that will handle the notification + * that the coroutine has completed. If the return type @c R of @c function is + * @c void, the function signature of the completion handler must be: + * + * @code void handler(std::exception_ptr); @endcode + * Otherwise, the function signature of the completion handler must be: + * @code void handler(std::exception_ptr, R); @endcode + * + * @par Completion Signature + * @code void(std::exception_ptr, R) @endcode + * where @c R is the return type of the function object. + * + * @par Per-Operation Cancellation + * The new thread of execution is created with a cancellation state that + * supports @c cancellation_type::terminal values only. To change the + * cancellation state, call the basic_yield_context member function + * @c reset_cancellation_state. + */ +template <typename Executor, typename StackAllocator, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type) + CompletionToken = default_completion_token_t<Executor>> +auto spawn(const Executor& ex, allocator_arg_t, + StackAllocator&& stack_allocator, F&& function, + CompletionToken&& token = default_completion_token_t<Executor>(), + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + > = 0) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type>( + declval<detail::initiate_spawn<Executor>>(), + token, allocator_arg_t(), + static_cast<StackAllocator&&>(stack_allocator), + static_cast<F&&>(function))); + +/// Start a new stackful coroutine that executes on a given execution context. +/** + * This function is used to launch a new stackful coroutine. + * + * @param ctx Identifies the execution context that will run the stackful + * coroutine. + * + * @param stack_allocator Denotes the allocator to be used to allocate the + * underlying coroutine's stack. The type must satisfy the stack-allocator + * concept defined by the Boost.Context library. + * + * @param function The coroutine function. The function must be callable the + * signature: + * @code void function(basic_yield_context<Executor> yield); @endcode + * + * @param token The @ref completion_token that will handle the notification + * that the coroutine has completed. If the return type @c R of @c function is + * @c void, the function signature of the completion handler must be: + * + * @code void handler(std::exception_ptr); @endcode + * Otherwise, the function signature of the completion handler must be: + * @code void handler(std::exception_ptr, R); @endcode + * + * @par Completion Signature + * @code void(std::exception_ptr, R) @endcode + * where @c R is the return type of the function object. + * + * @par Per-Operation Cancellation + * The new thread of execution is created with a cancellation state that + * supports @c cancellation_type::terminal values only. To change the + * cancellation state, call the basic_yield_context member function + * @c reset_cancellation_state. + */ +template <typename ExecutionContext, typename StackAllocator, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context< + typename ExecutionContext::executor_type>)>>::type) + CompletionToken = default_completion_token_t< + typename ExecutionContext::executor_type>> +auto spawn(ExecutionContext& ctx, allocator_arg_t, + StackAllocator&& stack_allocator, F&& function, + CompletionToken&& token + = default_completion_token_t<typename ExecutionContext::executor_type>(), + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context< + typename ExecutionContext::executor_type>)>>::type>( + declval<detail::initiate_spawn< + typename ExecutionContext::executor_type>>(), + token, allocator_arg_t(), + static_cast<StackAllocator&&>(stack_allocator), + static_cast<F&&>(function))); + +/// Start a new stackful coroutine, inheriting the executor of another. +/** + * This function is used to launch a new stackful coroutine using the + * specified stack allocator. + * + * @param ctx Identifies the current coroutine as a parent of the new + * coroutine. This specifies that the new coroutine should inherit the + * executor of the parent. For example, if the parent coroutine is executing + * in a particular strand, then the new coroutine will execute in the same + * strand. + * + * @param stack_allocator Denotes the allocator to be used to allocate the + * underlying coroutine's stack. The type must satisfy the stack-allocator + * concept defined by the Boost.Context library. + * + * @param function The coroutine function. The function must be callable the + * signature: + * @code void function(basic_yield_context<Executor> yield); @endcode + * + * @param token The @ref completion_token that will handle the notification + * that the coroutine has completed. If the return type @c R of @c function is + * @c void, the function signature of the completion handler must be: + * + * @code void handler(std::exception_ptr); @endcode + * Otherwise, the function signature of the completion handler must be: + * @code void handler(std::exception_ptr, R); @endcode + * + * @par Completion Signature + * @code void(std::exception_ptr, R) @endcode + * where @c R is the return type of the function object. + * + * @par Per-Operation Cancellation + * The new thread of execution is created with a cancellation state that + * supports @c cancellation_type::terminal values only. To change the + * cancellation state, call the basic_yield_context member function + * @c reset_cancellation_state. + */ +template <typename Executor, typename StackAllocator, typename F, + ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type) + CompletionToken = default_completion_token_t<Executor>> +auto spawn(const basic_yield_context<Executor>& ctx, allocator_arg_t, + StackAllocator&& stack_allocator, F&& function, + CompletionToken&& token = default_completion_token_t<Executor>(), + constraint_t< + is_executor<Executor>::value || execution::is_executor<Executor>::value + > = 0) + -> decltype( + async_initiate<CompletionToken, + typename detail::spawn_signature< + result_of_t<F(basic_yield_context<Executor>)>>::type>( + declval<detail::initiate_spawn<Executor>>(), + token, allocator_arg_t(), + static_cast<StackAllocator&&>(stack_allocator), + static_cast<F&&>(function))); + +#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER) + // || defined(GENERATING_DOCUMENTATION) + +#if defined(ASIO_HAS_BOOST_COROUTINE) \ + || defined(GENERATING_DOCUMENTATION) + +/// (Deprecated: Use overloads with a completion token.) Start a new stackful +/// coroutine, calling the specified handler when it completes. /** * This function is used to launch a new coroutine. * * @param function The coroutine function. The function must have the signature: - * @code void function(basic_yield_context<Handler> yield); @endcode + * @code void function(basic_yield_context<Executor> yield); @endcode + * where Executor is the associated executor type of @c Function. * * @param attributes Boost.Coroutine attributes used to customise the coroutine. */ template <typename Function> -void spawn(ASIO_MOVE_ARG(Function) function, +void spawn(Function&& function, const boost::coroutines::attributes& attributes = boost::coroutines::attributes()); -/// Start a new stackful coroutine, calling the specified handler when it -/// completes. +/// (Deprecated: Use overloads with a completion token.) Start a new stackful +/// coroutine, calling the specified handler when it completes. /** * This function is used to launch a new coroutine. * @@ -216,21 +738,23 @@ void spawn(ASIO_MOVE_ARG(Function) function, * @code void handler(); @endcode * * @param function The coroutine function. The function must have the signature: - * @code void function(basic_yield_context<Handler> yield); @endcode + * @code void function(basic_yield_context<Executor> yield); @endcode + * where Executor is the associated executor type of @c Handler. * * @param attributes Boost.Coroutine attributes used to customise the coroutine. */ template <typename Handler, typename Function> -void spawn(ASIO_MOVE_ARG(Handler) handler, - ASIO_MOVE_ARG(Function) function, +void spawn(Handler&& handler, Function&& function, const boost::coroutines::attributes& attributes = boost::coroutines::attributes(), - typename constraint< - !is_executor<typename decay<Handler>::type>::value && - !execution::is_executor<typename decay<Handler>::type>::value && - !is_convertible<Handler&, execution_context&>::value>::type = 0); + constraint_t< + !is_executor<decay_t<Handler>>::value && + !execution::is_executor<decay_t<Handler>>::value && + !is_convertible<Handler&, execution_context&>::value + > = 0); -/// Start a new stackful coroutine, inheriting the execution context of another. +/// (Deprecated: Use overloads with a completion token.) Start a new stackful +/// coroutine, inheriting the execution context of another. /** * This function is used to launch a new coroutine. * @@ -241,22 +765,23 @@ void spawn(ASIO_MOVE_ARG(Handler) handler, * same strand. * * @param function The coroutine function. The function must have the signature: - * @code void function(basic_yield_context<Handler> yield); @endcode + * @code void function(basic_yield_context<Executor> yield); @endcode * * @param attributes Boost.Coroutine attributes used to customise the coroutine. */ -template <typename Handler, typename Function> -void spawn(basic_yield_context<Handler> ctx, - ASIO_MOVE_ARG(Function) function, +template <typename Executor, typename Function> +void spawn(basic_yield_context<Executor> ctx, Function&& function, const boost::coroutines::attributes& attributes = boost::coroutines::attributes()); -/// Start a new stackful coroutine that executes on a given executor. +/// (Deprecated: Use overloads with a completion token.) Start a new stackful +/// coroutine that executes on a given executor. /** * This function is used to launch a new coroutine. * * @param ex Identifies the executor that will run the coroutine. The new - * coroutine is implicitly given its own strand within this executor. + * coroutine is automatically given its own explicit strand within this + * executor. * * @param function The coroutine function. The function must have the signature: * @code void function(yield_context yield); @endcode @@ -264,15 +789,15 @@ void spawn(basic_yield_context<Handler> ctx, * @param attributes Boost.Coroutine attributes used to customise the coroutine. */ template <typename Function, typename Executor> -void spawn(const Executor& ex, - ASIO_MOVE_ARG(Function) function, +void spawn(const Executor& ex, Function&& function, const boost::coroutines::attributes& attributes = boost::coroutines::attributes(), - typename constraint< + constraint_t< is_executor<Executor>::value || execution::is_executor<Executor>::value - >::type = 0); + > = 0); -/// Start a new stackful coroutine that executes on a given strand. +/// (Deprecated: Use overloads with a completion token.) Start a new stackful +/// coroutine that executes on a given strand. /** * This function is used to launch a new coroutine. * @@ -284,14 +809,14 @@ void spawn(const Executor& ex, * @param attributes Boost.Coroutine attributes used to customise the coroutine. */ template <typename Function, typename Executor> -void spawn(const strand<Executor>& ex, - ASIO_MOVE_ARG(Function) function, +void spawn(const strand<Executor>& ex, Function&& function, const boost::coroutines::attributes& attributes = boost::coroutines::attributes()); #if !defined(ASIO_NO_TS_EXECUTORS) -/// Start a new stackful coroutine that executes in the context of a strand. +/// (Deprecated: Use overloads with a completion token.) Start a new stackful +/// coroutine that executes in the context of a strand. /** * This function is used to launch a new coroutine. * @@ -305,14 +830,14 @@ void spawn(const strand<Executor>& ex, * @param attributes Boost.Coroutine attributes used to customise the coroutine. */ template <typename Function> -void spawn(const asio::io_context::strand& s, - ASIO_MOVE_ARG(Function) function, +void spawn(const asio::io_context::strand& s, Function&& function, const boost::coroutines::attributes& attributes = boost::coroutines::attributes()); #endif // !defined(ASIO_NO_TS_EXECUTORS) -/// Start a new stackful coroutine that executes on a given execution context. +/// (Deprecated: Use overloads with a completion token.) Start a new stackful +/// coroutine that executes on a given execution context. /** * This function is used to launch a new coroutine. * @@ -326,12 +851,15 @@ void spawn(const asio::io_context::strand& s, * @param attributes Boost.Coroutine attributes used to customise the coroutine. */ template <typename Function, typename ExecutionContext> -void spawn(ExecutionContext& ctx, - ASIO_MOVE_ARG(Function) function, +void spawn(ExecutionContext& ctx, Function&& function, const boost::coroutines::attributes& attributes = boost::coroutines::attributes(), - typename constraint<is_convertible< - ExecutionContext&, execution_context&>::value>::type = 0); + constraint_t< + is_convertible<ExecutionContext&, execution_context&>::value + > = 0); + +#endif // defined(ASIO_HAS_BOOST_COROUTINE) + // || defined(GENERATING_DOCUMENTATION) /*@}*/ diff --git a/3rdparty/asio/include/asio/ssl.hpp b/3rdparty/asio/include/asio/ssl.hpp index 79764367db2..4180dab6f42 100644 --- a/3rdparty/asio/include/asio/ssl.hpp +++ b/3rdparty/asio/include/asio/ssl.hpp @@ -2,7 +2,7 @@ // ssl.hpp // ~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/context.hpp b/3rdparty/asio/include/asio/ssl/context.hpp index 7360c33cef3..a41904a4089 100644 --- a/3rdparty/asio/include/asio/ssl/context.hpp +++ b/3rdparty/asio/include/asio/ssl/context.hpp @@ -2,7 +2,7 @@ // ssl/context.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -46,7 +46,6 @@ public: /// Construct to take ownership of a native handle. ASIO_DECL explicit context(native_handle_type native_handle); -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a context from another. /** * This constructor moves an SSL context from one object to another. @@ -72,7 +71,6 @@ public: * @li As a target for move-assignment. */ ASIO_DECL context& operator=(context&& other); -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destructor. ASIO_DECL ~context(); @@ -741,6 +739,9 @@ private: // Helper function to make a BIO from a memory buffer. ASIO_DECL BIO* make_buffer_bio(const const_buffer& b); + // Translate an SSL error into an error code. + ASIO_DECL static asio::error_code translate_error(long error); + // The underlying native implementation. native_handle_type handle_; diff --git a/3rdparty/asio/include/asio/ssl/context_base.hpp b/3rdparty/asio/include/asio/ssl/context_base.hpp index fe7946e38ef..36271012b06 100644 --- a/3rdparty/asio/include/asio/ssl/context_base.hpp +++ b/3rdparty/asio/include/asio/ssl/context_base.hpp @@ -2,7 +2,7 @@ // ssl/context_base.hpp // ~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -105,60 +105,60 @@ public: }; /// Bitmask type for SSL options. - typedef long options; + typedef uint64_t options; #if defined(GENERATING_DOCUMENTATION) /// Implement various bug workarounds. - static const long default_workarounds = implementation_defined; + static const uint64_t default_workarounds = implementation_defined; /// Always create a new key when using tmp_dh parameters. - static const long single_dh_use = implementation_defined; + static const uint64_t single_dh_use = implementation_defined; /// Disable SSL v2. - static const long no_sslv2 = implementation_defined; + static const uint64_t no_sslv2 = implementation_defined; /// Disable SSL v3. - static const long no_sslv3 = implementation_defined; + static const uint64_t no_sslv3 = implementation_defined; /// Disable TLS v1. - static const long no_tlsv1 = implementation_defined; + static const uint64_t no_tlsv1 = implementation_defined; /// Disable TLS v1.1. - static const long no_tlsv1_1 = implementation_defined; + static const uint64_t no_tlsv1_1 = implementation_defined; /// Disable TLS v1.2. - static const long no_tlsv1_2 = implementation_defined; + static const uint64_t no_tlsv1_2 = implementation_defined; /// Disable TLS v1.3. - static const long no_tlsv1_3 = implementation_defined; + static const uint64_t no_tlsv1_3 = implementation_defined; /// Disable compression. Compression is disabled by default. - static const long no_compression = implementation_defined; + static const uint64_t no_compression = implementation_defined; #else - ASIO_STATIC_CONSTANT(long, default_workarounds = SSL_OP_ALL); - ASIO_STATIC_CONSTANT(long, single_dh_use = SSL_OP_SINGLE_DH_USE); - ASIO_STATIC_CONSTANT(long, no_sslv2 = SSL_OP_NO_SSLv2); - ASIO_STATIC_CONSTANT(long, no_sslv3 = SSL_OP_NO_SSLv3); - ASIO_STATIC_CONSTANT(long, no_tlsv1 = SSL_OP_NO_TLSv1); + ASIO_STATIC_CONSTANT(uint64_t, default_workarounds = SSL_OP_ALL); + ASIO_STATIC_CONSTANT(uint64_t, single_dh_use = SSL_OP_SINGLE_DH_USE); + ASIO_STATIC_CONSTANT(uint64_t, no_sslv2 = SSL_OP_NO_SSLv2); + ASIO_STATIC_CONSTANT(uint64_t, no_sslv3 = SSL_OP_NO_SSLv3); + ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1 = SSL_OP_NO_TLSv1); # if defined(SSL_OP_NO_TLSv1_1) - ASIO_STATIC_CONSTANT(long, no_tlsv1_1 = SSL_OP_NO_TLSv1_1); + ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_1 = SSL_OP_NO_TLSv1_1); # else // defined(SSL_OP_NO_TLSv1_1) - ASIO_STATIC_CONSTANT(long, no_tlsv1_1 = 0x10000000L); + ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_1 = 0x10000000L); # endif // defined(SSL_OP_NO_TLSv1_1) # if defined(SSL_OP_NO_TLSv1_2) - ASIO_STATIC_CONSTANT(long, no_tlsv1_2 = SSL_OP_NO_TLSv1_2); + ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_2 = SSL_OP_NO_TLSv1_2); # else // defined(SSL_OP_NO_TLSv1_2) - ASIO_STATIC_CONSTANT(long, no_tlsv1_2 = 0x08000000L); + ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_2 = 0x08000000L); # endif // defined(SSL_OP_NO_TLSv1_2) # if defined(SSL_OP_NO_TLSv1_3) - ASIO_STATIC_CONSTANT(long, no_tlsv1_3 = SSL_OP_NO_TLSv1_3); + ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_3 = SSL_OP_NO_TLSv1_3); # else // defined(SSL_OP_NO_TLSv1_3) - ASIO_STATIC_CONSTANT(long, no_tlsv1_3 = 0x20000000L); + ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_3 = 0x20000000L); # endif // defined(SSL_OP_NO_TLSv1_3) # if defined(SSL_OP_NO_COMPRESSION) - ASIO_STATIC_CONSTANT(long, no_compression = SSL_OP_NO_COMPRESSION); + ASIO_STATIC_CONSTANT(uint64_t, no_compression = SSL_OP_NO_COMPRESSION); # else // defined(SSL_OP_NO_COMPRESSION) - ASIO_STATIC_CONSTANT(long, no_compression = 0x20000L); + ASIO_STATIC_CONSTANT(uint64_t, no_compression = 0x20000L); # endif // defined(SSL_OP_NO_COMPRESSION) #endif diff --git a/3rdparty/asio/include/asio/ssl/detail/buffered_handshake_op.hpp b/3rdparty/asio/include/asio/ssl/detail/buffered_handshake_op.hpp index ee1e32d36fc..4dba7120929 100644 --- a/3rdparty/asio/include/asio/ssl/detail/buffered_handshake_op.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/buffered_handshake_op.hpp @@ -2,7 +2,7 @@ // ssl/detail/buffered_handshake_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -29,7 +29,7 @@ template <typename ConstBufferSequence> class buffered_handshake_op { public: - static ASIO_CONSTEXPR const char* tracking_name() + static constexpr const char* tracking_name() { return "ssl::stream<>::async_buffered_handshake"; } @@ -56,7 +56,7 @@ public: const asio::error_code& ec, const std::size_t& bytes_transferred) const { - ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec, bytes_transferred); + static_cast<Handler&&>(handler)(ec, bytes_transferred); } private: diff --git a/3rdparty/asio/include/asio/ssl/detail/engine.hpp b/3rdparty/asio/include/asio/ssl/detail/engine.hpp index 40799330b73..e500ca529da 100644 --- a/3rdparty/asio/include/asio/ssl/detail/engine.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/engine.hpp @@ -2,7 +2,7 @@ // ssl/detail/engine.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -58,18 +58,17 @@ public: // Construct a new engine for the specified context. ASIO_DECL explicit engine(SSL_CTX* context); -#if defined(ASIO_HAS_MOVE) + // Construct a new engine for an existing native SSL implementation. + ASIO_DECL explicit engine(SSL* ssl_impl); + // Move construct from another engine. - ASIO_DECL engine(engine&& other) ASIO_NOEXCEPT; -#endif // defined(ASIO_HAS_MOVE) + ASIO_DECL engine(engine&& other) noexcept; // Destructor. ASIO_DECL ~engine(); -#if defined(ASIO_HAS_MOVE) // Move assign from another engine. - ASIO_DECL engine& operator=(engine&& other) ASIO_NOEXCEPT; -#endif // defined(ASIO_HAS_MOVE) + ASIO_DECL engine& operator=(engine&& other) noexcept; // Get the underlying implementation in the native type. ASIO_DECL SSL* native_handle(); diff --git a/3rdparty/asio/include/asio/ssl/detail/handshake_op.hpp b/3rdparty/asio/include/asio/ssl/detail/handshake_op.hpp index 74b624fde81..53533eb7a80 100644 --- a/3rdparty/asio/include/asio/ssl/detail/handshake_op.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/handshake_op.hpp @@ -2,7 +2,7 @@ // ssl/detail/handshake_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -28,7 +28,7 @@ namespace detail { class handshake_op { public: - static ASIO_CONSTEXPR const char* tracking_name() + static constexpr const char* tracking_name() { return "ssl::stream<>::async_handshake"; } @@ -51,7 +51,7 @@ public: const asio::error_code& ec, const std::size_t&) const { - ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec); + static_cast<Handler&&>(handler)(ec); } private: diff --git a/3rdparty/asio/include/asio/ssl/detail/impl/engine.ipp b/3rdparty/asio/include/asio/ssl/detail/impl/engine.ipp index 2c047389f00..91588cd6b47 100644 --- a/3rdparty/asio/include/asio/ssl/detail/impl/engine.ipp +++ b/3rdparty/asio/include/asio/ssl/detail/impl/engine.ipp @@ -2,7 +2,7 @@ // ssl/detail/impl/engine.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -55,15 +55,31 @@ engine::engine(SSL_CTX* context) ::SSL_set_bio(ssl_, int_bio, int_bio); } -#if defined(ASIO_HAS_MOVE) -engine::engine(engine&& other) ASIO_NOEXCEPT +engine::engine(SSL* ssl_impl) + : ssl_(ssl_impl) +{ +#if (OPENSSL_VERSION_NUMBER < 0x10000000L) + accept_mutex().init(); +#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L) + + ::SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE); + ::SSL_set_mode(ssl_, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); +#if defined(SSL_MODE_RELEASE_BUFFERS) + ::SSL_set_mode(ssl_, SSL_MODE_RELEASE_BUFFERS); +#endif // defined(SSL_MODE_RELEASE_BUFFERS) + + ::BIO* int_bio = 0; + ::BIO_new_bio_pair(&int_bio, 0, &ext_bio_, 0); + ::SSL_set_bio(ssl_, int_bio, int_bio); +} + +engine::engine(engine&& other) noexcept : ssl_(other.ssl_), ext_bio_(other.ext_bio_) { other.ssl_ = 0; other.ext_bio_ = 0; } -#endif // defined(ASIO_HAS_MOVE) engine::~engine() { @@ -80,8 +96,7 @@ engine::~engine() ::SSL_free(ssl_); } -#if defined(ASIO_HAS_MOVE) -engine& engine::operator=(engine&& other) ASIO_NOEXCEPT +engine& engine::operator=(engine&& other) noexcept { if (this != &other) { @@ -92,7 +107,6 @@ engine& engine::operator=(engine&& other) ASIO_NOEXCEPT } return *this; } -#endif // defined(ASIO_HAS_MOVE) SSL* engine::native_handle() { diff --git a/3rdparty/asio/include/asio/ssl/detail/impl/openssl_init.ipp b/3rdparty/asio/include/asio/ssl/detail/impl/openssl_init.ipp index 2c38e03a1f0..7a10cc2aa8a 100644 --- a/3rdparty/asio/include/asio/ssl/detail/impl/openssl_init.ipp +++ b/3rdparty/asio/include/asio/ssl/detail/impl/openssl_init.ipp @@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2005-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -85,9 +85,13 @@ public: #endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L) // && (OPENSSL_VERSION_NUMBER < 0x10100000L) // && !defined(SSL_OP_NO_COMPRESSION) -#if !defined(OPENSSL_IS_BORINGSSL) && !defined(ASIO_USE_WOLFSSL) +#if !defined(OPENSSL_IS_BORINGSSL) \ + && !defined(ASIO_USE_WOLFSSL) \ + && (OPENSSL_VERSION_NUMBER < 0x30000000L) ::CONF_modules_unload(1); -#endif // !defined(OPENSSL_IS_BORINGSSL) && !defined(ASIO_USE_WOLFSSL) +#endif // !defined(OPENSSL_IS_BORINGSSL) + // && !defined(ASIO_USE_WOLFSSL) + // && (OPENSSL_VERSION_NUMBER < 0x30000000L) #if !defined(OPENSSL_NO_ENGINE) \ && (OPENSSL_VERSION_NUMBER < 0x10100000L) ::ENGINE_cleanup(); @@ -130,7 +134,7 @@ private: // Mutexes to be used in locking callbacks. std::vector<asio::detail::shared_ptr< - asio::detail::mutex> > mutexes_; + asio::detail::mutex>> mutexes_; #endif // (OPENSSL_VERSION_NUMBER < 0x10100000L) #if !defined(SSL_OP_NO_COMPRESSION) \ diff --git a/3rdparty/asio/include/asio/ssl/detail/io.hpp b/3rdparty/asio/include/asio/ssl/detail/io.hpp index b8c85dc6b53..d951db593af 100644 --- a/3rdparty/asio/include/asio/ssl/detail/io.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/io.hpp @@ -2,7 +2,7 @@ // ssl/detail/io.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -107,11 +107,10 @@ public: start_(0), want_(engine::want_nothing), bytes_transferred_(0), - handler_(ASIO_MOVE_CAST(Handler)(handler)) + handler_(static_cast<Handler&&>(handler)) { } -#if defined(ASIO_HAS_MOVE) io_op(const io_op& other) : asio::detail::base_from_cancellation_state<Handler>(other), next_layer_(other.next_layer_), @@ -127,20 +126,18 @@ public: io_op(io_op&& other) : asio::detail::base_from_cancellation_state<Handler>( - ASIO_MOVE_CAST( - asio::detail::base_from_cancellation_state<Handler>)( - other)), + static_cast< + asio::detail::base_from_cancellation_state<Handler>&&>(other)), next_layer_(other.next_layer_), core_(other.core_), - op_(ASIO_MOVE_CAST(Operation)(other.op_)), + op_(static_cast<Operation&&>(other.op_)), start_(other.start_), want_(other.want_), ec_(other.ec_), bytes_transferred_(other.bytes_transferred_), - handler_(ASIO_MOVE_CAST(Handler)(other.handler_)) + handler_(static_cast<Handler&&>(other.handler_)) { } -#endif // defined(ASIO_HAS_MOVE) void operator()(asio::error_code ec, std::size_t bytes_transferred = ~std::size_t(0), int start = 0) @@ -177,7 +174,7 @@ public: // Start reading some data from the underlying transport. next_layer_.async_read_some( asio::buffer(core_.input_buffer_), - ASIO_MOVE_CAST(io_op)(*this)); + static_cast<io_op&&>(*this)); } else { @@ -185,7 +182,7 @@ public: __FILE__, __LINE__, Operation::tracking_name())); // Wait until the current read operation completes. - core_.pending_read_.async_wait(ASIO_MOVE_CAST(io_op)(*this)); + core_.pending_read_.async_wait(static_cast<io_op&&>(*this)); } // Yield control until asynchronous operation completes. Control @@ -210,7 +207,7 @@ public: // Start writing all the data to the underlying transport. asio::async_write(next_layer_, core_.engine_.get_output(core_.output_buffer_), - ASIO_MOVE_CAST(io_op)(*this)); + static_cast<io_op&&>(*this)); } else { @@ -218,7 +215,7 @@ public: __FILE__, __LINE__, Operation::tracking_name())); // Wait until the current write operation completes. - core_.pending_write_.async_wait(ASIO_MOVE_CAST(io_op)(*this)); + core_.pending_write_.async_wait(static_cast<io_op&&>(*this)); } // Yield control until asynchronous operation completes. Control @@ -239,7 +236,7 @@ public: next_layer_.async_read_some( asio::buffer(core_.input_buffer_, 0), - ASIO_MOVE_CAST(io_op)(*this)); + static_cast<io_op&&>(*this)); // Yield control until asynchronous operation completes. Control // resumes at the "default:" label below. @@ -331,32 +328,6 @@ public: }; template <typename Stream, typename Operation, typename Handler> -inline asio_handler_allocate_is_deprecated -asio_handler_allocate(std::size_t size, - io_op<Stream, Operation, Handler>* this_handler) -{ -#if defined(ASIO_NO_DEPRECATED) - asio_handler_alloc_helpers::allocate(size, this_handler->handler_); - return asio_handler_allocate_is_no_longer_used(); -#else // defined(ASIO_NO_DEPRECATED) - return asio_handler_alloc_helpers::allocate( - size, this_handler->handler_); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Stream, typename Operation, typename Handler> -inline asio_handler_deallocate_is_deprecated -asio_handler_deallocate(void* pointer, std::size_t size, - io_op<Stream, Operation, Handler>* this_handler) -{ - asio_handler_alloc_helpers::deallocate( - pointer, size, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_deallocate_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Stream, typename Operation, typename Handler> inline bool asio_handler_is_continuation( io_op<Stream, Operation, Handler>* this_handler) { @@ -364,32 +335,6 @@ inline bool asio_handler_is_continuation( : asio_handler_cont_helpers::is_continuation(this_handler->handler_); } -template <typename Function, typename Stream, - typename Operation, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(Function& function, - io_op<Stream, Operation, Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - -template <typename Function, typename Stream, - typename Operation, typename Handler> -inline asio_handler_invoke_is_deprecated -asio_handler_invoke(const Function& function, - io_op<Stream, Operation, Handler>* this_handler) -{ - asio_handler_invoke_helpers::invoke( - function, this_handler->handler_); -#if defined(ASIO_NO_DEPRECATED) - return asio_handler_invoke_is_no_longer_used(); -#endif // defined(ASIO_NO_DEPRECATED) -} - template <typename Stream, typename Operation, typename Handler> inline void async_io(Stream& next_layer, stream_core& core, const Operation& op, Handler& handler) @@ -411,8 +356,14 @@ struct associator<Associator, : Associator<Handler, DefaultCandidate> { static typename Associator<Handler, DefaultCandidate>::type get( - const ssl::detail::io_op<Stream, Operation, Handler>& h, - const DefaultCandidate& c = DefaultCandidate()) ASIO_NOEXCEPT + const ssl::detail::io_op<Stream, Operation, Handler>& h) noexcept + { + return Associator<Handler, DefaultCandidate>::get(h.handler_); + } + + static auto get(const ssl::detail::io_op<Stream, Operation, Handler>& h, + const DefaultCandidate& c) noexcept + -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c)) { return Associator<Handler, DefaultCandidate>::get(h.handler_, c); } diff --git a/3rdparty/asio/include/asio/ssl/detail/openssl_init.hpp b/3rdparty/asio/include/asio/ssl/detail/openssl_init.hpp index 8921bb64137..c66d9d62692 100644 --- a/3rdparty/asio/include/asio/ssl/detail/openssl_init.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/openssl_init.hpp @@ -2,7 +2,7 @@ // ssl/detail/openssl_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/detail/openssl_types.hpp b/3rdparty/asio/include/asio/ssl/detail/openssl_types.hpp index 0b1b8f90b1d..25f080f1e8e 100644 --- a/3rdparty/asio/include/asio/ssl/detail/openssl_types.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/openssl_types.hpp @@ -2,7 +2,7 @@ // ssl/detail/openssl_types.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/detail/password_callback.hpp b/3rdparty/asio/include/asio/ssl/detail/password_callback.hpp index 0e5e39824ef..03ac7db0f06 100644 --- a/3rdparty/asio/include/asio/ssl/detail/password_callback.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/password_callback.hpp @@ -2,7 +2,7 @@ // ssl/detail/password_callback.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/detail/read_op.hpp b/3rdparty/asio/include/asio/ssl/detail/read_op.hpp index fb2cf62f84a..5cb4249556f 100644 --- a/3rdparty/asio/include/asio/ssl/detail/read_op.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/read_op.hpp @@ -2,7 +2,7 @@ // ssl/detail/read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -30,7 +30,7 @@ template <typename MutableBufferSequence> class read_op { public: - static ASIO_CONSTEXPR const char* tracking_name() + static constexpr const char* tracking_name() { return "ssl::stream<>::async_read_some"; } @@ -56,7 +56,7 @@ public: const asio::error_code& ec, const std::size_t& bytes_transferred) const { - ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec, bytes_transferred); + static_cast<Handler&&>(handler)(ec, bytes_transferred); } private: diff --git a/3rdparty/asio/include/asio/ssl/detail/shutdown_op.hpp b/3rdparty/asio/include/asio/ssl/detail/shutdown_op.hpp index 2a8927db357..1f6b91e17c1 100644 --- a/3rdparty/asio/include/asio/ssl/detail/shutdown_op.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/shutdown_op.hpp @@ -2,7 +2,7 @@ // ssl/detail/shutdown_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -28,7 +28,7 @@ namespace detail { class shutdown_op { public: - static ASIO_CONSTEXPR const char* tracking_name() + static constexpr const char* tracking_name() { return "ssl::stream<>::async_shutdown"; } @@ -51,11 +51,11 @@ public: // The engine only generates an eof when the shutdown notification has // been received from the peer. This indicates that the shutdown has // completed successfully, and thus need not be passed on to the handler. - ASIO_MOVE_OR_LVALUE(Handler)(handler)(asio::error_code()); + static_cast<Handler&&>(handler)(asio::error_code()); } else { - ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec); + static_cast<Handler&&>(handler)(ec); } } }; diff --git a/3rdparty/asio/include/asio/ssl/detail/stream_core.hpp b/3rdparty/asio/include/asio/ssl/detail/stream_core.hpp index 27b77cf11f2..0ec763d4a2b 100644 --- a/3rdparty/asio/include/asio/ssl/detail/stream_core.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/stream_core.hpp @@ -2,7 +2,7 @@ // ssl/detail/stream_core.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -51,30 +51,43 @@ struct stream_core pending_write_.expires_at(neg_infin()); } -#if defined(ASIO_HAS_MOVE) + template <typename Executor> + stream_core(SSL* ssl_impl, const Executor& ex) + : engine_(ssl_impl), + pending_read_(ex), + pending_write_(ex), + output_buffer_space_(max_tls_record_size), + output_buffer_(asio::buffer(output_buffer_space_)), + input_buffer_space_(max_tls_record_size), + input_buffer_(asio::buffer(input_buffer_space_)) + { + pending_read_.expires_at(neg_infin()); + pending_write_.expires_at(neg_infin()); + } + stream_core(stream_core&& other) - : engine_(ASIO_MOVE_CAST(engine)(other.engine_)), + : engine_(static_cast<engine&&>(other.engine_)), #if defined(ASIO_HAS_BOOST_DATE_TIME) pending_read_( - ASIO_MOVE_CAST(asio::deadline_timer)( + static_cast<asio::deadline_timer&&>( other.pending_read_)), pending_write_( - ASIO_MOVE_CAST(asio::deadline_timer)( + static_cast<asio::deadline_timer&&>( other.pending_write_)), #else // defined(ASIO_HAS_BOOST_DATE_TIME) pending_read_( - ASIO_MOVE_CAST(asio::steady_timer)( + static_cast<asio::steady_timer&&>( other.pending_read_)), pending_write_( - ASIO_MOVE_CAST(asio::steady_timer)( + static_cast<asio::steady_timer&&>( other.pending_write_)), #endif // defined(ASIO_HAS_BOOST_DATE_TIME) output_buffer_space_( - ASIO_MOVE_CAST(std::vector<unsigned char>)( + static_cast<std::vector<unsigned char>&&>( other.output_buffer_space_)), output_buffer_(other.output_buffer_), input_buffer_space_( - ASIO_MOVE_CAST(std::vector<unsigned char>)( + static_cast<std::vector<unsigned char>&&>( other.input_buffer_space_)), input_buffer_(other.input_buffer_), input_(other.input_) @@ -83,40 +96,39 @@ struct stream_core other.input_buffer_ = asio::mutable_buffer(0, 0); other.input_ = asio::const_buffer(0, 0); } -#endif // defined(ASIO_HAS_MOVE) ~stream_core() { } -#if defined(ASIO_HAS_MOVE) stream_core& operator=(stream_core&& other) { if (this != &other) { - engine_ = ASIO_MOVE_CAST(engine)(other.engine_); + engine_ = static_cast<engine&&>(other.engine_); #if defined(ASIO_HAS_BOOST_DATE_TIME) pending_read_ = - ASIO_MOVE_CAST(asio::deadline_timer)( + static_cast<asio::deadline_timer&&>( other.pending_read_); pending_write_ = - ASIO_MOVE_CAST(asio::deadline_timer)( + static_cast<asio::deadline_timer&&>( other.pending_write_); #else // defined(ASIO_HAS_BOOST_DATE_TIME) pending_read_ = - ASIO_MOVE_CAST(asio::steady_timer)( + static_cast<asio::steady_timer&&>( other.pending_read_); pending_write_ = - ASIO_MOVE_CAST(asio::steady_timer)( + static_cast<asio::steady_timer&&>( other.pending_write_); #endif // defined(ASIO_HAS_BOOST_DATE_TIME) output_buffer_space_ = - ASIO_MOVE_CAST(std::vector<unsigned char>)( + static_cast<std::vector<unsigned char>&&>( other.output_buffer_space_); output_buffer_ = other.output_buffer_; input_buffer_space_ = - ASIO_MOVE_CAST(std::vector<unsigned char>)( + static_cast<std::vector<unsigned char>&&>( other.input_buffer_space_); + input_buffer_ = other.input_buffer_; input_ = other.input_; other.output_buffer_ = asio::mutable_buffer(0, 0); other.input_buffer_ = asio::mutable_buffer(0, 0); @@ -124,7 +136,6 @@ struct stream_core } return *this; } -#endif // defined(ASIO_HAS_MOVE) // The SSL engine. engine engine_; diff --git a/3rdparty/asio/include/asio/ssl/detail/verify_callback.hpp b/3rdparty/asio/include/asio/ssl/detail/verify_callback.hpp index 7f13fe49536..54169c9e6b8 100644 --- a/3rdparty/asio/include/asio/ssl/detail/verify_callback.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/verify_callback.hpp @@ -1,8 +1,8 @@ // // ssl/detail/verify_callback.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/detail/write_op.hpp b/3rdparty/asio/include/asio/ssl/detail/write_op.hpp index 407995b4fad..edcbcad5850 100644 --- a/3rdparty/asio/include/asio/ssl/detail/write_op.hpp +++ b/3rdparty/asio/include/asio/ssl/detail/write_op.hpp @@ -2,7 +2,7 @@ // ssl/detail/write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -30,7 +30,7 @@ template <typename ConstBufferSequence> class write_op { public: - static ASIO_CONSTEXPR const char* tracking_name() + static constexpr const char* tracking_name() { return "ssl::stream<>::async_write_some"; } @@ -60,7 +60,7 @@ public: const asio::error_code& ec, const std::size_t& bytes_transferred) const { - ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec, bytes_transferred); + static_cast<Handler&&>(handler)(ec, bytes_transferred); } private: diff --git a/3rdparty/asio/include/asio/ssl/error.hpp b/3rdparty/asio/include/asio/ssl/error.hpp index f1d1801cde4..e126f52c1c7 100644 --- a/3rdparty/asio/include/asio/ssl/error.hpp +++ b/3rdparty/asio/include/asio/ssl/error.hpp @@ -2,7 +2,7 @@ // ssl/error.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -77,7 +77,6 @@ static const asio::error_category& } // namespace ssl } // namespace asio -#if defined(ASIO_HAS_STD_SYSTEM_ERROR) namespace std { template<> struct is_error_code_enum<asio::error::ssl_errors> @@ -91,7 +90,6 @@ template<> struct is_error_code_enum<asio::ssl::error::stream_errors> }; } // namespace std -#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR) namespace asio { namespace error { diff --git a/3rdparty/asio/include/asio/ssl/host_name_verification.hpp b/3rdparty/asio/include/asio/ssl/host_name_verification.hpp index 0aabac54893..adb6ac8c0f7 100644 --- a/3rdparty/asio/include/asio/ssl/host_name_verification.hpp +++ b/3rdparty/asio/include/asio/ssl/host_name_verification.hpp @@ -2,7 +2,7 @@ // ssl/host_name_verification.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/impl/context.hpp b/3rdparty/asio/include/asio/ssl/impl/context.hpp index 1734e7bd262..2324a9880aa 100644 --- a/3rdparty/asio/include/asio/ssl/impl/context.hpp +++ b/3rdparty/asio/include/asio/ssl/impl/context.hpp @@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2005-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/impl/context.ipp b/3rdparty/asio/include/asio/ssl/impl/context.ipp index 56f8d7d2775..8711048b9a7 100644 --- a/3rdparty/asio/include/asio/ssl/impl/context.ipp +++ b/3rdparty/asio/include/asio/ssl/impl/context.ipp @@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com -// Copyright (c) 2005-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2005-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -47,6 +47,7 @@ struct context::evp_pkey_cleanup ~evp_pkey_cleanup() { if (p) ::EVP_PKEY_free(p); } }; +#if (OPENSSL_VERSION_NUMBER < 0x30000000L) struct context::rsa_cleanup { RSA* p; @@ -58,6 +59,7 @@ struct context::dh_cleanup DH* p; ~dh_cleanup() { if (p) ::DH_free(p); } }; +#endif // (OPENSSL_VERSION_NUMBER < 0x30000000L) context::context(context::method m) : handle_(0) @@ -357,9 +359,7 @@ context::context(context::method m) if (handle_ == 0) { - asio::error_code ec( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + asio::error_code ec = translate_error(::ERR_get_error()); asio::detail::throw_error(ec, "context"); } @@ -376,7 +376,6 @@ context::context(context::native_handle_type native_handle) } } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) context::context(context&& other) { handle_ = other.handle_; @@ -385,12 +384,11 @@ context::context(context&& other) context& context::operator=(context&& other) { - context tmp(ASIO_MOVE_CAST(context)(*this)); + context tmp(static_cast<context&&>(*this)); handle_ = other.handle_; other.handle_ = 0; return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) context::~context() { @@ -545,9 +543,7 @@ ASIO_SYNC_OP_VOID context::load_verify_file( if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1) { - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -582,17 +578,13 @@ ASIO_SYNC_OP_VOID context::add_certificate_authority( && ERR_GET_REASON(err) == PEM_R_NO_START_LINE) break; - ec = asio::error_code( - static_cast<int>(err), - asio::error::get_ssl_category()); + ec = translate_error(err); ASIO_SYNC_OP_VOID_RETURN(ec); } if (::X509_STORE_add_cert(store, cert.p) != 1) { - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } } @@ -617,9 +609,7 @@ ASIO_SYNC_OP_VOID context::set_default_verify_paths( if (::SSL_CTX_set_default_verify_paths(handle_) != 1) { - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -641,9 +631,7 @@ ASIO_SYNC_OP_VOID context::add_verify_path( if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1) { - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -697,9 +685,7 @@ ASIO_SYNC_OP_VOID context::use_certificate( ASIO_SYNC_OP_VOID_RETURN(ec); } - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -735,9 +721,7 @@ ASIO_SYNC_OP_VOID context::use_certificate_file( if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1) { - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -776,17 +760,14 @@ ASIO_SYNC_OP_VOID context::use_certificate_chain( cb_userdata) }; if (!cert.p) { - ec = asio::error_code(ERR_R_PEM_LIB, - asio::error::get_ssl_category()); + ec = translate_error(ERR_R_PEM_LIB); ASIO_SYNC_OP_VOID_RETURN(ec); } int result = ::SSL_CTX_use_certificate(handle_, cert.p); if (result == 0 || ::ERR_peek_error() != 0) { - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -809,9 +790,7 @@ ASIO_SYNC_OP_VOID context::use_certificate_chain( { if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert)) { - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } } @@ -826,9 +805,7 @@ ASIO_SYNC_OP_VOID context::use_certificate_chain( } } - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -846,9 +823,7 @@ ASIO_SYNC_OP_VOID context::use_certificate_chain_file( if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1) { - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -912,9 +887,7 @@ ASIO_SYNC_OP_VOID context::use_private_key( } } - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -944,16 +917,51 @@ ASIO_SYNC_OP_VOID context::use_rsa_private_key( && (!defined(LIBRESSL_VERSION_NUMBER) \ || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \ || defined(ASIO_USE_WOLFSSL) - pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_); - void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); + pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_); + void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) - pem_password_cb* callback = handle_->default_passwd_callback; - void* cb_userdata = handle_->default_passwd_callback_userdata; + pem_password_cb* callback = handle_->default_passwd_callback; + void* cb_userdata = handle_->default_passwd_callback_userdata; #endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) bio_cleanup bio = { make_buffer_bio(private_key) }; if (bio.p) { +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + evp_pkey_cleanup evp_private_key = { 0 }; + switch (format) + { + case context_base::asn1: + evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0); + break; + case context_base::pem: + evp_private_key.p = ::PEM_read_bio_PrivateKey( + bio.p, 0, callback, + cb_userdata); + break; + default: + { + ec = asio::error::invalid_argument; + ASIO_SYNC_OP_VOID_RETURN(ec); + } + } + + if (evp_private_key.p) + { + if (::EVP_PKEY_is_a(evp_private_key.p, "RSA") == 0) + { + ec = translate_error( + ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY)); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1) + { + ec = asio::error_code(); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + } +#else // (OPENSSL_VERSION_NUMBER >= 0x30000000L) rsa_cleanup rsa_private_key = { 0 }; switch (format) { @@ -980,11 +988,10 @@ ASIO_SYNC_OP_VOID context::use_rsa_private_key( ASIO_SYNC_OP_VOID_RETURN(ec); } } +#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L) } - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1012,9 +1019,7 @@ ASIO_SYNC_OP_VOID context::use_private_key_file( if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1) { - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1034,6 +1039,53 @@ ASIO_SYNC_OP_VOID context::use_rsa_private_key_file( const std::string& filename, context::file_format format, asio::error_code& ec) { +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + ::ERR_clear_error(); + + pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_); + void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); + + bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") }; + if (bio.p) + { + evp_pkey_cleanup evp_private_key = { 0 }; + switch (format) + { + case context_base::asn1: + evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0); + break; + case context_base::pem: + evp_private_key.p = ::PEM_read_bio_PrivateKey( + bio.p, 0, callback, + cb_userdata); + break; + default: + { + ec = asio::error::invalid_argument; + ASIO_SYNC_OP_VOID_RETURN(ec); + } + } + + if (evp_private_key.p) + { + if (::EVP_PKEY_is_a(evp_private_key.p, "RSA") == 0) + { + ec = translate_error( + ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY)); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + + if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1) + { + ec = asio::error_code(); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + } + } + + ec = translate_error(::ERR_get_error()); + ASIO_SYNC_OP_VOID_RETURN(ec); +#else // (OPENSSL_VERSION_NUMBER >= 0x30000000L) int file_type; switch (format) { @@ -1055,14 +1107,13 @@ ASIO_SYNC_OP_VOID context::use_rsa_private_key_file( if (::SSL_CTX_use_RSAPrivateKey_file( handle_, filename.c_str(), file_type) != 1) { - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } ec = asio::error_code(); ASIO_SYNC_OP_VOID_RETURN(ec); +#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L) } void context::use_tmp_dh(const const_buffer& dh) @@ -1083,9 +1134,7 @@ ASIO_SYNC_OP_VOID context::use_tmp_dh( return do_use_tmp_dh(bio.p, ec); } - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1107,9 +1156,7 @@ ASIO_SYNC_OP_VOID context::use_tmp_dh_file( return do_use_tmp_dh(bio.p, ec); } - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1118,6 +1165,19 @@ ASIO_SYNC_OP_VOID context::do_use_tmp_dh( { ::ERR_clear_error(); +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + EVP_PKEY* p = ::PEM_read_bio_Parameters(bio, 0); + if (p) + { + if (::SSL_CTX_set0_tmp_dh_pkey(handle_, p) == 1) + { + ec = asio::error_code(); + ASIO_SYNC_OP_VOID_RETURN(ec); + } + else + ::EVP_PKEY_free(p); + } +#else // (OPENSSL_VERSION_NUMBER >= 0x30000000L) dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) }; if (dh.p) { @@ -1127,10 +1187,9 @@ ASIO_SYNC_OP_VOID context::do_use_tmp_dh( ASIO_SYNC_OP_VOID_RETURN(ec); } } +#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L) - ec = asio::error_code( - static_cast<int>(::ERR_get_error()), - asio::error::get_ssl_category()); + ec = translate_error(::ERR_get_error()); ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1237,6 +1296,21 @@ BIO* context::make_buffer_bio(const const_buffer& b) static_cast<int>(b.size())); } +asio::error_code context::translate_error(long error) +{ +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + if (ERR_SYSTEM_ERROR(error)) + { + return asio::error_code( + static_cast<int>(ERR_GET_REASON(error)), + asio::error::get_system_category()); + } +#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L) + + return asio::error_code(static_cast<int>(error), + asio::error::get_ssl_category()); +} + } // namespace ssl } // namespace asio diff --git a/3rdparty/asio/include/asio/ssl/impl/error.ipp b/3rdparty/asio/include/asio/ssl/impl/error.ipp index dbc1fa0a084..7ff6e8a7359 100644 --- a/3rdparty/asio/include/asio/ssl/impl/error.ipp +++ b/3rdparty/asio/include/asio/ssl/impl/error.ipp @@ -2,7 +2,7 @@ // ssl/impl/error.ipp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -28,15 +28,37 @@ namespace detail { class ssl_category : public asio::error_category { public: - const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT + const char* name() const noexcept { return "asio.ssl"; } std::string message(int value) const { - const char* s = ::ERR_reason_error_string(value); - return s ? s : "asio.ssl error"; + const char* reason = ::ERR_reason_error_string(value); + if (reason) + { + const char* lib = ::ERR_lib_error_string(value); +#if (OPENSSL_VERSION_NUMBER < 0x30000000L) + const char* func = ::ERR_func_error_string(value); +#else // (OPENSSL_VERSION_NUMBER < 0x30000000L) + const char* func = 0; +#endif // (OPENSSL_VERSION_NUMBER < 0x30000000L) + std::string result(reason); + if (lib || func) + { + result += " ("; + if (lib) + result += lib; + if (lib && func) + result += ", "; + if (func) + result += func; + result += ")"; + } + return result; + } + return "asio.ssl error"; } }; @@ -66,7 +88,7 @@ namespace detail { class stream_category : public asio::error_category { public: - const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT + const char* name() const noexcept { return "asio.ssl.stream"; } diff --git a/3rdparty/asio/include/asio/ssl/impl/host_name_verification.ipp b/3rdparty/asio/include/asio/ssl/impl/host_name_verification.ipp index adfcbdcc7e4..198d1f3989c 100644 --- a/3rdparty/asio/include/asio/ssl/impl/host_name_verification.ipp +++ b/3rdparty/asio/include/asio/ssl/impl/host_name_verification.ipp @@ -2,7 +2,7 @@ // ssl/impl/host_name_verification.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/impl/rfc2818_verification.ipp b/3rdparty/asio/include/asio/ssl/impl/rfc2818_verification.ipp index 9e198e76060..93e161daa85 100644 --- a/3rdparty/asio/include/asio/ssl/impl/rfc2818_verification.ipp +++ b/3rdparty/asio/include/asio/ssl/impl/rfc2818_verification.ipp @@ -2,7 +2,7 @@ // ssl/impl/rfc2818_verification.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/impl/src.hpp b/3rdparty/asio/include/asio/ssl/impl/src.hpp index 4be197132e1..5ffb95fdcd6 100644 --- a/3rdparty/asio/include/asio/ssl/impl/src.hpp +++ b/3rdparty/asio/include/asio/ssl/impl/src.hpp @@ -2,7 +2,7 @@ // impl/ssl/src.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/rfc2818_verification.hpp b/3rdparty/asio/include/asio/ssl/rfc2818_verification.hpp index c5a9b9ea59c..db2831045d9 100644 --- a/3rdparty/asio/include/asio/ssl/rfc2818_verification.hpp +++ b/3rdparty/asio/include/asio/ssl/rfc2818_verification.hpp @@ -2,7 +2,7 @@ // ssl/rfc2818_verification.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/stream.hpp b/3rdparty/asio/include/asio/ssl/stream.hpp index 616be7b806f..befcc287e7f 100644 --- a/3rdparty/asio/include/asio/ssl/stream.hpp +++ b/3rdparty/asio/include/asio/ssl/stream.hpp @@ -2,7 +2,7 @@ // ssl/stream.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include "asio/async_result.hpp" +#include "asio/buffer.hpp" #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/handler_type_requirements.hpp" #include "asio/detail/non_const_lvalue.hpp" @@ -54,7 +55,7 @@ namespace ssl { * @code * asio::io_context my_context; * asio::ssl::context ctx(asio::ssl::context::sslv23); - * asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx); + * asio::ssl::stream<asio::ip::tcp::socket> sock(my_context, ctx); * @endcode * * @par Concepts: @@ -65,6 +66,13 @@ class stream : public stream_base, private noncopyable { +private: + class initiate_async_handshake; + class initiate_async_buffered_handshake; + class initiate_async_shutdown; + class initiate_async_write_some; + class initiate_async_read_some; + public: /// The native handle type of the SSL stream. typedef SSL* native_handle_type; @@ -76,7 +84,7 @@ public: }; /// The type of the next layer. - typedef typename remove_reference<Stream>::type next_layer_type; + typedef remove_reference_t<Stream> next_layer_type; /// The type of the lowest layer. typedef typename next_layer_type::lowest_layer_type lowest_layer_type; @@ -84,7 +92,6 @@ public: /// The type of the executor associated with the object. typedef typename lowest_layer_type::executor_type executor_type; -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Construct a stream. /** * This constructor creates a stream and initialises the underlying stream @@ -96,20 +103,28 @@ public: */ template <typename Arg> stream(Arg&& arg, context& ctx) - : next_layer_(ASIO_MOVE_CAST(Arg)(arg)), + : next_layer_(static_cast<Arg&&>(arg)), core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor()) { } -#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Construct a stream from an existing native implementation. + /** + * This constructor creates a stream and initialises the underlying stream + * object. On success, ownership of the native implementation is transferred + * to the stream, and it will be cleaned up when the stream is destroyed. + * + * @param arg The argument to be passed to initialise the underlying stream. + * + * @param handle An existing native SSL implementation. + */ template <typename Arg> - stream(Arg& arg, context& ctx) - : next_layer_(arg), - core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor()) + stream(Arg&& arg, native_handle_type handle) + : next_layer_(static_cast<Arg&&>(arg)), + core_(handle, next_layer_.lowest_layer().get_executor()) { } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a stream from another. /** * @param other The other stream object from which the move will occur. Must @@ -118,8 +133,8 @@ public: * operation is destruction, or use as the target of a move assignment. */ stream(stream&& other) - : next_layer_(ASIO_MOVE_CAST(Stream)(other.next_layer_)), - core_(ASIO_MOVE_CAST(detail::stream_core)(other.core_)) + : next_layer_(static_cast<Stream&&>(other.next_layer_)), + core_(static_cast<detail::stream_core&&>(other.core_)) { } @@ -134,12 +149,11 @@ public: { if (this != &other) { - next_layer_ = ASIO_MOVE_CAST(Stream)(other.next_layer_); - core_ = ASIO_MOVE_CAST(detail::stream_core)(other.core_); + next_layer_ = static_cast<Stream&&>(other.next_layer_); + core_ = static_cast<detail::stream_core&&>(other.core_); } return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destructor. /** @@ -157,7 +171,7 @@ public: * * @return A copy of the executor that stream will use to dispatch handlers. */ - executor_type get_executor() ASIO_NOEXCEPT + executor_type get_executor() noexcept { return next_layer_.lowest_layer().get_executor(); } @@ -173,7 +187,7 @@ public: * suitable for passing to functions such as @c SSL_get_verify_result and * @c SSL_get_peer_certificate: * @code - * asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx); + * asio::ssl::stream<asio::ip::tcp::socket> sock(io_ctx, ctx); * * // ... establish connection and perform handshake ... * @@ -450,17 +464,27 @@ public: /// Start an asynchronous SSL handshake. /** * This function is used to asynchronously perform an SSL handshake on the - * stream. This function call always returns immediately. + * stream. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param type The type of handshaking to be performed, i.e. as a client or as * a server. * - * @param handler The handler to be called when the handshake operation - * completes. Copies will be made of the handler as required. The equivalent - * function signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the handshake completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a + * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code) @endcode * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following @@ -475,23 +499,24 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) - HandshakeHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(HandshakeHandler, - void (asio::error_code)) - async_handshake(handshake_type type, - ASIO_MOVE_ARG(HandshakeHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return async_initiate<HandshakeHandler, + HandshakeToken = default_completion_token_t<executor_type>> + auto async_handshake(handshake_type type, + HandshakeToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<HandshakeToken, + void (asio::error_code)>( + declval<initiate_async_handshake>(), token, type)) + { + return async_initiate<HandshakeToken, void (asio::error_code)>( - initiate_async_handshake(this), handler, type); + initiate_async_handshake(this), token, type); } /// Start an asynchronous SSL handshake. /** * This function is used to asynchronously perform an SSL handshake on the - * stream. This function call always returns immediately. + * stream. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param type The type of handshaking to be performed, i.e. as a client or as * a server. @@ -499,15 +524,24 @@ public: * @param buffers The buffered data to be reused for the handshake. Although * the buffers object may be copied as necessary, ownership of the underlying * buffers is retained by the caller, which must guarantee that they remain - * valid until the handler is called. + * valid until the completion handler is called. * - * @param handler The handler to be called when the handshake operation - * completes. Copies will be made of the handler as required. The equivalent - * function signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the handshake completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. * std::size_t bytes_transferred // Amount of buffers used in handshake. * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a + * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following @@ -522,17 +556,22 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) BufferedHandshakeHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(BufferedHandshakeHandler, - void (asio::error_code, std::size_t)) - async_handshake(handshake_type type, const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(BufferedHandshakeHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return async_initiate<BufferedHandshakeHandler, + std::size_t)) BufferedHandshakeToken + = default_completion_token_t<executor_type>> + auto async_handshake(handshake_type type, const ConstBufferSequence& buffers, + BufferedHandshakeToken&& token + = default_completion_token_t<executor_type>(), + constraint_t< + is_const_buffer_sequence<ConstBufferSequence>::value + > = 0) + -> decltype( + async_initiate<BufferedHandshakeToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_buffered_handshake>(), token, type, buffers)) + { + return async_initiate<BufferedHandshakeToken, void (asio::error_code, std::size_t)>( - initiate_async_buffered_handshake(this), handler, type, buffers); + initiate_async_buffered_handshake(this), token, type, buffers); } /// Shut down SSL on the stream. @@ -564,15 +603,25 @@ public: /// 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: + * This function is used to asynchronously shut down SSL on the stream. It is + * an initiating function for an @ref asynchronous_operation, and always + * returns immediately. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the shutdown completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a + * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code) @endcode * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following @@ -587,17 +636,18 @@ public: */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) - ShutdownHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ShutdownHandler, - void (asio::error_code)) - async_shutdown( - ASIO_MOVE_ARG(ShutdownHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return async_initiate<ShutdownHandler, + ShutdownToken + = default_completion_token_t<executor_type>> + auto async_shutdown( + ShutdownToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ShutdownToken, + void (asio::error_code)>( + declval<initiate_async_shutdown>(), token)) + { + return async_initiate<ShutdownToken, void (asio::error_code)>( - initiate_async_shutdown(this), handler); + initiate_async_shutdown(this), token); } /// Write some data to the stream. @@ -652,20 +702,30 @@ public: /// Start an asynchronous write. /** * This function is used to asynchronously write one or more bytes of data to - * the stream. The function call always returns immediately. + * the stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param buffers The data to be written to the stream. Although the buffers * object may be copied as necessary, ownership of the underlying buffers is * retained by the caller, which must guarantee that they remain valid until - * the handler is called. + * the completion handler is called. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The equivalent function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. + * std::size_t bytes_transferred // Number of bytes written. * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a + * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode * * @note The async_write_some operation may not transmit all of the data to * the peer. Consider using the @ref async_write function if you need to @@ -685,17 +745,17 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_write_some(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return async_initiate<WriteHandler, + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_write_some(const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_write_some>(), token, buffers)) + { + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_write_some(this), handler, buffers); + initiate_async_write_some(this), token, buffers); } /// Read some data from the stream. @@ -750,20 +810,30 @@ public: /// Start an asynchronous read. /** * This function is used to asynchronously read one or more bytes of data from - * the stream. The function call always returns immediately. + * the stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * * @param buffers The buffers into which the data will be read. Although the * buffers object may be copied as necessary, ownership of the underlying * buffers is retained by the caller, which must guarantee that they remain - * valid until the handler is called. + * valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The equivalent function - * signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. + * std::size_t bytes_transferred // Number of bytes read. * ); @endcode + * Regardless of whether the asynchronous operation completes immediately or + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a + * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode * * @note The async_read_some operation may not read all of the requested * number of bytes. Consider using the @ref async_read function if you need to @@ -783,17 +853,17 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_read_some(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) - { - return async_initiate<ReadHandler, + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_read_some(const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_read_some>(), token, buffers)) + { + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_read_some(this), handler, buffers); + initiate_async_read_some(this), token, buffers); } private: @@ -807,13 +877,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return self_->get_executor(); } template <typename HandshakeHandler> - void operator()(ASIO_MOVE_ARG(HandshakeHandler) handler, + void operator()(HandshakeHandler&& handler, handshake_type type) const { // If you get an error on the following line it means that your handler @@ -839,13 +909,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return self_->get_executor(); } template <typename BufferedHandshakeHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(BufferedHandshakeHandler) handler, + void operator()(BufferedHandshakeHandler&& handler, handshake_type type, const ConstBufferSequence& buffers) const { // If you get an error on the following line it means that your @@ -875,13 +945,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return self_->get_executor(); } template <typename ShutdownHandler> - void operator()(ASIO_MOVE_ARG(ShutdownHandler) handler) const + void operator()(ShutdownHandler&& handler) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a ShutdownHandler. @@ -906,13 +976,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return self_->get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, const ConstBufferSequence& buffers) const { // If you get an error on the following line it means that your handler @@ -938,13 +1008,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + executor_type get_executor() const noexcept { return self_->get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, const MutableBufferSequence& buffers) const { // If you get an error on the following line it means that your handler diff --git a/3rdparty/asio/include/asio/ssl/stream_base.hpp b/3rdparty/asio/include/asio/ssl/stream_base.hpp index 41b7df3c851..2728ec8ca1b 100644 --- a/3rdparty/asio/include/asio/ssl/stream_base.hpp +++ b/3rdparty/asio/include/asio/ssl/stream_base.hpp @@ -2,7 +2,7 @@ // ssl/stream_base.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/verify_context.hpp b/3rdparty/asio/include/asio/ssl/verify_context.hpp index dbfcf1be491..7251856f08e 100644 --- a/3rdparty/asio/include/asio/ssl/verify_context.hpp +++ b/3rdparty/asio/include/asio/ssl/verify_context.hpp @@ -2,7 +2,7 @@ // ssl/verify_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ssl/verify_mode.hpp b/3rdparty/asio/include/asio/ssl/verify_mode.hpp index 241bd65eaca..919e308c8a4 100644 --- a/3rdparty/asio/include/asio/ssl/verify_mode.hpp +++ b/3rdparty/asio/include/asio/ssl/verify_mode.hpp @@ -2,7 +2,7 @@ // ssl/verify_mode.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/static_thread_pool.hpp b/3rdparty/asio/include/asio/static_thread_pool.hpp index 0b611266d9b..636afe1cee5 100644 --- a/3rdparty/asio/include/asio/static_thread_pool.hpp +++ b/3rdparty/asio/include/asio/static_thread_pool.hpp @@ -2,7 +2,7 @@ // static_thread_pool.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/steady_timer.hpp b/3rdparty/asio/include/asio/steady_timer.hpp index 17a72446d92..5db00250b71 100644 --- a/3rdparty/asio/include/asio/steady_timer.hpp +++ b/3rdparty/asio/include/asio/steady_timer.hpp @@ -2,7 +2,7 @@ // steady_timer.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) - #include "asio/basic_waitable_timer.hpp" #include "asio/detail/chrono.hpp" @@ -37,6 +34,4 @@ typedef basic_waitable_timer<chrono::steady_clock> steady_timer; } // namespace asio -#endif // defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) - #endif // ASIO_STEADY_TIMER_HPP diff --git a/3rdparty/asio/include/asio/strand.hpp b/3rdparty/asio/include/asio/strand.hpp index 52b2314df56..c63592b8649 100644 --- a/3rdparty/asio/include/asio/strand.hpp +++ b/3rdparty/asio/include/asio/strand.hpp @@ -2,7 +2,7 @@ // strand.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -48,20 +48,20 @@ public: /// Construct a strand for the specified executor. template <typename Executor1> explicit strand(const Executor1& e, - typename constraint< - conditional< + constraint_t< + conditional_t< !is_same<Executor1, strand>::value, is_convertible<Executor1, Executor>, false_type - >::type::value - >::type = 0) + >::value + > = 0) : executor_(e), impl_(strand::create_implementation(executor_)) { } /// Copy constructor. - strand(const strand& other) ASIO_NOEXCEPT + strand(const strand& other) noexcept : executor_(other.executor_), impl_(other.impl_) { @@ -74,14 +74,14 @@ public: */ template <class OtherExecutor> strand( - const strand<OtherExecutor>& other) ASIO_NOEXCEPT + const strand<OtherExecutor>& other) noexcept : executor_(other.executor_), impl_(other.impl_) { } /// Assignment operator. - strand& operator=(const strand& other) ASIO_NOEXCEPT + strand& operator=(const strand& other) noexcept { executor_ = other.executor_; impl_ = other.impl_; @@ -95,18 +95,17 @@ public: */ template <class OtherExecutor> strand& operator=( - const strand<OtherExecutor>& other) ASIO_NOEXCEPT + const strand<OtherExecutor>& other) noexcept { executor_ = other.executor_; impl_ = other.impl_; return *this; } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. - strand(strand&& other) ASIO_NOEXCEPT - : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)), - impl_(ASIO_MOVE_CAST(implementation_type)(other.impl_)) + strand(strand&& other) noexcept + : executor_(static_cast<Executor&&>(other.executor_)), + impl_(static_cast<implementation_type&&>(other.impl_)) { } @@ -116,17 +115,17 @@ public: * to @c Executor. */ template <class OtherExecutor> - strand(strand<OtherExecutor>&& other) ASIO_NOEXCEPT - : executor_(ASIO_MOVE_CAST(OtherExecutor)(other.executor_)), - impl_(ASIO_MOVE_CAST(implementation_type)(other.impl_)) + strand(strand<OtherExecutor>&& other) noexcept + : executor_(static_cast<OtherExecutor&&>(other.executor_)), + impl_(static_cast<implementation_type&&>(other.impl_)) { } /// Move assignment operator. - strand& operator=(strand&& other) ASIO_NOEXCEPT + strand& operator=(strand&& other) noexcept { - executor_ = ASIO_MOVE_CAST(Executor)(other.executor_); - impl_ = ASIO_MOVE_CAST(implementation_type)(other.impl_); + executor_ = static_cast<Executor&&>(other.executor_); + impl_ = static_cast<implementation_type&&>(other.impl_); return *this; } @@ -136,21 +135,20 @@ public: * convertible to @c Executor. */ template <class OtherExecutor> - strand& operator=(strand<OtherExecutor>&& other) ASIO_NOEXCEPT + strand& operator=(strand<OtherExecutor>&& other) noexcept { - executor_ = ASIO_MOVE_CAST(OtherExecutor)(other.executor_); - impl_ = ASIO_MOVE_CAST(implementation_type)(other.impl_); + executor_ = static_cast<OtherExecutor&&>(other.executor_); + impl_ = static_cast<implementation_type&&>(other.impl_); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destructor. - ~strand() ASIO_NOEXCEPT + ~strand() noexcept { } /// Obtain the underlying executor. - inner_executor_type get_inner_executor() const ASIO_NOEXCEPT + inner_executor_type get_inner_executor() const noexcept { return executor_; } @@ -167,16 +165,15 @@ public: * ... @endcode */ template <typename Property> - typename constraint< + constraint_t< can_query<const Executor&, Property>::value, - typename conditional< + conditional_t< is_convertible<Property, execution::blocking_t>::value, execution::blocking_t, - typename query_result<const Executor&, Property>::type - >::type - >::type query(const Property& p) const - ASIO_NOEXCEPT_IF(( - is_nothrow_query<const Executor&, Property>::value)) + query_result_t<const Executor&, Property> + > + > query(const Property& p) const + noexcept(is_nothrow_query<const Executor&, Property>::value) { return this->query_helper( is_convertible<Property, execution::blocking_t>(), p); @@ -193,19 +190,15 @@ public: * asio::execution::blocking.never); @endcode */ template <typename Property> - typename constraint< + constraint_t< can_require<const Executor&, Property>::value && !is_convertible<Property, execution::blocking_t::always_t>::value, - strand<typename decay< - typename require_result<const Executor&, Property>::type - >::type> - >::type require(const Property& p) const - ASIO_NOEXCEPT_IF(( - is_nothrow_require<const Executor&, Property>::value)) + strand<decay_t<require_result_t<const Executor&, Property>>> + > require(const Property& p) const + noexcept(is_nothrow_require<const Executor&, Property>::value) { - return strand<typename decay< - typename require_result<const Executor&, Property>::type - >::type>(asio::require(executor_, p), impl_); + return strand<decay_t<require_result_t<const Executor&, Property>>>( + asio::require(executor_, p), impl_); } /// Forward a preference to the underlying executor. @@ -219,24 +212,20 @@ public: * asio::execution::blocking.never); @endcode */ template <typename Property> - typename constraint< + constraint_t< can_prefer<const Executor&, Property>::value && !is_convertible<Property, execution::blocking_t::always_t>::value, - strand<typename decay< - typename prefer_result<const Executor&, Property>::type - >::type> - >::type prefer(const Property& p) const - ASIO_NOEXCEPT_IF(( - is_nothrow_prefer<const Executor&, Property>::value)) + strand<decay_t<prefer_result_t<const Executor&, Property>>> + > prefer(const Property& p) const + noexcept(is_nothrow_prefer<const Executor&, Property>::value) { - return strand<typename decay< - typename prefer_result<const Executor&, Property>::type - >::type>(asio::prefer(executor_, p), impl_); + return strand<decay_t<prefer_result_t<const Executor&, Property>>>( + asio::prefer(executor_, p), impl_); } #if !defined(ASIO_NO_TS_EXECUTORS) /// Obtain the underlying execution context. - execution_context& context() const ASIO_NOEXCEPT + execution_context& context() const noexcept { return executor_.context(); } @@ -245,7 +234,7 @@ public: /** * The strand delegates this call to its underlying executor. */ - void on_work_started() const ASIO_NOEXCEPT + void on_work_started() const noexcept { executor_.on_work_started(); } @@ -254,7 +243,7 @@ public: /** * The strand delegates this call to its underlying executor. */ - void on_work_finished() const ASIO_NOEXCEPT + void on_work_finished() const noexcept { executor_.on_work_finished(); } @@ -262,13 +251,6 @@ public: /// Request the strand to invoke the given function object. /** - * Do not call this function directly. It is intended for use with the - * execution::execute customisation point. - * - * For example: - * @code asio::strand<my_executor_type> ex = ...; - * execution::execute(ex, my_function_object); @endcode - * * This function is used to ask the strand to execute the given function * object on its underlying executor. The function object will be executed * according to the properties of the underlying executor. @@ -278,13 +260,13 @@ public: * function object must be: @code void function(); @endcode */ template <typename Function> - typename constraint< - execution::can_execute<const Executor&, Function>::value, + constraint_t< + traits::execute_member<const Executor&, Function>::is_valid, void - >::type execute(ASIO_MOVE_ARG(Function) f) const + > execute(Function&& f) const { detail::strand_executor_service::execute(impl_, - executor_, ASIO_MOVE_CAST(Function)(f)); + executor_, static_cast<Function&&>(f)); } #if !defined(ASIO_NO_TS_EXECUTORS) @@ -304,10 +286,10 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename Allocator> - void dispatch(ASIO_MOVE_ARG(Function) f, const Allocator& a) const + void dispatch(Function&& f, const Allocator& a) const { detail::strand_executor_service::dispatch(impl_, - executor_, ASIO_MOVE_CAST(Function)(f), a); + executor_, static_cast<Function&&>(f), a); } /// Request the strand to invoke the given function object. @@ -324,10 +306,10 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename Allocator> - void post(ASIO_MOVE_ARG(Function) f, const Allocator& a) const + void post(Function&& f, const Allocator& a) const { detail::strand_executor_service::post(impl_, - executor_, ASIO_MOVE_CAST(Function)(f), a); + executor_, static_cast<Function&&>(f), a); } /// Request the strand to invoke the given function object. @@ -344,10 +326,10 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename Allocator> - void defer(ASIO_MOVE_ARG(Function) f, const Allocator& a) const + void defer(Function&& f, const Allocator& a) const { detail::strand_executor_service::defer(impl_, - executor_, ASIO_MOVE_CAST(Function)(f), a); + executor_, static_cast<Function&&>(f), a); } #endif // !defined(ASIO_NO_TS_EXECUTORS) @@ -357,7 +339,7 @@ public: * submitted to the strand using post(), dispatch() or defer(). Otherwise * returns @c false. */ - bool running_in_this_thread() const ASIO_NOEXCEPT + bool running_in_this_thread() const noexcept { return detail::strand_executor_service::running_in_this_thread(impl_); } @@ -367,7 +349,7 @@ public: * Two strands are equal if they refer to the same ordered, non-concurrent * state. */ - friend bool operator==(const strand& a, const strand& b) ASIO_NOEXCEPT + friend bool operator==(const strand& a, const strand& b) noexcept { return a.impl_ == b.impl_; } @@ -377,7 +359,7 @@ public: * Two strands are equal if they refer to the same ordered, non-concurrent * state. */ - friend bool operator!=(const strand& a, const strand& b) ASIO_NOEXCEPT + friend bool operator!=(const strand& a, const strand& b) noexcept { return a.impl_ != b.impl_; } @@ -390,9 +372,9 @@ private: template <typename InnerExecutor> static implementation_type create_implementation(const InnerExecutor& ex, - typename constraint< + constraint_t< can_query<InnerExecutor, execution::context_t>::value - >::type = 0) + > = 0) { return use_service<detail::strand_executor_service>( asio::query(ex, execution::context)).create_implementation(); @@ -400,9 +382,9 @@ private: template <typename InnerExecutor> static implementation_type create_implementation(const InnerExecutor& ex, - typename constraint< + constraint_t< !can_query<InnerExecutor, execution::context_t>::value - >::type = 0) + > = 0) { return use_service<detail::strand_executor_service>( ex.context()).create_implementation(); @@ -415,7 +397,7 @@ private: } template <typename Property> - typename query_result<const Executor&, Property>::type query_helper( + query_result_t<const Executor&, Property> query_helper( false_type, const Property& property) const { return asio::query(executor_, property); @@ -441,22 +423,33 @@ private: /*@{*/ /// Create a @ref strand object for an executor. +/** + * @param ex An executor. + * + * @returns A strand constructed with the specified executor. + */ template <typename Executor> inline strand<Executor> make_strand(const Executor& ex, - typename constraint< + constraint_t< is_executor<Executor>::value || execution::is_executor<Executor>::value - >::type = 0) + > = 0) { return strand<Executor>(ex); } /// Create a @ref strand object for an execution context. +/** + * @param ctx An execution context, from which an executor will be obtained. + * + * @returns A strand constructed with the execution context's executor, obtained + * by performing <tt>ctx.get_executor()</tt>. + */ template <typename ExecutionContext> inline strand<typename ExecutionContext::executor_type> make_strand(ExecutionContext& ctx, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) { return strand<typename ExecutionContext::executor_type>(ctx.get_executor()); } @@ -470,10 +463,10 @@ namespace traits { #if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) template <typename Executor> -struct equality_comparable<strand<Executor> > +struct equality_comparable<strand<Executor>> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; }; #endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) @@ -482,12 +475,12 @@ struct equality_comparable<strand<Executor> > template <typename Executor, typename Function> struct execute_member<strand<Executor>, Function, - typename enable_if< - execution::can_execute<const Executor&, Function>::value - >::type> + enable_if_t< + traits::execute_member<const Executor&, Function>::is_valid + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef void result_type; }; @@ -497,17 +490,16 @@ struct execute_member<strand<Executor>, Function, template <typename Executor, typename Property> struct query_member<strand<Executor>, Property, - typename enable_if< + enable_if_t< can_query<const Executor&, Property>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_query<Executor, Property>::value)); - typedef typename conditional< + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_query<Executor, Property>::value; + typedef conditional_t< is_convertible<Property, execution::blocking_t>::value, - execution::blocking_t, typename query_result<Executor, Property>::type - >::type result_type; + execution::blocking_t, query_result_t<Executor, Property>> result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) @@ -516,17 +508,15 @@ struct query_member<strand<Executor>, Property, template <typename Executor, typename Property> struct require_member<strand<Executor>, Property, - typename enable_if< + enable_if_t< can_require<const Executor&, Property>::value && !is_convertible<Property, execution::blocking_t::always_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_require<Executor, Property>::value)); - typedef strand<typename decay< - typename require_result<Executor, Property>::type - >::type> result_type; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_require<Executor, Property>::value; + typedef strand<decay_t<require_result_t<Executor, Property>>> result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) @@ -535,17 +525,15 @@ struct require_member<strand<Executor>, Property, template <typename Executor, typename Property> struct prefer_member<strand<Executor>, Property, - typename enable_if< + enable_if_t< can_prefer<const Executor&, Property>::value && !is_convertible<Property, execution::blocking_t::always_t>::value - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - (is_nothrow_prefer<Executor, Property>::value)); - typedef strand<typename decay< - typename prefer_result<Executor, Property>::type - >::type> result_type; + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = + is_nothrow_prefer<Executor, Property>::value; + typedef strand<decay_t<prefer_result_t<Executor, Property>>> result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) diff --git a/3rdparty/asio/include/asio/stream_file.hpp b/3rdparty/asio/include/asio/stream_file.hpp new file mode 100644 index 00000000000..ef059a987e5 --- /dev/null +++ b/3rdparty/asio/include/asio/stream_file.hpp @@ -0,0 +1,35 @@ +// +// stream_file.hpp +// ~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_STREAM_FILE_HPP +#define ASIO_STREAM_FILE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_FILE) \ + || defined(GENERATING_DOCUMENTATION) + +#include "asio/basic_stream_file.hpp" + +namespace asio { + +/// Typedef for the typical usage of a stream-oriented file. +typedef basic_stream_file<> stream_file; + +} // namespace asio + +#endif // defined(ASIO_HAS_FILE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_STREAM_FILE_HPP diff --git a/3rdparty/asio/include/asio/streambuf.hpp b/3rdparty/asio/include/asio/streambuf.hpp index 4b7995e5480..d7745245cb8 100644 --- a/3rdparty/asio/include/asio/streambuf.hpp +++ b/3rdparty/asio/include/asio/streambuf.hpp @@ -2,7 +2,7 @@ // streambuf.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/system_context.hpp b/3rdparty/asio/include/asio/system_context.hpp index 6611ab7ee08..132ce615677 100644 --- a/3rdparty/asio/include/asio/system_context.hpp +++ b/3rdparty/asio/include/asio/system_context.hpp @@ -2,7 +2,7 @@ // system_context.hpp // ~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -43,13 +43,13 @@ public: ASIO_DECL ~system_context(); /// Obtain an executor for the context. - executor_type get_executor() ASIO_NOEXCEPT; + executor_type get_executor() noexcept; /// Signal all threads in the system thread pool to stop. ASIO_DECL void stop(); /// Determine whether the system thread pool has been stopped. - ASIO_DECL bool stopped() const ASIO_NOEXCEPT; + ASIO_DECL bool stopped() const noexcept; /// Join all threads in the system thread pool. ASIO_DECL void join(); diff --git a/3rdparty/asio/include/asio/system_error.hpp b/3rdparty/asio/include/asio/system_error.hpp index 3fb2d14db20..d7f932627bd 100644 --- a/3rdparty/asio/include/asio/system_error.hpp +++ b/3rdparty/asio/include/asio/system_error.hpp @@ -2,7 +2,7 @@ // system_error.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,114 +16,14 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_STD_SYSTEM_ERROR) -# include <system_error> -#else // defined(ASIO_HAS_STD_SYSTEM_ERROR) -# include <cerrno> -# include <exception> -# include <string> -# include "asio/error_code.hpp" -# include "asio/detail/scoped_ptr.hpp" -#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR) +#include <system_error> #include "asio/detail/push_options.hpp" namespace asio { -#if defined(ASIO_HAS_STD_SYSTEM_ERROR) - typedef std::system_error system_error; -#else // defined(ASIO_HAS_STD_SYSTEM_ERROR) - -/// The system_error class is used to represent system conditions that -/// prevent the library from operating correctly. -class system_error - : public std::exception -{ -public: - /// Construct with an error code. - system_error(const error_code& ec) - : code_(ec), - context_() - { - } - - /// Construct with an error code and context. - system_error(const error_code& ec, const std::string& context) - : code_(ec), - context_(context) - { - } - - /// Copy constructor. - system_error(const system_error& other) - : std::exception(other), - code_(other.code_), - context_(other.context_), - what_() - { - } - - /// Destructor. - virtual ~system_error() throw () - { - } - - /// Assignment operator. - system_error& operator=(const system_error& e) - { - context_ = e.context_; - code_ = e.code_; - what_.reset(); - return *this; - } - - /// Get a string representation of the exception. - virtual const char* what() const throw () - { -#if !defined(ASIO_NO_EXCEPTIONS) - try -#endif // !defined(ASIO_NO_EXCEPTIONS) - { - if (!what_.get()) - { - std::string tmp(context_); - if (tmp.length()) - tmp += ": "; - tmp += code_.message(); - what_.reset(new std::string(tmp)); - } - return what_->c_str(); - } -#if !defined(ASIO_NO_EXCEPTIONS) - catch (std::exception&) - { - return "system_error"; - } -#endif // !defined(ASIO_NO_EXCEPTIONS) - } - - /// Get the error code associated with the exception. - error_code code() const - { - return code_; - } - -private: - // The code associated with the error. - error_code code_; - - // The context associated with the error. - std::string context_; - - // The string representation of the error. - mutable asio::detail::scoped_ptr<std::string> what_; -}; - -#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR) - } // namespace asio #include "asio/detail/pop_options.hpp" diff --git a/3rdparty/asio/include/asio/system_executor.hpp b/3rdparty/asio/include/asio/system_executor.hpp index 84025f0d519..19b6d30e322 100644 --- a/3rdparty/asio/include/asio/system_executor.hpp +++ b/3rdparty/asio/include/asio/system_executor.hpp @@ -2,7 +2,7 @@ // system_executor.hpp // ~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -39,7 +39,7 @@ class basic_system_executor { public: /// Default constructor. - basic_system_executor() ASIO_NOEXCEPT + basic_system_executor() noexcept : allocator_(Allocator()) { } @@ -168,11 +168,11 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::allocator); @endcode */ - basic_system_executor<Blocking, Relationship, std::allocator<void> > + basic_system_executor<Blocking, Relationship, std::allocator<void>> require(execution::allocator_t<void>) const { return basic_system_executor<Blocking, - Relationship, std::allocator<void> >(); + Relationship, std::allocator<void>>(); } #if !defined(GENERATING_DOCUMENTATION) @@ -195,8 +195,8 @@ private: * == asio::execution::mapping.thread) * ... @endcode */ - static ASIO_CONSTEXPR execution::mapping_t query( - execution::mapping_t) ASIO_NOEXCEPT + static constexpr execution::mapping_t query( + execution::mapping_t) noexcept { return execution::mapping.thread; } @@ -211,7 +211,7 @@ private: * asio::system_context& pool = asio::query( * ex, asio::execution::context); @endcode */ - static system_context& query(execution::context_t) ASIO_NOEXCEPT; + static system_context& query(execution::context_t) noexcept; /// Query the current value of the @c blocking property. /** @@ -224,8 +224,8 @@ private: * == asio::execution::blocking.always) * ... @endcode */ - static ASIO_CONSTEXPR execution::blocking_t query( - execution::blocking_t) ASIO_NOEXCEPT + static constexpr execution::blocking_t query( + execution::blocking_t) noexcept { return Blocking(); } @@ -241,8 +241,8 @@ private: * == asio::execution::relationship.continuation) * ... @endcode */ - static ASIO_CONSTEXPR execution::relationship_t query( - execution::relationship_t) ASIO_NOEXCEPT + static constexpr execution::relationship_t query( + execution::relationship_t) noexcept { return Relationship(); } @@ -258,8 +258,8 @@ private: * asio::execution::allocator); @endcode */ template <typename OtherAllocator> - ASIO_CONSTEXPR Allocator query( - execution::allocator_t<OtherAllocator>) const ASIO_NOEXCEPT + constexpr Allocator query( + execution::allocator_t<OtherAllocator>) const noexcept { return allocator_; } @@ -274,8 +274,8 @@ private: * auto alloc = asio::query(ex, * asio::execution::allocator); @endcode */ - ASIO_CONSTEXPR Allocator query( - execution::allocator_t<void>) const ASIO_NOEXCEPT + constexpr Allocator query( + execution::allocator_t<void>) const noexcept { return allocator_; } @@ -291,7 +291,7 @@ private: * std::size_t occupancy = asio::query( * ex, asio::execution::occupancy); @endcode */ - std::size_t query(execution::occupancy_t) const ASIO_NOEXCEPT; + std::size_t query(execution::occupancy_t) const noexcept; public: /// Compare two executors for equality. @@ -299,7 +299,7 @@ public: * Two executors are equal if they refer to the same underlying io_context. */ friend bool operator==(const basic_system_executor&, - const basic_system_executor&) ASIO_NOEXCEPT + const basic_system_executor&) noexcept { return true; } @@ -309,41 +309,28 @@ public: * Two executors are equal if they refer to the same underlying io_context. */ friend bool operator!=(const basic_system_executor&, - const basic_system_executor&) ASIO_NOEXCEPT + const basic_system_executor&) noexcept { return false; } -#if !defined(GENERATING_DOCUMENTATION) -private: - friend struct asio_execution_execute_fn::impl; -#endif // !defined(GENERATING_DOCUMENTATION) - /// Execution function. - /** - * Do not call this function directly. It is intended for use with the - * execution::execute customisation point. - * - * For example: - * @code asio::system_executor ex; - * execution::execute(ex, my_function_object); @endcode - */ template <typename Function> - void execute(ASIO_MOVE_ARG(Function) f) const + void execute(Function&& f) const { - this->do_execute(ASIO_MOVE_CAST(Function)(f), Blocking()); + this->do_execute(static_cast<Function&&>(f), Blocking()); } #if !defined(ASIO_NO_TS_EXECUTORS) public: /// Obtain the underlying execution context. - system_context& context() const ASIO_NOEXCEPT; + system_context& context() const 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 ASIO_NOEXCEPT + void on_work_started() const noexcept { } @@ -351,7 +338,7 @@ public: /** * For the system executor, this is a no-op. */ - void on_work_finished() const ASIO_NOEXCEPT + void on_work_finished() const noexcept { } @@ -368,7 +355,7 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename OtherAllocator> - void dispatch(ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const; + void dispatch(Function&& f, const OtherAllocator& a) const; /// Request the system executor to invoke the given function object. /** @@ -384,7 +371,7 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename OtherAllocator> - void post(ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const; + void post(Function&& f, const OtherAllocator& a) const; /// Request the system executor to invoke the given function object. /** @@ -400,7 +387,7 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename OtherAllocator> - void defer(ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const; + void defer(Function&& f, const OtherAllocator& a) const; #endif // !defined(ASIO_NO_TS_EXECUTORS) private: @@ -414,17 +401,17 @@ private: /// Execution helper implementation for the possibly blocking property. template <typename Function> - void do_execute(ASIO_MOVE_ARG(Function) f, + void do_execute(Function&& f, execution::blocking_t::possibly_t) const; /// Execution helper implementation for the always blocking property. template <typename Function> - void do_execute(ASIO_MOVE_ARG(Function) f, + void do_execute(Function&& f, execution::blocking_t::always_t) const; /// Execution helper implementation for the never blocking property. template <typename Function> - void do_execute(ASIO_MOVE_ARG(Function) f, + void do_execute(Function&& f, execution::blocking_t::never_t) const; // The allocator used for execution functions. @@ -441,7 +428,7 @@ private: * immediately. */ typedef basic_system_executor<execution::blocking_t::possibly_t, - execution::relationship_t::fork_t, std::allocator<void> > + execution::relationship_t::fork_t, std::allocator<void>> system_executor; #if !defined(GENERATING_DOCUMENTATION) @@ -455,8 +442,8 @@ struct equality_comparable< asio::basic_system_executor<Blocking, Relationship, Allocator> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; }; #endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) @@ -470,8 +457,8 @@ struct execute_member< Function > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef void result_type; }; @@ -485,8 +472,8 @@ struct require_member< asio::execution::blocking_t::possibly_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::basic_system_executor< asio::execution::blocking_t::possibly_t, Relationship, Allocator> result_type; @@ -498,8 +485,8 @@ struct require_member< asio::execution::blocking_t::always_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::basic_system_executor< asio::execution::blocking_t::always_t, Relationship, Allocator> result_type; @@ -511,8 +498,8 @@ struct require_member< asio::execution::blocking_t::never_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::basic_system_executor< asio::execution::blocking_t::never_t, Relationship, Allocator> result_type; @@ -524,8 +511,8 @@ struct require_member< asio::execution::relationship_t::fork_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::basic_system_executor<Blocking, asio::execution::relationship_t::fork_t, Allocator> result_type; @@ -537,8 +524,8 @@ struct require_member< asio::execution::relationship_t::continuation_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::basic_system_executor<Blocking, asio::execution::relationship_t::continuation_t, Allocator> result_type; @@ -550,10 +537,10 @@ struct require_member< asio::execution::allocator_t<void> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::basic_system_executor<Blocking, - Relationship, std::allocator<void> > result_type; + Relationship, std::allocator<void>> result_type; }; template <typename Blocking, typename Relationship, @@ -563,8 +550,8 @@ struct require_member< asio::execution::allocator_t<OtherAllocator> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::basic_system_executor<Blocking, Relationship, OtherAllocator> result_type; }; @@ -586,11 +573,11 @@ struct query_static_constexpr_member< >::type > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::execution::mapping_t::thread_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return result_type(); } @@ -613,8 +600,8 @@ struct query_member< >::type > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::execution::blocking_t result_type; }; @@ -631,8 +618,8 @@ struct query_member< >::type > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::execution::relationship_t result_type; }; @@ -642,8 +629,8 @@ struct query_member< asio::execution::context_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::system_context& result_type; }; @@ -653,8 +640,8 @@ struct query_member< asio::execution::allocator_t<void> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef Allocator result_type; }; @@ -664,8 +651,8 @@ struct query_member< asio::execution::allocator_t<Allocator> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef Allocator result_type; }; diff --git a/3rdparty/asio/include/asio/system_timer.hpp b/3rdparty/asio/include/asio/system_timer.hpp index 75425ebad55..7b5e768032f 100644 --- a/3rdparty/asio/include/asio/system_timer.hpp +++ b/3rdparty/asio/include/asio/system_timer.hpp @@ -2,7 +2,7 @@ // system_timer.hpp // ~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,9 +16,6 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) - #include "asio/basic_waitable_timer.hpp" #include "asio/detail/chrono.hpp" @@ -37,6 +34,4 @@ typedef basic_waitable_timer<chrono::system_clock> system_timer; } // namespace asio -#endif // defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION) - #endif // ASIO_SYSTEM_TIMER_HPP diff --git a/3rdparty/asio/include/asio/this_coro.hpp b/3rdparty/asio/include/asio/this_coro.hpp index 6db27174649..37381b92abf 100644 --- a/3rdparty/asio/include/asio/this_coro.hpp +++ b/3rdparty/asio/include/asio/this_coro.hpp @@ -2,7 +2,7 @@ // this_coro.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -26,22 +26,18 @@ namespace this_coro { /// Awaitable type that returns the executor of the current coroutine. struct executor_t { - ASIO_CONSTEXPR executor_t() + constexpr executor_t() { } }; /// Awaitable object that returns the executor of the current coroutine. -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr executor_t executor; -#elif defined(ASIO_MSVC) -__declspec(selectany) executor_t executor; -#endif /// Awaitable type that returns the cancellation state of the current coroutine. struct cancellation_state_t { - ASIO_CONSTEXPR cancellation_state_t() + constexpr cancellation_state_t() { } }; @@ -61,11 +57,7 @@ struct cancellation_state_t * // ... * } @endcode */ -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr cancellation_state_t cancellation_state; -#elif defined(ASIO_MSVC) -__declspec(selectany) cancellation_state_t cancellation_state; -#endif #if defined(GENERATING_DOCUMENTATION) @@ -73,7 +65,7 @@ __declspec(selectany) cancellation_state_t cancellation_state; /// of the current coroutine. /** * Let <tt>P</tt> be the cancellation slot associated with the current - * coroutine's `co_spawn` completion handler. Assigns a new + * coroutine's @ref co_spawn completion handler. Assigns a new * asio::cancellation_state object <tt>S</tt>, constructed as * <tt>S(P)</tt>, into the current coroutine's cancellation state object. * @@ -88,14 +80,14 @@ __declspec(selectany) cancellation_state_t cancellation_state; * @note The cancellation state is shared by all coroutines in the same "thread * of execution" that was created using asio::co_spawn. */ -ASIO_NODISCARD ASIO_CONSTEXPR unspecified +ASIO_NODISCARD constexpr unspecified reset_cancellation_state(); /// Returns an awaitable object that may be used to reset the cancellation state /// of the current coroutine. /** * Let <tt>P</tt> be the cancellation slot associated with the current - * coroutine's `co_spawn` completion handler. Assigns a new + * coroutine's @ref co_spawn completion handler. Assigns a new * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P, * std::forward<Filter>(filter))</tt>, into the current coroutine's * cancellation state object. @@ -113,14 +105,14 @@ reset_cancellation_state(); * of execution" that was created using asio::co_spawn. */ template <typename Filter> -ASIO_NODISCARD ASIO_CONSTEXPR unspecified -reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter); +ASIO_NODISCARD constexpr unspecified +reset_cancellation_state(Filter&& filter); /// Returns an awaitable object that may be used to reset the cancellation state /// of the current coroutine. /** * Let <tt>P</tt> be the cancellation slot associated with the current - * coroutine's `co_spawn` completion handler. Assigns a new + * coroutine's @ref co_spawn completion handler. Assigns a new * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P, * std::forward<InFilter>(in_filter), * std::forward<OutFilter>(out_filter))</tt>, into the current coroutine's @@ -140,10 +132,10 @@ reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter); * of execution" that was created using asio::co_spawn. */ template <typename InFilter, typename OutFilter> -ASIO_NODISCARD ASIO_CONSTEXPR unspecified +ASIO_NODISCARD constexpr unspecified reset_cancellation_state( - ASIO_MOVE_ARG(InFilter) in_filter, - ASIO_MOVE_ARG(OutFilter) out_filter); + InFilter&& in_filter, + OutFilter&& out_filter); /// Returns an awaitable object that may be used to determine whether the /// coroutine throws if trying to suspend when it has been cancelled. @@ -157,7 +149,7 @@ reset_cancellation_state( * // ... * } @endcode */ -ASIO_NODISCARD ASIO_CONSTEXPR unspecified +ASIO_NODISCARD constexpr unspecified throw_if_cancelled(); /// Returns an awaitable object that may be used to specify whether the @@ -171,19 +163,19 @@ throw_if_cancelled(); * // ... * } @endcode */ -ASIO_NODISCARD ASIO_CONSTEXPR unspecified +ASIO_NODISCARD constexpr unspecified throw_if_cancelled(bool value); #else // defined(GENERATING_DOCUMENTATION) struct reset_cancellation_state_0_t { - ASIO_CONSTEXPR reset_cancellation_state_0_t() + constexpr reset_cancellation_state_0_t() { } }; -ASIO_NODISCARD inline ASIO_CONSTEXPR reset_cancellation_state_0_t +ASIO_NODISCARD inline constexpr reset_cancellation_state_0_t reset_cancellation_state() { return reset_cancellation_state_0_t(); @@ -193,9 +185,9 @@ template <typename Filter> struct reset_cancellation_state_1_t { template <typename F> - ASIO_CONSTEXPR reset_cancellation_state_1_t( - ASIO_MOVE_ARG(F) filter) - : filter(ASIO_MOVE_CAST(F)(filter)) + explicit constexpr reset_cancellation_state_1_t( + F&& filt) + : filter(static_cast<F&&>(filt)) { } @@ -203,22 +195,22 @@ struct reset_cancellation_state_1_t }; template <typename Filter> -ASIO_NODISCARD inline ASIO_CONSTEXPR reset_cancellation_state_1_t< - typename decay<Filter>::type> -reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter) +ASIO_NODISCARD inline constexpr reset_cancellation_state_1_t< + decay_t<Filter>> +reset_cancellation_state(Filter&& filter) { - return reset_cancellation_state_1_t<typename decay<Filter>::type>( - ASIO_MOVE_CAST(Filter)(filter)); + return reset_cancellation_state_1_t<decay_t<Filter>>( + static_cast<Filter&&>(filter)); } template <typename InFilter, typename OutFilter> struct reset_cancellation_state_2_t { template <typename F1, typename F2> - ASIO_CONSTEXPR reset_cancellation_state_2_t( - ASIO_MOVE_ARG(F1) in_filter, ASIO_MOVE_ARG(F2) out_filter) - : in_filter(ASIO_MOVE_CAST(F1)(in_filter)), - out_filter(ASIO_MOVE_CAST(F2)(out_filter)) + constexpr reset_cancellation_state_2_t( + F1&& in_filt, F2&& out_filt) + : in_filter(static_cast<F1&&>(in_filt)), + out_filter(static_cast<F2&&>(out_filt)) { } @@ -227,28 +219,23 @@ struct reset_cancellation_state_2_t }; template <typename InFilter, typename OutFilter> -ASIO_NODISCARD inline ASIO_CONSTEXPR reset_cancellation_state_2_t< - typename decay<InFilter>::type, - typename decay<OutFilter>::type> -reset_cancellation_state( - ASIO_MOVE_ARG(InFilter) in_filter, - ASIO_MOVE_ARG(OutFilter) out_filter) +ASIO_NODISCARD inline constexpr +reset_cancellation_state_2_t<decay_t<InFilter>, decay_t<OutFilter>> +reset_cancellation_state(InFilter&& in_filter, OutFilter&& out_filter) { - return reset_cancellation_state_2_t< - typename decay<InFilter>::type, - typename decay<OutFilter>::type>( - ASIO_MOVE_CAST(InFilter)(in_filter), - ASIO_MOVE_CAST(OutFilter)(out_filter)); + return reset_cancellation_state_2_t<decay_t<InFilter>, decay_t<OutFilter>>( + static_cast<InFilter&&>(in_filter), + static_cast<OutFilter&&>(out_filter)); } struct throw_if_cancelled_0_t { - ASIO_CONSTEXPR throw_if_cancelled_0_t() + constexpr throw_if_cancelled_0_t() { } }; -ASIO_NODISCARD inline ASIO_CONSTEXPR throw_if_cancelled_0_t +ASIO_NODISCARD inline constexpr throw_if_cancelled_0_t throw_if_cancelled() { return throw_if_cancelled_0_t(); @@ -256,15 +243,15 @@ throw_if_cancelled() struct throw_if_cancelled_1_t { - ASIO_CONSTEXPR throw_if_cancelled_1_t(bool value) - : value(value) + explicit constexpr throw_if_cancelled_1_t(bool val) + : value(val) { } bool value; }; -ASIO_NODISCARD inline ASIO_CONSTEXPR throw_if_cancelled_1_t +ASIO_NODISCARD inline constexpr throw_if_cancelled_1_t throw_if_cancelled(bool value) { return throw_if_cancelled_1_t(value); diff --git a/3rdparty/asio/include/asio/thread.hpp b/3rdparty/asio/include/asio/thread.hpp index d15c8ad5e5d..fc57bffdd9e 100644 --- a/3rdparty/asio/include/asio/thread.hpp +++ b/3rdparty/asio/include/asio/thread.hpp @@ -2,7 +2,7 @@ // thread.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/thread_pool.hpp b/3rdparty/asio/include/asio/thread_pool.hpp index f8fae0175ea..f9095d9441a 100644 --- a/3rdparty/asio/include/asio/thread_pool.hpp +++ b/3rdparty/asio/include/asio/thread_pool.hpp @@ -2,7 +2,7 @@ // thread_pool.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -28,11 +28,11 @@ namespace asio { namespace detail { struct thread_pool_bits { - ASIO_STATIC_CONSTEXPR(unsigned int, blocking_never = 1); - ASIO_STATIC_CONSTEXPR(unsigned int, blocking_always = 2); - ASIO_STATIC_CONSTEXPR(unsigned int, blocking_mask = 3); - ASIO_STATIC_CONSTEXPR(unsigned int, relationship_continuation = 4); - ASIO_STATIC_CONSTEXPR(unsigned int, outstanding_work_tracked = 8); + static constexpr unsigned int blocking_never = 1; + static constexpr unsigned int blocking_always = 2; + static constexpr unsigned int blocking_mask = 3; + static constexpr unsigned int relationship_continuation = 4; + static constexpr unsigned int outstanding_work_tracked = 8; }; } // namespace detail @@ -84,9 +84,6 @@ public: /// Executor used to submit functions to a thread pool. typedef basic_executor_type<std::allocator<void>, 0> executor_type; - /// Scheduler used to schedule receivers on a thread pool. - typedef basic_executor_type<std::allocator<void>, 0> scheduler_type; - #if !defined(ASIO_NO_TS_EXECUTORS) /// Constructs a pool with an automatically determined number of threads. ASIO_DECL thread_pool(); @@ -102,13 +99,10 @@ public: ASIO_DECL ~thread_pool(); /// Obtains the executor associated with the pool. - executor_type get_executor() ASIO_NOEXCEPT; + executor_type get_executor() noexcept; /// Obtains the executor associated with the pool. - executor_type executor() ASIO_NOEXCEPT; - - /// Obtains the scheduler associated with the pool. - scheduler_type scheduler() ASIO_NOEXCEPT; + executor_type executor() noexcept; /// Stops the threads. /** @@ -142,8 +136,8 @@ public: ASIO_DECL void wait(); private: - thread_pool(const thread_pool&) ASIO_DELETED; - thread_pool& operator=(const thread_pool&) ASIO_DELETED; + thread_pool(const thread_pool&) = delete; + thread_pool& operator=(const thread_pool&) = delete; struct thread_function; @@ -165,32 +159,8 @@ template <typename Allocator, unsigned int Bits> class thread_pool::basic_executor_type : detail::thread_pool_bits { public: - /// The sender type, when this type is used as a scheduler. - typedef basic_executor_type sender_type; - - /// The bulk execution shape type. - typedef std::size_t shape_type; - - /// The bulk execution index type. - typedef std::size_t index_type; - -#if defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) \ - && defined(ASIO_HAS_STD_EXCEPTION_PTR) - template < - template <typename...> class Tuple, - template <typename...> class Variant> - using value_types = Variant<Tuple<>>; - - template <template <typename...> class Variant> - using error_types = Variant<std::exception_ptr>; - - ASIO_STATIC_CONSTEXPR(bool, sends_done = true); -#endif // defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) - // && defined(ASIO_HAS_STD_EXCEPTION_PTR) - /// Copy constructor. - basic_executor_type( - const basic_executor_type& other) ASIO_NOEXCEPT + basic_executor_type(const basic_executor_type& other) noexcept : pool_(other.pool_), allocator_(other.allocator_), bits_(other.bits_) @@ -200,20 +170,18 @@ public: pool_->scheduler_.work_started(); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move constructor. - basic_executor_type(basic_executor_type&& other) ASIO_NOEXCEPT + basic_executor_type(basic_executor_type&& other) noexcept : pool_(other.pool_), - allocator_(ASIO_MOVE_CAST(Allocator)(other.allocator_)), + allocator_(static_cast<Allocator&&>(other.allocator_)), bits_(other.bits_) { if (Bits & outstanding_work_tracked) other.pool_ = 0; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Destructor. - ~basic_executor_type() ASIO_NOEXCEPT + ~basic_executor_type() noexcept { if (Bits & outstanding_work_tracked) if (pool_) @@ -221,14 +189,10 @@ public: } /// Assignment operator. - basic_executor_type& operator=( - const basic_executor_type& other) ASIO_NOEXCEPT; + basic_executor_type& operator=(const basic_executor_type& other) noexcept; -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move assignment operator. - basic_executor_type& operator=( - basic_executor_type&& other) ASIO_NOEXCEPT; -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + basic_executor_type& operator=(basic_executor_type&& other) noexcept; #if !defined(GENERATING_DOCUMENTATION) private: @@ -246,7 +210,7 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::blocking.possibly); @endcode */ - ASIO_CONSTEXPR basic_executor_type<Allocator, + constexpr basic_executor_type<Allocator, ASIO_UNSPECIFIED(Bits & ~blocking_mask)> require(execution::blocking_t::possibly_t) const { @@ -264,7 +228,7 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::blocking.always); @endcode */ - ASIO_CONSTEXPR basic_executor_type<Allocator, + constexpr basic_executor_type<Allocator, ASIO_UNSPECIFIED((Bits & ~blocking_mask) | blocking_always)> require(execution::blocking_t::always_t) const { @@ -283,7 +247,7 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::blocking.never); @endcode */ - ASIO_CONSTEXPR basic_executor_type<Allocator, + constexpr basic_executor_type<Allocator, ASIO_UNSPECIFIED(Bits & ~blocking_mask)> require(execution::blocking_t::never_t) const { @@ -301,8 +265,7 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::relationship.fork); @endcode */ - ASIO_CONSTEXPR basic_executor_type require( - execution::relationship_t::fork_t) const + constexpr basic_executor_type require(execution::relationship_t::fork_t) const { return basic_executor_type(pool_, allocator_, bits_ & ~relationship_continuation); @@ -318,7 +281,7 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::relationship.continuation); @endcode */ - ASIO_CONSTEXPR basic_executor_type require( + constexpr basic_executor_type require( execution::relationship_t::continuation_t) const { return basic_executor_type(pool_, @@ -335,7 +298,7 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::outstanding_work.tracked); @endcode */ - ASIO_CONSTEXPR basic_executor_type<Allocator, + constexpr basic_executor_type<Allocator, ASIO_UNSPECIFIED(Bits | outstanding_work_tracked)> require(execution::outstanding_work_t::tracked_t) const { @@ -353,7 +316,7 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::outstanding_work.untracked); @endcode */ - ASIO_CONSTEXPR basic_executor_type<Allocator, + constexpr basic_executor_type<Allocator, ASIO_UNSPECIFIED(Bits & ~outstanding_work_tracked)> require(execution::outstanding_work_t::untracked_t) const { @@ -372,7 +335,7 @@ private: * asio::execution::allocator(my_allocator)); @endcode */ template <typename OtherAllocator> - ASIO_CONSTEXPR basic_executor_type<OtherAllocator, Bits> + constexpr basic_executor_type<OtherAllocator, Bits> require(execution::allocator_t<OtherAllocator> a) const { return basic_executor_type<OtherAllocator, Bits>( @@ -389,7 +352,7 @@ private: * auto ex2 = asio::require(ex1, * asio::execution::allocator); @endcode */ - ASIO_CONSTEXPR basic_executor_type<std::allocator<void>, Bits> + constexpr basic_executor_type<std::allocator<void>, Bits> require(execution::allocator_t<void>) const { return basic_executor_type<std::allocator<void>, Bits>( @@ -403,23 +366,6 @@ private: friend struct asio::execution::detail::outstanding_work_t<0>; #endif // !defined(GENERATING_DOCUMENTATION) - /// Query the current value of the @c bulk_guarantee property. - /** - * Do not call this function directly. It is intended for use with the - * asio::query customisation point. - * - * For example: - * @code auto ex = my_thread_pool.executor(); - * if (asio::query(ex, asio::execution::bulk_guarantee) - * == asio::execution::bulk_guarantee.parallel) - * ... @endcode - */ - static ASIO_CONSTEXPR execution::bulk_guarantee_t query( - execution::bulk_guarantee_t) ASIO_NOEXCEPT - { - return execution::bulk_guarantee.parallel; - } - /// Query the current value of the @c mapping property. /** * Do not call this function directly. It is intended for use with the @@ -431,8 +377,7 @@ private: * == asio::execution::mapping.thread) * ... @endcode */ - static ASIO_CONSTEXPR execution::mapping_t query( - execution::mapping_t) ASIO_NOEXCEPT + static constexpr execution::mapping_t query(execution::mapping_t) noexcept { return execution::mapping.thread; } @@ -447,7 +392,7 @@ private: * asio::thread_pool& pool = asio::query( * ex, asio::execution::context); @endcode */ - thread_pool& query(execution::context_t) const ASIO_NOEXCEPT + thread_pool& query(execution::context_t) const noexcept { return *pool_; } @@ -463,8 +408,7 @@ private: * == asio::execution::blocking.always) * ... @endcode */ - ASIO_CONSTEXPR execution::blocking_t query( - execution::blocking_t) const ASIO_NOEXCEPT + constexpr execution::blocking_t query(execution::blocking_t) const noexcept { return (bits_ & blocking_never) ? execution::blocking_t(execution::blocking.never) @@ -484,8 +428,8 @@ private: * == asio::execution::relationship.continuation) * ... @endcode */ - ASIO_CONSTEXPR execution::relationship_t query( - execution::relationship_t) const ASIO_NOEXCEPT + constexpr execution::relationship_t query( + execution::relationship_t) const noexcept { return (bits_ & relationship_continuation) ? execution::relationship_t(execution::relationship.continuation) @@ -503,8 +447,8 @@ private: * == asio::execution::outstanding_work.tracked) * ... @endcode */ - static ASIO_CONSTEXPR execution::outstanding_work_t query( - execution::outstanding_work_t) ASIO_NOEXCEPT + static constexpr execution::outstanding_work_t query( + execution::outstanding_work_t) noexcept { return (Bits & outstanding_work_tracked) ? execution::outstanding_work_t(execution::outstanding_work.tracked) @@ -522,8 +466,8 @@ private: * asio::execution::allocator); @endcode */ template <typename OtherAllocator> - ASIO_CONSTEXPR Allocator query( - execution::allocator_t<OtherAllocator>) const ASIO_NOEXCEPT + constexpr Allocator query( + execution::allocator_t<OtherAllocator>) const noexcept { return allocator_; } @@ -538,8 +482,7 @@ private: * auto alloc = asio::query(ex, * asio::execution::allocator); @endcode */ - ASIO_CONSTEXPR Allocator query( - execution::allocator_t<void>) const ASIO_NOEXCEPT + constexpr Allocator query(execution::allocator_t<void>) const noexcept { return allocator_; } @@ -554,7 +497,7 @@ private: * std::size_t occupancy = asio::query( * ex, asio::execution::occupancy); @endcode */ - std::size_t query(execution::occupancy_t) const ASIO_NOEXCEPT + std::size_t query(execution::occupancy_t) const noexcept { return static_cast<std::size_t>(pool_->num_threads_); } @@ -565,14 +508,14 @@ public: * @return @c true if the current thread is running the thread pool. Otherwise * returns @c false. */ - bool running_in_this_thread() const ASIO_NOEXCEPT; + bool running_in_this_thread() const noexcept; /// Compare two executors for equality. /** * Two executors are equal if they refer to the same underlying thread pool. */ friend bool operator==(const basic_executor_type& a, - const basic_executor_type& b) ASIO_NOEXCEPT + const basic_executor_type& b) noexcept { return a.pool_ == b.pool_ && a.allocator_ == b.allocator_ @@ -584,78 +527,25 @@ public: * Two executors are equal if they refer to the same underlying thread pool. */ friend bool operator!=(const basic_executor_type& a, - const basic_executor_type& b) ASIO_NOEXCEPT + const basic_executor_type& b) noexcept { return a.pool_ != b.pool_ || a.allocator_ != b.allocator_ || a.bits_ != b.bits_; } -#if !defined(GENERATING_DOCUMENTATION) -private: - friend struct asio_execution_execute_fn::impl; -#endif // !defined(GENERATING_DOCUMENTATION) - /// Execution function. - /** - * Do not call this function directly. It is intended for use with the - * execution::execute customisation point. - * - * For example: - * @code auto ex = my_thread_pool.executor(); - * execution::execute(ex, my_function_object); @endcode - */ template <typename Function> - void execute(ASIO_MOVE_ARG(Function) f) const + void execute(Function&& f) const { - this->do_execute(ASIO_MOVE_CAST(Function)(f), + this->do_execute(static_cast<Function&&>(f), integral_constant<bool, (Bits & blocking_always) != 0>()); } public: - /// Bulk execution function. - template <typename Function> - void bulk_execute(ASIO_MOVE_ARG(Function) f, std::size_t n) const - { - this->do_bulk_execute(ASIO_MOVE_CAST(Function)(f), n, - integral_constant<bool, (Bits & blocking_always) != 0>()); - } - - /// Schedule function. - /** - * Do not call this function directly. It is intended for use with the - * execution::schedule customisation point. - * - * @return An object that satisfies the sender concept. - */ - sender_type schedule() const ASIO_NOEXCEPT - { - return *this; - } - - /// Connect function. - /** - * Do not call this function directly. It is intended for use with the - * execution::connect customisation point. - * - * @return An object of an unspecified type that satisfies the @c - * operation_state concept. - */ - template <ASIO_EXECUTION_RECEIVER_OF_0 Receiver> -#if defined(GENERATING_DOCUMENTATION) - unspecified -#else // defined(GENERATING_DOCUMENTATION) - execution::detail::as_operation<basic_executor_type, Receiver> -#endif // defined(GENERATING_DOCUMENTATION) - connect(ASIO_MOVE_ARG(Receiver) r) const - { - return execution::detail::as_operation<basic_executor_type, Receiver>( - *this, ASIO_MOVE_CAST(Receiver)(r)); - } - #if !defined(ASIO_NO_TS_EXECUTORS) /// Obtain the underlying execution context. - thread_pool& context() const ASIO_NOEXCEPT; + thread_pool& context() const noexcept; /// Inform the thread pool that it has some outstanding work to do. /** @@ -663,7 +553,7 @@ public: * This ensures that the thread pool's join() function will not return while * the work is underway. */ - void on_work_started() const ASIO_NOEXCEPT; + void on_work_started() const noexcept; /// Inform the thread pool that some work is no longer outstanding. /** @@ -671,7 +561,7 @@ public: * finished. Once the count of unfinished work reaches zero, the thread * pool's join() function is permitted to exit. */ - void on_work_finished() const ASIO_NOEXCEPT; + void on_work_finished() const noexcept; /// Request the thread pool to invoke the given function object. /** @@ -688,8 +578,7 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename OtherAllocator> - void dispatch(ASIO_MOVE_ARG(Function) f, - const OtherAllocator& a) const; + void dispatch(Function&& f, const OtherAllocator& a) const; /// Request the thread pool to invoke the given function object. /** @@ -705,8 +594,7 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename OtherAllocator> - void post(ASIO_MOVE_ARG(Function) f, - const OtherAllocator& a) const; + void post(Function&& f, const OtherAllocator& a) const; /// Request the thread pool to invoke the given function object. /** @@ -726,8 +614,7 @@ public: * internal storage needed for function invocation. */ template <typename Function, typename OtherAllocator> - void defer(ASIO_MOVE_ARG(Function) f, - const OtherAllocator& a) const; + void defer(Function&& f, const OtherAllocator& a) const; #endif // !defined(ASIO_NO_TS_EXECUTORS) private: @@ -735,7 +622,7 @@ private: template <typename, unsigned int> friend class basic_executor_type; // Constructor used by thread_pool::get_executor(). - explicit basic_executor_type(thread_pool& p) ASIO_NOEXCEPT + explicit basic_executor_type(thread_pool& p) noexcept : pool_(&p), allocator_(), bits_(0) @@ -746,7 +633,7 @@ private: // Constructor used by require(). basic_executor_type(thread_pool* p, - const Allocator& a, unsigned int bits) ASIO_NOEXCEPT + const Allocator& a, unsigned int bits) noexcept : pool_(p), allocator_(a), bits_(bits) @@ -758,21 +645,11 @@ private: /// Execution helper implementation for possibly and never blocking. template <typename Function> - void do_execute(ASIO_MOVE_ARG(Function) f, false_type) const; + void do_execute(Function&& f, false_type) const; /// Execution helper implementation for always blocking. template <typename Function> - void do_execute(ASIO_MOVE_ARG(Function) f, true_type) const; - - /// Bulk execution helper implementation for possibly and never blocking. - template <typename Function> - void do_bulk_execute(ASIO_MOVE_ARG(Function) f, - std::size_t n, false_type) const; - - /// Bulk execution helper implementation for always blocking. - template <typename Function> - void do_bulk_execute(ASIO_MOVE_ARG(Function) f, - std::size_t n, true_type) const; + void do_execute(Function&& f, true_type) const; // The underlying thread pool. thread_pool* pool_; @@ -795,8 +672,8 @@ struct equality_comparable< asio::thread_pool::basic_executor_type<Allocator, Bits> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; }; #endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) @@ -809,45 +686,13 @@ struct execute_member< Function > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef void result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) -#if !defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) - -template <typename Allocator, unsigned int Bits> -struct schedule_member< - const asio::thread_pool::basic_executor_type<Allocator, Bits> - > -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef asio::thread_pool::basic_executor_type< - Allocator, Bits> result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) - -#if !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) - -template <typename Allocator, unsigned int Bits, typename Receiver> -struct connect_member< - const asio::thread_pool::basic_executor_type<Allocator, Bits>, - Receiver - > -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); - typedef asio::execution::detail::as_operation< - asio::thread_pool::basic_executor_type<Allocator, Bits>, - Receiver> result_type; -}; - -#endif // !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) - #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) template <typename Allocator, unsigned int Bits> @@ -856,8 +701,8 @@ struct require_member< asio::execution::blocking_t::possibly_t > : asio::detail::thread_pool_bits { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::thread_pool::basic_executor_type< Allocator, Bits & ~blocking_mask> result_type; }; @@ -868,8 +713,8 @@ struct require_member< asio::execution::blocking_t::always_t > : asio::detail::thread_pool_bits { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::thread_pool::basic_executor_type<Allocator, (Bits & ~blocking_mask) | blocking_always> result_type; }; @@ -880,8 +725,8 @@ struct require_member< asio::execution::blocking_t::never_t > : asio::detail::thread_pool_bits { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::thread_pool::basic_executor_type< Allocator, Bits & ~blocking_mask> result_type; }; @@ -892,8 +737,8 @@ struct require_member< asio::execution::relationship_t::fork_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::thread_pool::basic_executor_type< Allocator, Bits> result_type; }; @@ -904,8 +749,8 @@ struct require_member< asio::execution::relationship_t::continuation_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::thread_pool::basic_executor_type< Allocator, Bits> result_type; }; @@ -916,8 +761,8 @@ struct require_member< asio::execution::outstanding_work_t::tracked_t > : asio::detail::thread_pool_bits { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::thread_pool::basic_executor_type< Allocator, Bits | outstanding_work_tracked> result_type; }; @@ -928,8 +773,8 @@ struct require_member< asio::execution::outstanding_work_t::untracked_t > : asio::detail::thread_pool_bits { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::thread_pool::basic_executor_type< Allocator, Bits & ~outstanding_work_tracked> result_type; }; @@ -940,8 +785,8 @@ struct require_member< asio::execution::allocator_t<void> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::thread_pool::basic_executor_type< std::allocator<void>, Bits> result_type; }; @@ -953,8 +798,8 @@ struct require_member< asio::execution::allocator_t<OtherAllocator> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = false; typedef asio::thread_pool::basic_executor_type< OtherAllocator, Bits> result_type; }; @@ -970,38 +815,16 @@ struct query_static_constexpr_member< typename asio::enable_if< asio::is_convertible< Property, - asio::execution::bulk_guarantee_t - >::value - >::type - > -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); - typedef asio::execution::bulk_guarantee_t::parallel_t result_type; - - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT - { - return result_type(); - } -}; - -template <typename Allocator, unsigned int Bits, typename Property> -struct query_static_constexpr_member< - asio::thread_pool::basic_executor_type<Allocator, Bits>, - Property, - typename asio::enable_if< - asio::is_convertible< - Property, asio::execution::outstanding_work_t >::value >::type > : asio::detail::thread_pool_bits { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::execution::outstanding_work_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return (Bits & outstanding_work_tracked) ? execution::outstanding_work_t(execution::outstanding_work.tracked) @@ -1021,11 +844,11 @@ struct query_static_constexpr_member< >::type > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::execution::mapping_t::thread_t result_type; - static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT + static constexpr result_type value() noexcept { return result_type(); } @@ -1047,8 +870,8 @@ struct query_member< >::type > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::execution::blocking_t result_type; }; @@ -1064,8 +887,8 @@ struct query_member< >::type > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::execution::relationship_t result_type; }; @@ -1075,8 +898,8 @@ struct query_member< asio::execution::occupancy_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef std::size_t result_type; }; @@ -1086,8 +909,8 @@ struct query_member< asio::execution::context_t > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef asio::thread_pool& result_type; }; @@ -1097,8 +920,8 @@ struct query_member< asio::execution::allocator_t<void> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef Allocator result_type; }; @@ -1108,8 +931,8 @@ struct query_member< asio::execution::allocator_t<OtherAllocator> > { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true); + static constexpr bool is_valid = true; + static constexpr bool is_noexcept = true; typedef Allocator result_type; }; @@ -1117,6 +940,15 @@ struct query_member< } // namespace traits +namespace execution { + +template <> +struct is_executor<thread_pool> : false_type +{ +}; + +} // namespace execution + #endif // !defined(GENERATING_DOCUMENTATION) } // namespace asio diff --git a/3rdparty/asio/include/asio/time_traits.hpp b/3rdparty/asio/include/asio/time_traits.hpp index 7f847e89b90..f3980233eab 100644 --- a/3rdparty/asio/include/asio/time_traits.hpp +++ b/3rdparty/asio/include/asio/time_traits.hpp @@ -2,7 +2,7 @@ // time_traits.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/traits/bulk_execute_free.hpp b/3rdparty/asio/include/asio/traits/bulk_execute_free.hpp deleted file mode 100644 index 3e089bc3ac7..00000000000 --- a/3rdparty/asio/include/asio/traits/bulk_execute_free.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// traits/bulk_execute_free.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_BULK_EXECUTE_FREE_HPP -#define ASIO_TRAITS_BULK_EXECUTE_FREE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_BULK_EXECUTE_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename F, typename N, typename = void> -struct bulk_execute_free_default; - -template <typename T, typename F, typename N, typename = void> -struct bulk_execute_free; - -} // namespace traits -namespace detail { - -struct no_bulk_execute_free -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_FREE_TRAIT) - -template <typename T, typename F, typename N, typename = void> -struct bulk_execute_free_trait : no_bulk_execute_free -{ -}; - -template <typename T, typename F, typename N> -struct bulk_execute_free_trait<T, F, N, - typename void_type< - decltype(bulk_execute(declval<T>(), declval<F>(), declval<N>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype( - bulk_execute(declval<T>(), declval<F>(), declval<N>())); - - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - bulk_execute(declval<T>(), declval<F>(), declval<N>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_FREE_TRAIT) - -template <typename T, typename F, typename N, typename = void> -struct bulk_execute_free_trait : - conditional< - is_same<T, typename remove_reference<T>::type>::value - && is_same<F, typename decay<F>::type>::value - && is_same<N, typename decay<N>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_bulk_execute_free, - traits::bulk_execute_free<typename add_const<T>::type, F, N> - >::type, - traits::bulk_execute_free< - typename remove_reference<T>::type, - typename decay<F>::type, - typename decay<N>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_FREE_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename F, typename N, typename> -struct bulk_execute_free_default : - detail::bulk_execute_free_trait<T, F, N> -{ -}; - -template <typename T, typename F, typename N, typename> -struct bulk_execute_free : - bulk_execute_free_default<T, F, N> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_BULK_EXECUTE_FREE_HPP diff --git a/3rdparty/asio/include/asio/traits/bulk_execute_member.hpp b/3rdparty/asio/include/asio/traits/bulk_execute_member.hpp deleted file mode 100644 index f0e1e90dbac..00000000000 --- a/3rdparty/asio/include/asio/traits/bulk_execute_member.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// traits/bulk_execute_member.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_BULK_EXECUTE_MEMBER_HPP -#define ASIO_TRAITS_BULK_EXECUTE_MEMBER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_BULK_EXECUTE_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename F, typename N, typename = void> -struct bulk_execute_member_default; - -template <typename T, typename F, typename N, typename = void> -struct bulk_execute_member; - -} // namespace traits -namespace detail { - -struct no_bulk_execute_member -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_MEMBER_TRAIT) - -template <typename T, typename F, typename N, typename = void> -struct bulk_execute_member_trait : no_bulk_execute_member -{ -}; - -template <typename T, typename F, typename N> -struct bulk_execute_member_trait<T, F, N, - typename void_type< - decltype(declval<T>().bulk_execute(declval<F>(), declval<N>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype( - declval<T>().bulk_execute(declval<F>(), declval<N>())); - - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - declval<T>().bulk_execute(declval<F>(), declval<N>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_MEMBER_TRAIT) - -template <typename T, typename F, typename N, typename = void> -struct bulk_execute_member_trait : - conditional< - is_same<T, typename remove_reference<T>::type>::value - && is_same<F, typename decay<F>::type>::value - && is_same<N, typename decay<N>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_bulk_execute_member, - traits::bulk_execute_member<typename add_const<T>::type, F, N> - >::type, - traits::bulk_execute_member< - typename remove_reference<T>::type, - typename decay<F>::type, - typename decay<N>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_MEMBER_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename F, typename N, typename> -struct bulk_execute_member_default : - detail::bulk_execute_member_trait<T, F, N> -{ -}; - -template <typename T, typename F, typename N, typename> -struct bulk_execute_member : - bulk_execute_member_default<T, F, N> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_BULK_EXECUTE_MEMBER_HPP diff --git a/3rdparty/asio/include/asio/traits/connect_free.hpp b/3rdparty/asio/include/asio/traits/connect_free.hpp deleted file mode 100644 index 96b3ac44078..00000000000 --- a/3rdparty/asio/include/asio/traits/connect_free.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// traits/connect_free.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_CONNECT_FREE_HPP -#define ASIO_TRAITS_CONNECT_FREE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename S, typename R, typename = void> -struct connect_free_default; - -template <typename S, typename R, typename = void> -struct connect_free; - -} // namespace traits -namespace detail { - -struct no_connect_free -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT) - -template <typename S, typename R, typename = void> -struct connect_free_trait : no_connect_free -{ -}; - -template <typename S, typename R> -struct connect_free_trait<S, R, - typename void_type< - decltype(connect(declval<S>(), declval<R>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype( - connect(declval<S>(), declval<R>())); - - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - connect(declval<S>(), declval<R>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT) - -template <typename S, typename R, typename = void> -struct connect_free_trait : - conditional< - is_same<S, typename remove_reference<S>::type>::value - && is_same<R, typename decay<R>::type>::value, - typename conditional< - is_same<S, typename add_const<S>::type>::value, - no_connect_free, - traits::connect_free<typename add_const<S>::type, R> - >::type, - traits::connect_free< - typename remove_reference<S>::type, - typename decay<R>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT) - -} // namespace detail -namespace traits { - -template <typename S, typename R, typename> -struct connect_free_default : - detail::connect_free_trait<S, R> -{ -}; - -template <typename S, typename R, typename> -struct connect_free : - connect_free_default<S, R> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_CONNECT_FREE_HPP diff --git a/3rdparty/asio/include/asio/traits/connect_member.hpp b/3rdparty/asio/include/asio/traits/connect_member.hpp deleted file mode 100644 index d73beed5453..00000000000 --- a/3rdparty/asio/include/asio/traits/connect_member.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// traits/connect_member.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_CONNECT_MEMBER_HPP -#define ASIO_TRAITS_CONNECT_MEMBER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename S, typename R, typename = void> -struct connect_member_default; - -template <typename S, typename R, typename = void> -struct connect_member; - -} // namespace traits -namespace detail { - -struct no_connect_member -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) - -template <typename S, typename R, typename = void> -struct connect_member_trait : no_connect_member -{ -}; - -template <typename S, typename R> -struct connect_member_trait<S, R, - typename void_type< - decltype(declval<S>().connect(declval<R>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype( - declval<S>().connect(declval<R>())); - - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - declval<S>().connect(declval<R>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) - -template <typename S, typename R, typename = void> -struct connect_member_trait : - conditional< - is_same<S, typename remove_reference<S>::type>::value - && is_same<R, typename decay<R>::type>::value, - typename conditional< - is_same<S, typename add_const<S>::type>::value, - no_connect_member, - traits::connect_member<typename add_const<S>::type, R> - >::type, - traits::connect_member< - typename remove_reference<S>::type, - typename decay<R>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) - -} // namespace detail -namespace traits { - -template <typename S, typename R, typename> -struct connect_member_default : - detail::connect_member_trait<S, R> -{ -}; - -template <typename S, typename R, typename> -struct connect_member : - connect_member_default<S, R> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_CONNECT_MEMBER_HPP diff --git a/3rdparty/asio/include/asio/traits/equality_comparable.hpp b/3rdparty/asio/include/asio/traits/equality_comparable.hpp index c8418ca3b94..0a6decf2d93 100644 --- a/3rdparty/asio/include/asio/traits/equality_comparable.hpp +++ b/3rdparty/asio/include/asio/traits/equality_comparable.hpp @@ -2,7 +2,7 @@ // traits/equality_comparable.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,13 +18,9 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) namespace asio { namespace traits { @@ -40,8 +36,8 @@ namespace detail { struct no_equality_comparable { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = false; + static constexpr bool is_noexcept = false; }; #if defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) @@ -53,7 +49,7 @@ struct equality_comparable_trait : no_equality_comparable template <typename T> struct equality_comparable_trait<T, - typename void_type< + void_t< decltype( static_cast<void>( static_cast<bool>(declval<const T>() == declval<const T>()) @@ -62,24 +58,24 @@ struct equality_comparable_trait<T, static_cast<bool>(declval<const T>() != declval<const T>()) ) ) - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = + static constexpr bool is_noexcept = noexcept(declval<const T>() == declval<const T>()) - && noexcept(declval<const T>() != declval<const T>())); + && noexcept(declval<const T>() != declval<const T>()); }; #else // defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) template <typename T, typename = void> struct equality_comparable_trait : - conditional< - is_same<T, typename decay<T>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value, no_equality_comparable, - traits::equality_comparable<typename decay<T>::type> - >::type + traits::equality_comparable<decay_t<T>> + > { }; diff --git a/3rdparty/asio/include/asio/traits/execute_free.hpp b/3rdparty/asio/include/asio/traits/execute_free.hpp deleted file mode 100644 index f66d937b021..00000000000 --- a/3rdparty/asio/include/asio/traits/execute_free.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// traits/execute_free.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_EXECUTE_FREE_HPP -#define ASIO_TRAITS_EXECUTE_FREE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename F, typename = void> -struct execute_free_default; - -template <typename T, typename F, typename = void> -struct execute_free; - -} // namespace traits -namespace detail { - -struct no_execute_free -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT) - -template <typename T, typename F, typename = void> -struct execute_free_trait : no_execute_free -{ -}; - -template <typename T, typename F> -struct execute_free_trait<T, F, - typename void_type< - decltype(execute(declval<T>(), declval<F>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype( - execute(declval<T>(), declval<F>())); - - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - execute(declval<T>(), declval<F>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT) - -template <typename T, typename F, typename = void> -struct execute_free_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<F, typename decay<F>::type>::value, - no_execute_free, - traits::execute_free< - typename decay<T>::type, - typename decay<F>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename F, typename> -struct execute_free_default : - detail::execute_free_trait<T, F> -{ -}; - -template <typename T, typename F, typename> -struct execute_free : - execute_free_default<T, F> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_EXECUTE_FREE_HPP diff --git a/3rdparty/asio/include/asio/traits/execute_member.hpp b/3rdparty/asio/include/asio/traits/execute_member.hpp index 01f280d56b4..fc0760bef05 100644 --- a/3rdparty/asio/include/asio/traits/execute_member.hpp +++ b/3rdparty/asio/include/asio/traits/execute_member.hpp @@ -2,7 +2,7 @@ // traits/execute_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,13 +18,9 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) #include "asio/detail/push_options.hpp" @@ -42,8 +38,8 @@ namespace detail { struct no_execute_member { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = false; + static constexpr bool is_noexcept = false; }; #if defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) @@ -55,31 +51,31 @@ struct execute_member_trait : no_execute_member template <typename T, typename F> struct execute_member_trait<T, F, - typename void_type< + void_t< decltype(declval<T>().execute(declval<F>())) - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; using result_type = decltype( declval<T>().execute(declval<F>())); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - declval<T>().execute(declval<F>()))); + static constexpr bool is_noexcept = + noexcept(declval<T>().execute(declval<F>())); }; #else // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) template <typename T, typename F, typename = void> struct execute_member_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<F, typename decay<F>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<F, decay_t<F>>::value, no_execute_member, traits::execute_member< - typename decay<T>::type, - typename decay<F>::type> - >::type + decay_t<T>, + decay_t<F>> + > { }; diff --git a/3rdparty/asio/include/asio/traits/prefer_free.hpp b/3rdparty/asio/include/asio/traits/prefer_free.hpp index 6be0a363241..c6104d636ed 100644 --- a/3rdparty/asio/include/asio/traits/prefer_free.hpp +++ b/3rdparty/asio/include/asio/traits/prefer_free.hpp @@ -2,7 +2,7 @@ // traits/prefer_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,13 +18,9 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) #include "asio/detail/push_options.hpp" @@ -42,8 +38,8 @@ namespace detail { struct no_prefer_free { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = false; + static constexpr bool is_noexcept = false; }; #if defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) @@ -55,31 +51,31 @@ struct prefer_free_trait : no_prefer_free template <typename T, typename Property> struct prefer_free_trait<T, Property, - typename void_type< + void_t< decltype(prefer(declval<T>(), declval<Property>())) - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; using result_type = decltype( prefer(declval<T>(), declval<Property>())); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - prefer(declval<T>(), declval<Property>()))); + static constexpr bool is_noexcept = + noexcept(prefer(declval<T>(), declval<Property>())); }; #else // defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) template <typename T, typename Property, typename = void> struct prefer_free_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_prefer_free, traits::prefer_free< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; diff --git a/3rdparty/asio/include/asio/traits/prefer_member.hpp b/3rdparty/asio/include/asio/traits/prefer_member.hpp index 0dbb1247830..278c25c9964 100644 --- a/3rdparty/asio/include/asio/traits/prefer_member.hpp +++ b/3rdparty/asio/include/asio/traits/prefer_member.hpp @@ -2,7 +2,7 @@ // traits/prefer_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,13 +18,9 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) #include "asio/detail/push_options.hpp" @@ -42,8 +38,8 @@ namespace detail { struct no_prefer_member { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = false; + static constexpr bool is_noexcept = false; }; #if defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) @@ -55,31 +51,31 @@ struct prefer_member_trait : no_prefer_member template <typename T, typename Property> struct prefer_member_trait<T, Property, - typename void_type< + void_t< decltype(declval<T>().prefer(declval<Property>())) - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; using result_type = decltype( declval<T>().prefer(declval<Property>())); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - declval<T>().prefer(declval<Property>()))); + static constexpr bool is_noexcept = + noexcept(declval<T>().prefer(declval<Property>())); }; #else // defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT) template <typename T, typename Property, typename = void> struct prefer_member_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_prefer_member, traits::prefer_member< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; diff --git a/3rdparty/asio/include/asio/traits/query_free.hpp b/3rdparty/asio/include/asio/traits/query_free.hpp index 3347793bf3c..a54016adddc 100644 --- a/3rdparty/asio/include/asio/traits/query_free.hpp +++ b/3rdparty/asio/include/asio/traits/query_free.hpp @@ -2,7 +2,7 @@ // traits/query_free.hpp // ~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,13 +18,9 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) #include "asio/detail/push_options.hpp" @@ -42,8 +38,8 @@ namespace detail { struct no_query_free { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = false; + static constexpr bool is_noexcept = false; }; #if defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) @@ -55,31 +51,31 @@ struct query_free_trait : no_query_free template <typename T, typename Property> struct query_free_trait<T, Property, - typename void_type< + void_t< decltype(query(declval<T>(), declval<Property>())) - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; using result_type = decltype( query(declval<T>(), declval<Property>())); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - query(declval<T>(), declval<Property>()))); + static constexpr bool is_noexcept = + noexcept(query(declval<T>(), declval<Property>())); }; #else // defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) template <typename T, typename Property, typename = void> struct query_free_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_query_free, traits::query_free< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; diff --git a/3rdparty/asio/include/asio/traits/query_member.hpp b/3rdparty/asio/include/asio/traits/query_member.hpp index f69461b5296..2202c9dab4b 100644 --- a/3rdparty/asio/include/asio/traits/query_member.hpp +++ b/3rdparty/asio/include/asio/traits/query_member.hpp @@ -2,7 +2,7 @@ // traits/query_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,13 +18,9 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) #include "asio/detail/push_options.hpp" @@ -42,8 +38,8 @@ namespace detail { struct no_query_member { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = false; + static constexpr bool is_noexcept = false; }; #if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) @@ -55,31 +51,31 @@ struct query_member_trait : no_query_member template <typename T, typename Property> struct query_member_trait<T, Property, - typename void_type< + void_t< decltype(declval<T>().query(declval<Property>())) - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; using result_type = decltype( declval<T>().query(declval<Property>())); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - declval<T>().query(declval<Property>()))); + static constexpr bool is_noexcept = + noexcept(declval<T>().query(declval<Property>())); }; #else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) template <typename T, typename Property, typename = void> struct query_member_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_query_member, traits::query_member< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; diff --git a/3rdparty/asio/include/asio/traits/query_static_constexpr_member.hpp b/3rdparty/asio/include/asio/traits/query_static_constexpr_member.hpp index 2c6eb839dd9..95bdb7db376 100644 --- a/3rdparty/asio/include/asio/traits/query_static_constexpr_member.hpp +++ b/3rdparty/asio/include/asio/traits/query_static_constexpr_member.hpp @@ -2,7 +2,7 @@ // traits/query_static_constexpr_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,16 +18,10 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_CONSTEXPR) \ - && defined(ASIO_HAS_CONSTANT_EXPRESSION_SFINAE) \ +#if defined(ASIO_HAS_CONSTANT_EXPRESSION_SFINAE) \ && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_CONSTEXPR) - // && defined(ASIO_HAS_CONSTANT_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_CONSTANT_EXPRESSION_SFINAE) // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) #include "asio/detail/push_options.hpp" @@ -46,19 +40,19 @@ namespace detail { struct no_query_static_constexpr_member { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); + static constexpr bool is_valid = false; }; template <typename T, typename Property, typename = void> struct query_static_constexpr_member_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_query_static_constexpr_member, traits::query_static_constexpr_member< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; @@ -66,18 +60,17 @@ struct query_static_constexpr_member_trait : template <typename T, typename Property> struct query_static_constexpr_member_trait<T, Property, - typename enable_if< + enable_if_t< (static_cast<void>(T::query(Property{})), true) - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; using result_type = decltype(T::query(Property{})); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - noexcept(T::query(Property{}))); + static constexpr bool is_noexcept = noexcept(T::query(Property{})); - static ASIO_CONSTEXPR result_type value() noexcept(is_noexcept) + static constexpr result_type value() noexcept(is_noexcept) { return T::query(Property{}); } diff --git a/3rdparty/asio/include/asio/traits/require_concept_free.hpp b/3rdparty/asio/include/asio/traits/require_concept_free.hpp index d7ea447e39d..1ae2ad7801d 100644 --- a/3rdparty/asio/include/asio/traits/require_concept_free.hpp +++ b/3rdparty/asio/include/asio/traits/require_concept_free.hpp @@ -2,7 +2,7 @@ // traits/require_concept_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,13 +18,9 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) #include "asio/detail/push_options.hpp" @@ -42,8 +38,8 @@ namespace detail { struct no_require_concept_free { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = false; + static constexpr bool is_noexcept = false; }; #if defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_FREE_TRAIT) @@ -55,31 +51,31 @@ struct require_concept_free_trait : no_require_concept_free template <typename T, typename Property> struct require_concept_free_trait<T, Property, - typename void_type< + void_t< decltype(require_concept(declval<T>(), declval<Property>())) - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; using result_type = decltype( require_concept(declval<T>(), declval<Property>())); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - require_concept(declval<T>(), declval<Property>()))); + static constexpr bool is_noexcept = + noexcept(require_concept(declval<T>(), declval<Property>())); }; #else // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_FREE_TRAIT) template <typename T, typename Property, typename = void> struct require_concept_free_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_require_concept_free, traits::require_concept_free< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; diff --git a/3rdparty/asio/include/asio/traits/require_concept_member.hpp b/3rdparty/asio/include/asio/traits/require_concept_member.hpp index a7e86059037..f6b6535e9bd 100644 --- a/3rdparty/asio/include/asio/traits/require_concept_member.hpp +++ b/3rdparty/asio/include/asio/traits/require_concept_member.hpp @@ -2,7 +2,7 @@ // traits/require_concept_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,13 +18,9 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) #include "asio/detail/push_options.hpp" @@ -42,8 +38,8 @@ namespace detail { struct no_require_concept_member { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = false; + static constexpr bool is_noexcept = false; }; #if defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT) @@ -55,31 +51,31 @@ struct require_concept_member_trait : no_require_concept_member template <typename T, typename Property> struct require_concept_member_trait<T, Property, - typename void_type< + void_t< decltype(declval<T>().require_concept(declval<Property>())) - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; using result_type = decltype( declval<T>().require_concept(declval<Property>())); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - declval<T>().require_concept(declval<Property>()))); + static constexpr bool is_noexcept = + noexcept(declval<T>().require_concept(declval<Property>())); }; #else // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT) template <typename T, typename Property, typename = void> struct require_concept_member_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_require_concept_member, traits::require_concept_member< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; diff --git a/3rdparty/asio/include/asio/traits/require_free.hpp b/3rdparty/asio/include/asio/traits/require_free.hpp index 53cf805a316..02b558676b1 100644 --- a/3rdparty/asio/include/asio/traits/require_free.hpp +++ b/3rdparty/asio/include/asio/traits/require_free.hpp @@ -2,7 +2,7 @@ // traits/require_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,13 +18,9 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) #include "asio/detail/push_options.hpp" @@ -42,8 +38,8 @@ namespace detail { struct no_require_free { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = false; + static constexpr bool is_noexcept = false; }; #if defined(ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT) @@ -55,31 +51,31 @@ struct require_free_trait : no_require_free template <typename T, typename Property> struct require_free_trait<T, Property, - typename void_type< + void_t< decltype(require(declval<T>(), declval<Property>())) - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; using result_type = decltype( require(declval<T>(), declval<Property>())); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - require(declval<T>(), declval<Property>()))); + static constexpr bool is_noexcept = + noexcept(require(declval<T>(), declval<Property>())); }; #else // defined(ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT) template <typename T, typename Property, typename = void> struct require_free_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_require_free, traits::require_free< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; diff --git a/3rdparty/asio/include/asio/traits/require_member.hpp b/3rdparty/asio/include/asio/traits/require_member.hpp index 2c8c4bbcbe0..af733e3b270 100644 --- a/3rdparty/asio/include/asio/traits/require_member.hpp +++ b/3rdparty/asio/include/asio/traits/require_member.hpp @@ -2,7 +2,7 @@ // traits/require_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,13 +18,9 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) +#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) #include "asio/detail/push_options.hpp" @@ -42,8 +38,8 @@ namespace detail { struct no_require_member { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = false; + static constexpr bool is_noexcept = false; }; #if defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) @@ -55,31 +51,31 @@ struct require_member_trait : no_require_member template <typename T, typename Property> struct require_member_trait<T, Property, - typename void_type< + void_t< decltype(declval<T>().require(declval<Property>())) - >::type> + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; using result_type = decltype( declval<T>().require(declval<Property>())); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - declval<T>().require(declval<Property>()))); + static constexpr bool is_noexcept = + noexcept(declval<T>().require(declval<Property>())); }; #else // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) template <typename T, typename Property, typename = void> struct require_member_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_require_member, traits::require_member< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; diff --git a/3rdparty/asio/include/asio/traits/schedule_free.hpp b/3rdparty/asio/include/asio/traits/schedule_free.hpp deleted file mode 100644 index 36ccad32d98..00000000000 --- a/3rdparty/asio/include/asio/traits/schedule_free.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// traits/schedule_free.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_SCHEDULE_FREE_HPP -#define ASIO_TRAITS_SCHEDULE_FREE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename = void> -struct schedule_free_default; - -template <typename T, typename = void> -struct schedule_free; - -} // namespace traits -namespace detail { - -struct no_schedule_free -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT) - -template <typename T, typename = void> -struct schedule_free_trait : no_schedule_free -{ -}; - -template <typename T> -struct schedule_free_trait<T, - typename void_type< - decltype(schedule(declval<T>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype(schedule(declval<T>())); - - ASIO_STATIC_CONSTEXPR(bool, - is_noexcept = noexcept(schedule(declval<T>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT) - -template <typename T, typename = void> -struct schedule_free_trait : - conditional< - is_same<T, typename remove_reference<T>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_schedule_free, - traits::schedule_free<typename add_const<T>::type> - >::type, - traits::schedule_free<typename remove_reference<T>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename> -struct schedule_free_default : - detail::schedule_free_trait<T> -{ -}; - -template <typename T, typename> -struct schedule_free : - schedule_free_default<T> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_SCHEDULE_FREE_HPP diff --git a/3rdparty/asio/include/asio/traits/schedule_member.hpp b/3rdparty/asio/include/asio/traits/schedule_member.hpp deleted file mode 100644 index b2e6d568816..00000000000 --- a/3rdparty/asio/include/asio/traits/schedule_member.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// traits/schedule_member.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_SCHEDULE_MEMBER_HPP -#define ASIO_TRAITS_SCHEDULE_MEMBER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename = void> -struct schedule_member_default; - -template <typename T, typename = void> -struct schedule_member; - -} // namespace traits -namespace detail { - -struct no_schedule_member -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) - -template <typename T, typename = void> -struct schedule_member_trait : no_schedule_member -{ -}; - -template <typename T> -struct schedule_member_trait<T, - typename void_type< - decltype(declval<T>().schedule()) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype(declval<T>().schedule()); - - ASIO_STATIC_CONSTEXPR(bool, - is_noexcept = noexcept(declval<T>().schedule())); -}; - -#else // defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) - -template <typename T, typename = void> -struct schedule_member_trait : - conditional< - is_same<T, typename remove_reference<T>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_schedule_member, - traits::schedule_member<typename add_const<T>::type> - >::type, - traits::schedule_member<typename remove_reference<T>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename> -struct schedule_member_default : - detail::schedule_member_trait<T> -{ -}; - -template <typename T, typename> -struct schedule_member : - schedule_member_default<T> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_SCHEDULE_MEMBER_HPP diff --git a/3rdparty/asio/include/asio/traits/set_done_free.hpp b/3rdparty/asio/include/asio/traits/set_done_free.hpp deleted file mode 100644 index f52e02c0d84..00000000000 --- a/3rdparty/asio/include/asio/traits/set_done_free.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// traits/set_done_free.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_SET_DONE_FREE_HPP -#define ASIO_TRAITS_SET_DONE_FREE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename = void> -struct set_done_free_default; - -template <typename T, typename = void> -struct set_done_free; - -} // namespace traits -namespace detail { - -struct no_set_done_free -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT) - -template <typename T, typename = void> -struct set_done_free_trait : no_set_done_free -{ -}; - -template <typename T> -struct set_done_free_trait<T, - typename void_type< - decltype(set_done(declval<T>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype(set_done(declval<T>())); - - ASIO_STATIC_CONSTEXPR(bool, - is_noexcept = noexcept(set_done(declval<T>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT) - -template <typename T, typename = void> -struct set_done_free_trait : - conditional< - is_same<T, typename remove_reference<T>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_set_done_free, - traits::set_done_free<typename add_const<T>::type> - >::type, - traits::set_done_free<typename remove_reference<T>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename> -struct set_done_free_default : - detail::set_done_free_trait<T> -{ -}; - -template <typename T, typename> -struct set_done_free : - set_done_free_default<T> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_SET_DONE_FREE_HPP diff --git a/3rdparty/asio/include/asio/traits/set_done_member.hpp b/3rdparty/asio/include/asio/traits/set_done_member.hpp deleted file mode 100644 index 1ee9cdc3067..00000000000 --- a/3rdparty/asio/include/asio/traits/set_done_member.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// traits/set_done_member.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_SET_DONE_MEMBER_HPP -#define ASIO_TRAITS_SET_DONE_MEMBER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename = void> -struct set_done_member_default; - -template <typename T, typename = void> -struct set_done_member; - -} // namespace traits -namespace detail { - -struct no_set_done_member -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - -template <typename T, typename = void> -struct set_done_member_trait : no_set_done_member -{ -}; - -template <typename T> -struct set_done_member_trait<T, - typename void_type< - decltype(declval<T>().set_done()) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype(declval<T>().set_done()); - - ASIO_STATIC_CONSTEXPR(bool, - is_noexcept = noexcept(declval<T>().set_done())); -}; - -#else // defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - -template <typename T, typename = void> -struct set_done_member_trait : - conditional< - is_same<T, typename remove_reference<T>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_set_done_member, - traits::set_done_member<typename add_const<T>::type> - >::type, - traits::set_done_member<typename remove_reference<T>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename> -struct set_done_member_default : - detail::set_done_member_trait<T> -{ -}; - -template <typename T, typename> -struct set_done_member : - set_done_member_default<T> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_SET_DONE_MEMBER_HPP diff --git a/3rdparty/asio/include/asio/traits/set_error_free.hpp b/3rdparty/asio/include/asio/traits/set_error_free.hpp deleted file mode 100644 index b7455be5025..00000000000 --- a/3rdparty/asio/include/asio/traits/set_error_free.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// traits/set_error_free.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_SET_ERROR_FREE_HPP -#define ASIO_TRAITS_SET_ERROR_FREE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename E, typename = void> -struct set_error_free_default; - -template <typename T, typename E, typename = void> -struct set_error_free; - -} // namespace traits -namespace detail { - -struct no_set_error_free -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT) - -template <typename T, typename E, typename = void> -struct set_error_free_trait : no_set_error_free -{ -}; - -template <typename T, typename E> -struct set_error_free_trait<T, E, - typename void_type< - decltype(set_error(declval<T>(), declval<E>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype( - set_error(declval<T>(), declval<E>())); - - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - set_error(declval<T>(), declval<E>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT) - -template <typename T, typename E, typename = void> -struct set_error_free_trait : - conditional< - is_same<T, typename remove_reference<T>::type>::value - && is_same<E, typename decay<E>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_set_error_free, - traits::set_error_free<typename add_const<T>::type, E> - >::type, - traits::set_error_free< - typename remove_reference<T>::type, - typename decay<E>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename E, typename> -struct set_error_free_default : - detail::set_error_free_trait<T, E> -{ -}; - -template <typename T, typename E, typename> -struct set_error_free : - set_error_free_default<T, E> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_SET_ERROR_FREE_HPP diff --git a/3rdparty/asio/include/asio/traits/set_error_member.hpp b/3rdparty/asio/include/asio/traits/set_error_member.hpp deleted file mode 100644 index b9ef63e03a0..00000000000 --- a/3rdparty/asio/include/asio/traits/set_error_member.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// traits/set_error_member.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_SET_ERROR_MEMBER_HPP -#define ASIO_TRAITS_SET_ERROR_MEMBER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename E, typename = void> -struct set_error_member_default; - -template <typename T, typename E, typename = void> -struct set_error_member; - -} // namespace traits -namespace detail { - -struct no_set_error_member -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - -template <typename T, typename E, typename = void> -struct set_error_member_trait : no_set_error_member -{ -}; - -template <typename T, typename E> -struct set_error_member_trait<T, E, - typename void_type< - decltype(declval<T>().set_error(declval<E>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype( - declval<T>().set_error(declval<E>())); - - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - declval<T>().set_error(declval<E>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - -template <typename T, typename E, typename = void> -struct set_error_member_trait : - conditional< - is_same<T, typename remove_reference<T>::type>::value - && is_same<E, typename decay<E>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_set_error_member, - traits::set_error_member<typename add_const<T>::type, E> - >::type, - traits::set_error_member< - typename remove_reference<T>::type, - typename decay<E>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename E, typename> -struct set_error_member_default : - detail::set_error_member_trait<T, E> -{ -}; - -template <typename T, typename E, typename> -struct set_error_member : - set_error_member_default<T, E> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_SET_ERROR_MEMBER_HPP diff --git a/3rdparty/asio/include/asio/traits/set_value_free.hpp b/3rdparty/asio/include/asio/traits/set_value_free.hpp deleted file mode 100644 index cb5b382754d..00000000000 --- a/3rdparty/asio/include/asio/traits/set_value_free.hpp +++ /dev/null @@ -1,234 +0,0 @@ -// -// traits/set_value_free.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_SET_VALUE_FREE_HPP -#define ASIO_TRAITS_SET_VALUE_FREE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename Vs, typename = void> -struct set_value_free_default; - -template <typename T, typename Vs, typename = void> -struct set_value_free; - -} // namespace traits -namespace detail { - -struct no_set_value_free -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT) - -template <typename T, typename Vs, typename = void> -struct set_value_free_trait : no_set_value_free -{ -}; - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T, typename... Vs> -struct set_value_free_trait<T, void(Vs...), - typename void_type< - decltype(set_value(declval<T>(), declval<Vs>()...)) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype( - set_value(declval<T>(), declval<Vs>()...)); - - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - set_value(declval<T>(), declval<Vs>()...))); -}; - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T> -struct set_value_free_trait<T, void(), - typename void_type< - decltype(set_value(declval<T>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype(set_value(declval<T>())); - - ASIO_STATIC_CONSTEXPR(bool, - is_noexcept = noexcept(set_value(declval<T>()))); -}; - -#define ASIO_PRIVATE_SET_VALUE_FREE_TRAIT_DEF(n) \ - template <typename T, ASIO_VARIADIC_TPARAMS(n)> \ - struct set_value_free_trait<T, void(ASIO_VARIADIC_TARGS(n)), \ - typename void_type< \ - decltype(set_value(declval<T>(), ASIO_VARIADIC_DECLVAL(n))) \ - >::type> \ - { \ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); \ - \ - using result_type = decltype( \ - set_value(declval<T>(), ASIO_VARIADIC_DECLVAL(n))); \ - \ - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( \ - set_value(declval<T>(), ASIO_VARIADIC_DECLVAL(n)))); \ - }; \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_FREE_TRAIT_DEF) -#undef ASIO_PRIVATE_SET_VALUE_FREE_TRAIT_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#else // defined(ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT) - -template <typename T, typename Vs, typename = void> -struct set_value_free_trait; - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T, typename... Vs> -struct set_value_free_trait<T, void(Vs...)> : - conditional< - is_same<T, typename remove_reference<T>::type>::value - && conjunction<is_same<Vs, typename decay<Vs>::type>...>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_set_value_free, - traits::set_value_free<typename add_const<T>::type, void(Vs...)> - >::type, - traits::set_value_free< - typename remove_reference<T>::type, - void(typename decay<Vs>::type...)> - >::type -{ -}; - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T> -struct set_value_free_trait<T, void()> : - conditional< - is_same<T, typename remove_reference<T>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_set_value_free, - traits::set_value_free<typename add_const<T>::type, void()> - >::type, - traits::set_value_free<typename remove_reference<T>::type, void()> - >::type -{ -}; - -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME(n) \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_##n - -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1 \ - && is_same<T1, typename decay<T1>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1 \ - && is_same<T2, typename decay<T2>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2 \ - && is_same<T3, typename decay<T3>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3 \ - && is_same<T4, typename decay<T4>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4 \ - && is_same<T5, typename decay<T5>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5 \ - && is_same<T6, typename decay<T6>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6 \ - && is_same<T7, typename decay<T7>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_8 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7 \ - && is_same<T8, typename decay<T8>::type>::value - -#define ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF(n) \ - template <typename T, ASIO_VARIADIC_TPARAMS(n)> \ - struct set_value_free_trait<T, void(ASIO_VARIADIC_TARGS(n))> : \ - conditional< \ - is_same<T, typename remove_reference<T>::type>::value \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME(n), \ - typename conditional< \ - is_same<T, typename add_const<T>::type>::value, \ - no_set_value_free, \ - traits::set_value_free< \ - typename add_const<T>::type, \ - void(ASIO_VARIADIC_TARGS(n))> \ - >::type, \ - traits::set_value_free< \ - typename remove_reference<T>::type, \ - void(ASIO_VARIADIC_DECAY(n))> \ - >::type \ - { \ - }; \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF) -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_8 - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#endif // defined(ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename Vs, typename> -struct set_value_free_default : - detail::set_value_free_trait<T, Vs> -{ -}; - -template <typename T, typename Vs, typename> -struct set_value_free : - set_value_free_default<T, Vs> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_SET_VALUE_FREE_HPP diff --git a/3rdparty/asio/include/asio/traits/set_value_member.hpp b/3rdparty/asio/include/asio/traits/set_value_member.hpp deleted file mode 100644 index 6b0960713ee..00000000000 --- a/3rdparty/asio/include/asio/traits/set_value_member.hpp +++ /dev/null @@ -1,234 +0,0 @@ -// -// traits/set_value_member.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_SET_VALUE_MEMBER_HPP -#define ASIO_TRAITS_SET_VALUE_MEMBER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" -#include "asio/detail/variadic_templates.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename Vs, typename = void> -struct set_value_member_default; - -template <typename T, typename Vs, typename = void> -struct set_value_member; - -} // namespace traits -namespace detail { - -struct no_set_value_member -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - -template <typename T, typename Vs, typename = void> -struct set_value_member_trait : no_set_value_member -{ -}; - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T, typename... Vs> -struct set_value_member_trait<T, void(Vs...), - typename void_type< - decltype(declval<T>().set_value(declval<Vs>()...)) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype( - declval<T>().set_value(declval<Vs>()...)); - - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - declval<T>().set_value(declval<Vs>()...))); -}; - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T> -struct set_value_member_trait<T, void(), - typename void_type< - decltype(declval<T>().set_value()) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype(declval<T>().set_value()); - - ASIO_STATIC_CONSTEXPR(bool, - is_noexcept = noexcept(declval<T>().set_value())); -}; - -#define ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF(n) \ - template <typename T, ASIO_VARIADIC_TPARAMS(n)> \ - struct set_value_member_trait<T, void(ASIO_VARIADIC_TARGS(n)), \ - typename void_type< \ - decltype(declval<T>().set_value(ASIO_VARIADIC_DECLVAL(n))) \ - >::type> \ - { \ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); \ - \ - using result_type = decltype( \ - declval<T>().set_value(ASIO_VARIADIC_DECLVAL(n))); \ - \ - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( \ - declval<T>().set_value(ASIO_VARIADIC_DECLVAL(n)))); \ - }; \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF) -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#else // defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - -template <typename T, typename Vs, typename = void> -struct set_value_member_trait; - -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T, typename... Vs> -struct set_value_member_trait<T, void(Vs...)> : - conditional< - is_same<T, typename remove_reference<T>::type>::value - && conjunction<is_same<Vs, typename decay<Vs>::type>...>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_set_value_member, - traits::set_value_member<typename add_const<T>::type, void(Vs...)> - >::type, - traits::set_value_member< - typename remove_reference<T>::type, - void(typename decay<Vs>::type...)> - >::type -{ -}; - -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename T> -struct set_value_member_trait<T, void()> : - conditional< - is_same<T, typename remove_reference<T>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_set_value_member, - traits::set_value_member<typename add_const<T>::type, void()> - >::type, - traits::set_value_member<typename remove_reference<T>::type, void()> - >::type -{ -}; - -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME(n) \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_##n - -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1 \ - && is_same<T1, typename decay<T1>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1 \ - && is_same<T2, typename decay<T2>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2 \ - && is_same<T3, typename decay<T3>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3 \ - && is_same<T4, typename decay<T4>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4 \ - && is_same<T5, typename decay<T5>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5 \ - && is_same<T6, typename decay<T6>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6 \ - && is_same<T7, typename decay<T7>::type>::value -#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_8 \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7 \ - && is_same<T8, typename decay<T8>::type>::value - -#define ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF(n) \ - template <typename T, ASIO_VARIADIC_TPARAMS(n)> \ - struct set_value_member_trait<T, void(ASIO_VARIADIC_TARGS(n))> : \ - conditional< \ - is_same<T, typename remove_reference<T>::type>::value \ - ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME(n), \ - typename conditional< \ - is_same<T, typename add_const<T>::type>::value, \ - no_set_value_member, \ - traits::set_value_member< \ - typename add_const<T>::type, \ - void(ASIO_VARIADIC_TARGS(n))> \ - >::type, \ - traits::set_value_member< \ - typename remove_reference<T>::type, \ - void(ASIO_VARIADIC_DECAY(n))> \ - >::type \ - { \ - }; \ - /**/ -ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF) -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7 -#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_8 - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -#endif // defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename Vs, typename> -struct set_value_member_default : - detail::set_value_member_trait<T, Vs> -{ -}; - -template <typename T, typename Vs, typename> -struct set_value_member : - set_value_member_default<T, Vs> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_SET_VALUE_MEMBER_HPP diff --git a/3rdparty/asio/include/asio/traits/start_free.hpp b/3rdparty/asio/include/asio/traits/start_free.hpp deleted file mode 100644 index 2489b97c60d..00000000000 --- a/3rdparty/asio/include/asio/traits/start_free.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// traits/start_free.hpp -// ~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_START_FREE_HPP -#define ASIO_TRAITS_START_FREE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_START_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename = void> -struct start_free_default; - -template <typename T, typename = void> -struct start_free; - -} // namespace traits -namespace detail { - -struct no_start_free -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_START_FREE_TRAIT) - -template <typename T, typename = void> -struct start_free_trait : no_start_free -{ -}; - -template <typename T> -struct start_free_trait<T, - typename void_type< - decltype(start(declval<T>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype(start(declval<T>())); - - ASIO_STATIC_CONSTEXPR(bool, - is_noexcept = noexcept(start(declval<T>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_START_FREE_TRAIT) - -template <typename T, typename = void> -struct start_free_trait : - conditional< - is_same<T, typename remove_reference<T>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_start_free, - traits::start_free<typename add_const<T>::type> - >::type, - traits::start_free<typename remove_reference<T>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_START_FREE_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename> -struct start_free_default : - detail::start_free_trait<T> -{ -}; - -template <typename T, typename> -struct start_free : - start_free_default<T> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_START_FREE_HPP diff --git a/3rdparty/asio/include/asio/traits/start_member.hpp b/3rdparty/asio/include/asio/traits/start_member.hpp deleted file mode 100644 index cb5d2c16736..00000000000 --- a/3rdparty/asio/include/asio/traits/start_member.hpp +++ /dev/null @@ -1,108 +0,0 @@ -// -// traits/start_member.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_START_MEMBER_HPP -#define ASIO_TRAITS_START_MEMBER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_START_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename T, typename = void> -struct start_member_default; - -template <typename T, typename = void> -struct start_member; - -} // namespace traits -namespace detail { - -struct no_start_member -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT) - -template <typename T, typename = void> -struct start_member_trait : no_start_member -{ -}; - -template <typename T> -struct start_member_trait<T, - typename void_type< - decltype(declval<T>().start()) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype(declval<T>().start()); - - ASIO_STATIC_CONSTEXPR(bool, - is_noexcept = noexcept(declval<T>().start())); -}; - -#else // defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT) - -template <typename T, typename = void> -struct start_member_trait : - conditional< - is_same<T, typename remove_reference<T>::type>::value, - typename conditional< - is_same<T, typename add_const<T>::type>::value, - no_start_member, - traits::start_member<typename add_const<T>::type> - >::type, - traits::start_member<typename remove_reference<T>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT) - -} // namespace detail -namespace traits { - -template <typename T, typename> -struct start_member_default : - detail::start_member_trait<T> -{ -}; - -template <typename T, typename> -struct start_member : - start_member_default<T> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_START_MEMBER_HPP diff --git a/3rdparty/asio/include/asio/traits/static_query.hpp b/3rdparty/asio/include/asio/traits/static_query.hpp index d2a96aae85d..b177a9d5304 100644 --- a/3rdparty/asio/include/asio/traits/static_query.hpp +++ b/3rdparty/asio/include/asio/traits/static_query.hpp @@ -2,7 +2,7 @@ // traits/static_query.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,16 +18,10 @@ #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_CONSTEXPR) \ - && defined(ASIO_HAS_VARIABLE_TEMPLATES) \ +#if defined(ASIO_HAS_VARIABLE_TEMPLATES) \ && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) # define ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_CONSTEXPR) - // && defined(ASIO_HAS_VARIABLE_TEMPLATES) +#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) #include "asio/detail/push_options.hpp" @@ -46,20 +40,20 @@ namespace detail { struct no_static_query { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); + static constexpr bool is_valid = false; + static constexpr bool is_noexcept = false; }; template <typename T, typename Property, typename = void> struct static_query_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_static_query, traits::static_query< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; @@ -67,21 +61,21 @@ struct static_query_trait : template <typename T, typename Property> struct static_query_trait<T, Property, - typename void_type< - decltype(decay<Property>::type::template static_query_v<T>) - >::type> + void_t< + decltype(decay_t<Property>::template static_query_v<T>) + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; using result_type = decltype( - decay<Property>::type::template static_query_v<T>); + decay_t<Property>::template static_query_v<T>); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = - noexcept(decay<Property>::type::template static_query_v<T>)); + static constexpr bool is_noexcept = + noexcept(decay_t<Property>::template static_query_v<T>); - static ASIO_CONSTEXPR result_type value() noexcept(is_noexcept) + static constexpr result_type value() noexcept(is_noexcept) { - return decay<Property>::type::template static_query_v<T>; + return decay_t<Property>::template static_query_v<T>; } }; diff --git a/3rdparty/asio/include/asio/traits/static_require.hpp b/3rdparty/asio/include/asio/traits/static_require.hpp index e30c2d101c5..4ef4a617390 100644 --- a/3rdparty/asio/include/asio/traits/static_require.hpp +++ b/3rdparty/asio/include/asio/traits/static_require.hpp @@ -2,7 +2,7 @@ // traits/static_require.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,11 +19,7 @@ #include "asio/detail/type_traits.hpp" #include "asio/traits/static_query.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) -# define ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) +#define ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT 1 #include "asio/detail/push_options.hpp" @@ -41,33 +37,31 @@ namespace detail { struct no_static_require { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); + static constexpr bool is_valid = false; }; template <typename T, typename Property, typename = void> struct static_require_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_static_require, traits::static_require< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; -#if defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - #if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) template <typename T, typename Property> struct static_require_trait<T, Property, - typename enable_if< - decay<Property>::type::value() == traits::static_query<T, Property>::value() - >::type> + enable_if_t< + decay_t<Property>::value() == traits::static_query<T, Property>::value() + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; }; #else // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) @@ -76,32 +70,30 @@ false_type static_require_test(...); template <typename T, typename Property> true_type static_require_test(T*, Property*, - typename enable_if< + enable_if_t< Property::value() == traits::static_query<T, Property>::value() - >::type* = 0); + >* = 0); template <typename T, typename Property> struct has_static_require { - ASIO_STATIC_CONSTEXPR(bool, value = + static constexpr bool value = decltype((static_require_test)( - static_cast<T*>(0), static_cast<Property*>(0)))::value); + static_cast<T*>(0), static_cast<Property*>(0)))::value; }; template <typename T, typename Property> struct static_require_trait<T, Property, - typename enable_if< - has_static_require<typename decay<T>::type, - typename decay<Property>::type>::value - >::type> + enable_if_t< + has_static_require<decay_t<T>, + decay_t<Property>>::value + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; }; #endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -#endif // defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT) - } // namespace detail namespace traits { diff --git a/3rdparty/asio/include/asio/traits/static_require_concept.hpp b/3rdparty/asio/include/asio/traits/static_require_concept.hpp index d35287d4db4..6861f46aa0d 100644 --- a/3rdparty/asio/include/asio/traits/static_require_concept.hpp +++ b/3rdparty/asio/include/asio/traits/static_require_concept.hpp @@ -2,7 +2,7 @@ // traits/static_require_concept.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,11 +19,7 @@ #include "asio/detail/type_traits.hpp" #include "asio/traits/static_query.hpp" -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) -# define ASIO_HAS_DEDUCED_STATIC_REQUIRE_CONCEPT_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) +#define ASIO_HAS_DEDUCED_STATIC_REQUIRE_CONCEPT_TRAIT 1 #include "asio/detail/push_options.hpp" @@ -41,33 +37,31 @@ namespace detail { struct no_static_require_concept { - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); + static constexpr bool is_valid = false; }; template <typename T, typename Property, typename = void> struct static_require_concept_trait : - conditional< - is_same<T, typename decay<T>::type>::value - && is_same<Property, typename decay<Property>::type>::value, + conditional_t< + is_same<T, decay_t<T>>::value + && is_same<Property, decay_t<Property>>::value, no_static_require_concept, traits::static_require_concept< - typename decay<T>::type, - typename decay<Property>::type> - >::type + decay_t<T>, + decay_t<Property>> + > { }; -#if defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_CONCEPT_TRAIT) - #if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) template <typename T, typename Property> struct static_require_concept_trait<T, Property, - typename enable_if< - decay<Property>::type::value() == traits::static_query<T, Property>::value() - >::type> + enable_if_t< + decay_t<Property>::value() == traits::static_query<T, Property>::value() + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; }; #else // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) @@ -76,32 +70,30 @@ false_type static_require_concept_test(...); template <typename T, typename Property> true_type static_require_concept_test(T*, Property*, - typename enable_if< + enable_if_t< Property::value() == traits::static_query<T, Property>::value() - >::type* = 0); + >* = 0); template <typename T, typename Property> struct has_static_require_concept { - ASIO_STATIC_CONSTEXPR(bool, value = + static constexpr bool value = decltype((static_require_concept_test)( - static_cast<T*>(0), static_cast<Property*>(0)))::value); + static_cast<T*>(0), static_cast<Property*>(0)))::value; }; template <typename T, typename Property> struct static_require_concept_trait<T, Property, - typename enable_if< - has_static_require_concept<typename decay<T>::type, - typename decay<Property>::type>::value - >::type> + enable_if_t< + has_static_require_concept<decay_t<T>, + decay_t<Property>>::value + >> { - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); + static constexpr bool is_valid = true; }; #endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -#endif // defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_CONCEPT_TRAIT) - } // namespace detail namespace traits { diff --git a/3rdparty/asio/include/asio/traits/submit_free.hpp b/3rdparty/asio/include/asio/traits/submit_free.hpp deleted file mode 100644 index 1ea583e7109..00000000000 --- a/3rdparty/asio/include/asio/traits/submit_free.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// traits/submit_free.hpp -// ~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_SUBMIT_FREE_HPP -#define ASIO_TRAITS_SUBMIT_FREE_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_SUBMIT_FREE_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename S, typename R, typename = void> -struct submit_free_default; - -template <typename S, typename R, typename = void> -struct submit_free; - -} // namespace traits -namespace detail { - -struct no_submit_free -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_SUBMIT_FREE_TRAIT) - -template <typename S, typename R, typename = void> -struct submit_free_trait : no_submit_free -{ -}; - -template <typename S, typename R> -struct submit_free_trait<S, R, - typename void_type< - decltype(submit(declval<S>(), declval<R>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype( - submit(declval<S>(), declval<R>())); - - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - submit(declval<S>(), declval<R>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_SUBMIT_FREE_TRAIT) - -template <typename S, typename R, typename = void> -struct submit_free_trait : - conditional< - is_same<S, typename remove_reference<S>::type>::value - && is_same<R, typename decay<R>::type>::value, - typename conditional< - is_same<S, typename add_const<S>::type>::value, - no_submit_free, - traits::submit_free<typename add_const<S>::type, R> - >::type, - traits::submit_free< - typename remove_reference<S>::type, - typename decay<R>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_SUBMIT_FREE_TRAIT) - -} // namespace detail -namespace traits { - -template <typename S, typename R, typename> -struct submit_free_default : - detail::submit_free_trait<S, R> -{ -}; - -template <typename S, typename R, typename> -struct submit_free : - submit_free_default<S, R> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_SUBMIT_FREE_HPP diff --git a/3rdparty/asio/include/asio/traits/submit_member.hpp b/3rdparty/asio/include/asio/traits/submit_member.hpp deleted file mode 100644 index 8aa42a02778..00000000000 --- a/3rdparty/asio/include/asio/traits/submit_member.hpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// traits/submit_member.hpp -// ~~~~~~~~~~~~~~~~~~~~~~~~ -// -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) -// -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -// - -#ifndef ASIO_TRAITS_SUBMIT_MEMBER_HPP -#define ASIO_TRAITS_SUBMIT_MEMBER_HPP - -#if defined(_MSC_VER) && (_MSC_VER >= 1200) -# pragma once -#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) - -#include "asio/detail/config.hpp" -#include "asio/detail/type_traits.hpp" - -#if defined(ASIO_HAS_DECLTYPE) \ - && defined(ASIO_HAS_NOEXCEPT) \ - && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) -# define ASIO_HAS_DEDUCED_SUBMIT_MEMBER_TRAIT 1 -#endif // defined(ASIO_HAS_DECLTYPE) - // && defined(ASIO_HAS_NOEXCEPT) - // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) - -#include "asio/detail/push_options.hpp" - -namespace asio { -namespace traits { - -template <typename S, typename R, typename = void> -struct submit_member_default; - -template <typename S, typename R, typename = void> -struct submit_member; - -} // namespace traits -namespace detail { - -struct no_submit_member -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = false); - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); -}; - -#if defined(ASIO_HAS_DEDUCED_SUBMIT_MEMBER_TRAIT) - -template <typename S, typename R, typename = void> -struct submit_member_trait : no_submit_member -{ -}; - -template <typename S, typename R> -struct submit_member_trait<S, R, - typename void_type< - decltype(declval<S>().submit(declval<R>())) - >::type> -{ - ASIO_STATIC_CONSTEXPR(bool, is_valid = true); - - using result_type = decltype( - declval<S>().submit(declval<R>())); - - ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( - declval<S>().submit(declval<R>()))); -}; - -#else // defined(ASIO_HAS_DEDUCED_SUBMIT_MEMBER_TRAIT) - -template <typename S, typename R, typename = void> -struct submit_member_trait : - conditional< - is_same<S, typename remove_reference<S>::type>::value - && is_same<R, typename decay<R>::type>::value, - typename conditional< - is_same<S, typename add_const<S>::type>::value, - no_submit_member, - traits::submit_member<typename add_const<S>::type, R> - >::type, - traits::submit_member< - typename remove_reference<S>::type, - typename decay<R>::type> - >::type -{ -}; - -#endif // defined(ASIO_HAS_DEDUCED_SUBMIT_MEMBER_TRAIT) - -} // namespace detail -namespace traits { - -template <typename S, typename R, typename> -struct submit_member_default : - detail::submit_member_trait<S, R> -{ -}; - -template <typename S, typename R, typename> -struct submit_member : - submit_member_default<S, R> -{ -}; - -} // namespace traits -} // namespace asio - -#include "asio/detail/pop_options.hpp" - -#endif // ASIO_TRAITS_SUBMIT_MEMBER_HPP diff --git a/3rdparty/asio/include/asio/ts/buffer.hpp b/3rdparty/asio/include/asio/ts/buffer.hpp index 9c16febc79c..6c74a50ca66 100644 --- a/3rdparty/asio/include/asio/ts/buffer.hpp +++ b/3rdparty/asio/include/asio/ts/buffer.hpp @@ -2,7 +2,7 @@ // ts/buffer.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ts/executor.hpp b/3rdparty/asio/include/asio/ts/executor.hpp index 66c318d3824..df28bbf44bb 100644 --- a/3rdparty/asio/include/asio/ts/executor.hpp +++ b/3rdparty/asio/include/asio/ts/executor.hpp @@ -2,7 +2,7 @@ // ts/executor.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ts/internet.hpp b/3rdparty/asio/include/asio/ts/internet.hpp index a2a3212968d..eb2c35cd628 100644 --- a/3rdparty/asio/include/asio/ts/internet.hpp +++ b/3rdparty/asio/include/asio/ts/internet.hpp @@ -2,7 +2,7 @@ // ts/internet.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ts/io_context.hpp b/3rdparty/asio/include/asio/ts/io_context.hpp index 7ce08f56727..c688f160e7a 100644 --- a/3rdparty/asio/include/asio/ts/io_context.hpp +++ b/3rdparty/asio/include/asio/ts/io_context.hpp @@ -2,7 +2,7 @@ // ts/io_context.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ts/net.hpp b/3rdparty/asio/include/asio/ts/net.hpp index c4a1b7352ec..f82113b930a 100644 --- a/3rdparty/asio/include/asio/ts/net.hpp +++ b/3rdparty/asio/include/asio/ts/net.hpp @@ -2,7 +2,7 @@ // ts/net.hpp // ~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ts/netfwd.hpp b/3rdparty/asio/include/asio/ts/netfwd.hpp index 1c5924d7ece..a575b6e497a 100644 --- a/3rdparty/asio/include/asio/ts/netfwd.hpp +++ b/3rdparty/asio/include/asio/ts/netfwd.hpp @@ -2,7 +2,7 @@ // ts/netfwd.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -16,10 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" - -#if defined(ASIO_HAS_CHRONO) -# include "asio/detail/chrono.hpp" -#endif // defined(ASIO_HAS_CHRONO) +#include "asio/detail/chrono.hpp" #if defined(ASIO_HAS_BOOST_DATE_TIME) # include "asio/detail/date_time_fwd.hpp" @@ -66,20 +63,9 @@ namespace execution { #if !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL) #define ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL -#if defined(ASIO_HAS_VARIADIC_TEMPLATES) - template <typename... SupportableProperties> class any_executor; -#else // defined(ASIO_HAS_VARIADIC_TEMPLATES) - -template <typename = void, typename = void, typename = void, - typename = void, typename = void, typename = void, - typename = void, typename = void, typename = void> -class any_executor; - -#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) - #endif // !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL) template <typename U> @@ -119,8 +105,6 @@ class basic_waitable_timer; #endif // !defined(ASIO_BASIC_WAITABLE_TIMER_FWD_DECL) -#if defined(ASIO_HAS_CHRONO) - typedef basic_waitable_timer<chrono::system_clock> system_timer; typedef basic_waitable_timer<chrono::steady_clock> steady_timer; @@ -128,8 +112,6 @@ typedef basic_waitable_timer<chrono::steady_clock> steady_timer; typedef basic_waitable_timer<chrono::high_resolution_clock> high_resolution_timer; -#endif // defined(ASIO_HAS_CHRONO) - #if !defined(ASIO_BASIC_SOCKET_FWD_DECL) #define ASIO_BASIC_SOCKET_FWD_DECL @@ -171,10 +153,10 @@ template <typename Protocol, #if defined(ASIO_HAS_BOOST_DATE_TIME) \ || defined(GENERATING_DOCUMENTATION) typename Clock = boost::posix_time::ptime, - typename WaitTraits = time_traits<Clock> > + typename WaitTraits = time_traits<Clock>> #else typename Clock = chrono::steady_clock, - typename WaitTraits = wait_traits<Clock> > + typename WaitTraits = wait_traits<Clock>> #endif class basic_socket_streambuf; @@ -188,10 +170,10 @@ template <typename Protocol, #if defined(ASIO_HAS_BOOST_DATE_TIME) \ || defined(GENERATING_DOCUMENTATION) typename Clock = boost::posix_time::ptime, - typename WaitTraits = time_traits<Clock> > + typename WaitTraits = time_traits<Clock>> #else typename Clock = chrono::steady_clock, - typename WaitTraits = wait_traits<Clock> > + typename WaitTraits = wait_traits<Clock>> #endif class basic_socket_iostream; diff --git a/3rdparty/asio/include/asio/ts/socket.hpp b/3rdparty/asio/include/asio/ts/socket.hpp index 62578fcb522..d54e0778264 100644 --- a/3rdparty/asio/include/asio/ts/socket.hpp +++ b/3rdparty/asio/include/asio/ts/socket.hpp @@ -2,7 +2,7 @@ // ts/socket.hpp // ~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/ts/timer.hpp b/3rdparty/asio/include/asio/ts/timer.hpp index 4d58373430f..3b3d6facf11 100644 --- a/3rdparty/asio/include/asio/ts/timer.hpp +++ b/3rdparty/asio/include/asio/ts/timer.hpp @@ -2,7 +2,7 @@ // ts/timer.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/unyield.hpp b/3rdparty/asio/include/asio/unyield.hpp index 983a000546e..f843d6137a2 100644 --- a/3rdparty/asio/include/asio/unyield.hpp +++ b/3rdparty/asio/include/asio/unyield.hpp @@ -2,7 +2,7 @@ // unyield.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/use_awaitable.hpp b/3rdparty/asio/include/asio/use_awaitable.hpp index 14e5ec1dc4f..6dd42f3d6e3 100644 --- a/3rdparty/asio/include/asio/use_awaitable.hpp +++ b/3rdparty/asio/include/asio/use_awaitable.hpp @@ -2,7 +2,7 @@ // use_awaitable.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -32,7 +32,7 @@ namespace asio { -/// A completion token that represents the currently executing coroutine. +/// A @ref completion_token that represents the currently executing coroutine. /** * The @c use_awaitable_t class, with its value @c use_awaitable, is used to * represent the currently executing coroutine. This completion token may be @@ -53,7 +53,7 @@ template <typename Executor = any_io_executor> struct use_awaitable_t { /// Default constructor. - ASIO_CONSTEXPR use_awaitable_t( + constexpr use_awaitable_t( #if defined(ASIO_ENABLE_HANDLER_TRACKING) # if defined(ASIO_HAS_SOURCE_LOCATION) detail::source_location location = detail::source_location::current() @@ -75,7 +75,7 @@ struct use_awaitable_t } /// Constructor used to specify file name, line, and function name. - ASIO_CONSTEXPR use_awaitable_t(const char* file_name, + constexpr use_awaitable_t(const char* file_name, int line, const char* function_name) #if defined(ASIO_ENABLE_HANDLER_TRACKING) : file_name_(file_name), @@ -101,13 +101,13 @@ struct use_awaitable_t /// Construct the adapted executor from the inner executor type. template <typename InnerExecutor1> executor_with_default(const InnerExecutor1& ex, - typename constraint< - conditional< + constraint_t< + conditional_t< !is_same<InnerExecutor1, executor_with_default>::value, is_convertible<InnerExecutor1, InnerExecutor>, false_type - >::type::value - >::type = 0) ASIO_NOEXCEPT + >::value + > = 0) noexcept : InnerExecutor(ex) { } @@ -115,25 +115,21 @@ struct use_awaitable_t /// Type alias to adapt an I/O object to use @c use_awaitable_t as its /// default completion token type. -#if defined(ASIO_HAS_ALIAS_TEMPLATES) \ - || defined(GENERATING_DOCUMENTATION) template <typename T> using as_default_on_t = typename T::template rebind_executor< - executor_with_default<typename T::executor_type> >::other; -#endif // defined(ASIO_HAS_ALIAS_TEMPLATES) - // || defined(GENERATING_DOCUMENTATION) + executor_with_default<typename T::executor_type>>::other; /// Function helper to adapt an I/O object to use @c use_awaitable_t as its /// default completion token type. template <typename T> - static typename decay<T>::type::template rebind_executor< - executor_with_default<typename decay<T>::type::executor_type> + static typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> >::other - as_default_on(ASIO_MOVE_ARG(T) object) + as_default_on(T&& object) { - return typename decay<T>::type::template rebind_executor< - executor_with_default<typename decay<T>::type::executor_type> - >::other(ASIO_MOVE_CAST(T)(object)); + return typename decay_t<T>::template rebind_executor< + executor_with_default<typename decay_t<T>::executor_type> + >::other(static_cast<T&&>(object)); } #if defined(ASIO_ENABLE_HANDLER_TRACKING) @@ -143,16 +139,15 @@ struct use_awaitable_t #endif // defined(ASIO_ENABLE_HANDLER_TRACKING) }; -/// A completion token object that represents the currently executing coroutine. +/// A @ref completion_token object that represents the currently executing +/// coroutine. /** * See the documentation for asio::use_awaitable_t for a usage example. */ #if defined(GENERATING_DOCUMENTATION) constexpr use_awaitable_t<> use_awaitable; -#elif defined(ASIO_HAS_CONSTEXPR) +#else constexpr use_awaitable_t<> use_awaitable(0, 0, 0); -#elif defined(ASIO_MSVC) -__declspec(selectany) use_awaitable_t<> use_awaitable(0, 0, 0); #endif } // namespace asio diff --git a/3rdparty/asio/include/asio/use_future.hpp b/3rdparty/asio/include/asio/use_future.hpp index dfef15c89ef..26f5ae1fed0 100644 --- a/3rdparty/asio/include/asio/use_future.hpp +++ b/3rdparty/asio/include/asio/use_future.hpp @@ -2,7 +2,7 @@ // use_future.hpp // ~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -37,12 +37,14 @@ class packaged_handler; } // namespace detail -/// Class used to specify that an asynchronous operation should return a future. +/// A @ref completion_token type that causes an asynchronous operation to return +/// a future. /** - * The use_future_t class is used to indicate that an asynchronous operation - * should return a std::future object. A use_future_t object may be passed as a - * handler to an asynchronous operation, typically using the special value @c - * asio::use_future. For example: + * The use_future_t class is a completion token type that is used to indicate + * that an asynchronous operation should return a std::future object. A + * use_future_t object may be passed as a completion token to an asynchronous + * operation, typically using the special value @c asio::use_future. For + * example: * * @code std::future<std::size_t> my_future * = my_socket.async_read_some(my_buffer, asio::use_future); @endcode @@ -52,7 +54,7 @@ class packaged_handler; * completes with an error_code indicating failure, it is converted into a * system_error and passed back to the caller via the future. */ -template <typename Allocator = std::allocator<void> > +template <typename Allocator = std::allocator<void>> class use_future_t { public: @@ -61,7 +63,7 @@ public: typedef Allocator allocator_type; /// Construct using default-constructed allocator. - ASIO_CONSTEXPR use_future_t() + constexpr use_future_t() { } @@ -114,16 +116,16 @@ public: #if defined(GENERATING_DOCUMENTATION) unspecified #else // defined(GENERATING_DOCUMENTATION) - detail::packaged_token<typename decay<Function>::type, Allocator> + detail::packaged_token<decay_t<Function>, Allocator> #endif // defined(GENERATING_DOCUMENTATION) - operator()(ASIO_MOVE_ARG(Function) f) const; + operator()(Function&& f) const; private: // Helper type to ensure that use_future can be constexpr default-constructed // even when std::allocator<void> can't be. struct std_allocator_void { - ASIO_CONSTEXPR std_allocator_void() + constexpr std_allocator_void() { } @@ -133,20 +135,17 @@ private: } }; - typename conditional< + conditional_t< is_same<std::allocator<void>, Allocator>::value, - std_allocator_void, Allocator>::type allocator_; + std_allocator_void, Allocator> allocator_; }; -/// A special value, similar to std::nothrow. +/// A @ref completion_token object that causes an asynchronous operation to +/// return a future. /** * See the documentation for asio::use_future_t for a usage example. */ -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr use_future_t<> use_future; -#elif defined(ASIO_MSVC) -__declspec(selectany) use_future_t<> use_future; -#endif } // namespace asio diff --git a/3rdparty/asio/include/asio/uses_executor.hpp b/3rdparty/asio/include/asio/uses_executor.hpp index 5232f6c203a..ff475cad4a1 100644 --- a/3rdparty/asio/include/asio/uses_executor.hpp +++ b/3rdparty/asio/include/asio/uses_executor.hpp @@ -2,7 +2,7 @@ // uses_executor.hpp // ~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -34,7 +34,7 @@ namespace asio { struct executor_arg_t { /// Constructor. - ASIO_CONSTEXPR executor_arg_t() ASIO_NOEXCEPT + constexpr executor_arg_t() noexcept { } }; @@ -45,11 +45,7 @@ struct executor_arg_t * See asio::executor_arg_t and asio::uses_executor * for more information. */ -#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION) constexpr executor_arg_t executor_arg; -#elif defined(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. diff --git a/3rdparty/asio/include/asio/version.hpp b/3rdparty/asio/include/asio/version.hpp index cb8bf03f5f4..c52fdd45b58 100644 --- a/3rdparty/asio/include/asio/version.hpp +++ b/3rdparty/asio/include/asio/version.hpp @@ -2,7 +2,7 @@ // version.hpp // ~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,6 +18,6 @@ // ASIO_VERSION % 100 is the sub-minor version // ASIO_VERSION / 100 % 1000 is the minor version // ASIO_VERSION / 100000 is the major version -#define ASIO_VERSION 102000 // 1.20.0 +#define ASIO_VERSION 103002 // 1.30.2 #endif // ASIO_VERSION_HPP diff --git a/3rdparty/asio/include/asio/wait_traits.hpp b/3rdparty/asio/include/asio/wait_traits.hpp index 152fcece073..5f5e876da66 100644 --- a/3rdparty/asio/include/asio/wait_traits.hpp +++ b/3rdparty/asio/include/asio/wait_traits.hpp @@ -2,7 +2,7 @@ // wait_traits.hpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/windows/basic_object_handle.hpp b/3rdparty/asio/include/asio/windows/basic_object_handle.hpp index f929e04e72c..bb10efc2a0a 100644 --- a/3rdparty/asio/include/asio/windows/basic_object_handle.hpp +++ b/3rdparty/asio/include/asio/windows/basic_object_handle.hpp @@ -2,7 +2,7 @@ // windows/basic_object_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying @@ -21,6 +21,7 @@ #if defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE) \ || defined(GENERATING_DOCUMENTATION) +#include <utility> #include "asio/any_io_executor.hpp" #include "asio/async_result.hpp" #include "asio/detail/io_object_impl.hpp" @@ -29,10 +30,6 @@ #include "asio/error.hpp" #include "asio/execution_context.hpp" -#if defined(ASIO_HAS_MOVE) -# include <utility> -#endif // defined(ASIO_HAS_MOVE) - #include "asio/detail/push_options.hpp" namespace asio { @@ -50,6 +47,9 @@ namespace windows { template <typename Executor = any_io_executor> class basic_object_handle { +private: + class initiate_async_wait; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -96,10 +96,10 @@ public: */ template <typename ExecutionContext> explicit basic_object_handle(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : impl_(0, 0, context) { } @@ -142,9 +142,9 @@ public: template <typename ExecutionContext> basic_object_handle(ExecutionContext& context, const native_handle_type& native_handle, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -152,7 +152,6 @@ public: asio::detail::throw_error(ec, "assign"); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct an object handle from another. /** * This constructor moves an object handle from one object to another. @@ -185,10 +184,55 @@ public: impl_ = std::move(other.impl_); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + // All handles have access to each other's implementations. + template <typename Executor1> + friend class basic_object_handle; + + /// Move-construct an object handle from a handle of another executor type. + /** + * This constructor moves an object handle from one object to another. + * + * @param other The other object handle object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_object_handle(const executor_type&) + * constructor. + */ + template<typename Executor1> + basic_object_handle(basic_object_handle<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign an object handle from a handle of another executor type. + /** + * This assignment operator moves an object handle from one object to another. + * + * @param other The other object handle object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_object_handle(const executor_type&) + * constructor. + */ + template<typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_object_handle& + > operator=(basic_object_handle<Executor1>&& other) + { + impl_ = std::move(other.impl_); + return *this; + } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + const executor_type& get_executor() noexcept { return impl_.get_executor(); } @@ -357,36 +401,42 @@ public: /// Start an asynchronous wait on the object handle. /** * This function is be used to initiate an asynchronous wait against the - * object handle. It always returns immediately. + * object handle. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. * - * @param handler The handler to be called when the object handle is set to - * the signalled state. Copies will be made of the handler as required. The - * function signature of the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the wait completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error // Result of operation. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). + * + * @par Completion Signature + * @code void(asio::error_code) @endcode */ template < ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code)) - WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler, - void (asio::error_code)) - async_wait( - ASIO_MOVE_ARG(WaitHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + WaitToken = default_completion_token_t<executor_type>> + auto async_wait( + WaitToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WaitToken, void (asio::error_code)>( + declval<initiate_async_wait>(), token)) { - return async_initiate<WaitHandler, void (asio::error_code)>( - initiate_async_wait(this), handler); + return async_initiate<WaitToken, void (asio::error_code)>( + initiate_async_wait(this), token); } private: // Disallow copying and assignment. - basic_object_handle(const basic_object_handle&) ASIO_DELETED; - basic_object_handle& operator=(const basic_object_handle&) ASIO_DELETED; + basic_object_handle(const basic_object_handle&) = delete; + basic_object_handle& operator=(const basic_object_handle&) = delete; class initiate_async_wait { @@ -398,13 +448,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WaitHandler> - void operator()(ASIO_MOVE_ARG(WaitHandler) handler) const + void operator()(WaitHandler&& handler) const { // If you get an error on the following line it means that your handler // does not meet the documented type requirements for a WaitHandler. diff --git a/3rdparty/asio/include/asio/windows/basic_overlapped_handle.hpp b/3rdparty/asio/include/asio/windows/basic_overlapped_handle.hpp index 29154b036a3..8b8475b0006 100644 --- a/3rdparty/asio/include/asio/windows/basic_overlapped_handle.hpp +++ b/3rdparty/asio/include/asio/windows/basic_overlapped_handle.hpp @@ -2,7 +2,7 @@ // windows/basic_overlapped_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -22,6 +22,7 @@ || defined(GENERATING_DOCUMENTATION) #include <cstddef> +#include <utility> #include "asio/any_io_executor.hpp" #include "asio/async_result.hpp" #include "asio/detail/io_object_impl.hpp" @@ -30,10 +31,6 @@ #include "asio/error.hpp" #include "asio/execution_context.hpp" -#if defined(ASIO_HAS_MOVE) -# include <utility> -#endif // defined(ASIO_HAS_MOVE) - #include "asio/detail/push_options.hpp" namespace asio { @@ -99,10 +96,10 @@ public: */ template <typename ExecutionContext> explicit basic_overlapped_handle(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : impl_(0, 0, context) { } @@ -145,9 +142,9 @@ public: template <typename ExecutionContext> basic_overlapped_handle(ExecutionContext& context, const native_handle_type& native_handle, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : impl_(0, 0, context) { asio::error_code ec; @@ -155,7 +152,6 @@ public: asio::detail::throw_error(ec, "assign"); } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct an overlapped handle from another. /** * This constructor moves a handle from one object to another. @@ -188,10 +184,56 @@ public: impl_ = std::move(other.impl_); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + // All overlapped handles have access to each other's implementations. + template <typename Executor1> + friend class basic_overlapped_handle; + + /// Move-construct an overlapped handle from a handle of another executor + /// type. + /** + * This constructor moves a handle from one object to another. + * + * @param other The other overlapped handle object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c overlapped_handle(const executor_type&) + * constructor. + */ + template<typename Executor1> + basic_overlapped_handle(basic_overlapped_handle<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : impl_(std::move(other.impl_)) + { + } + + /// Move-assign an overlapped handle from a handle of another executor type. + /** + * This assignment operator moves a handle from one object to another. + * + * @param other The other overlapped handle object from which the move will + * occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c overlapped_handle(const executor_type&) + * constructor. + */ + template<typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_overlapped_handle& + > operator=(basic_overlapped_handle<Executor1>&& other) + { + impl_ = std::move(other.impl_); + return *this; + } /// Get the executor associated with the object. - executor_type get_executor() ASIO_NOEXCEPT + const executor_type& get_executor() noexcept { return impl_.get_executor(); } @@ -289,6 +331,58 @@ public: ASIO_SYNC_OP_VOID_RETURN(ec); } + /// Release ownership of the underlying native handle. + /** + * This function causes all outstanding asynchronous operations to finish + * immediately, and the handlers for cancelled operations will be passed the + * asio::error::operation_aborted error. Ownership of the native handle + * is then transferred to the caller. + * + * @throws asio::system_error Thrown on failure. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with asio::error::operation_not_supported on + * these platforms. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release() + { + asio::error_code ec; + native_handle_type s = impl_.get_service().release( + impl_.get_implementation(), ec); + asio::detail::throw_error(ec, "release"); + return s; + } + + /// Release ownership of the underlying native handle. + /** + * This function causes all outstanding asynchronous operations to finish + * immediately, and the handlers for cancelled operations will be passed the + * asio::error::operation_aborted error. Ownership of the native handle + * is then transferred to the caller. + * + * @param ec Set to indicate what error occurred, if any. + * + * @note This function is unsupported on Windows versions prior to Windows + * 8.1, and will fail with asio::error::operation_not_supported on + * these platforms. + */ +#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \ + && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603) + __declspec(deprecated("This function always fails with " + "operation_not_supported when used on Windows versions " + "prior to Windows 8.1.")) +#endif + native_handle_type release(asio::error_code& ec) + { + return impl_.get_service().release(impl_.get_implementation(), ec); + } + /// Get the native handle representation. /** * This function may be used to obtain the underlying representation of the @@ -344,9 +438,9 @@ protected: private: // Disallow copying and assignment. - basic_overlapped_handle(const basic_overlapped_handle&) ASIO_DELETED; + basic_overlapped_handle(const basic_overlapped_handle&) = delete; basic_overlapped_handle& operator=( - const basic_overlapped_handle&) ASIO_DELETED; + const basic_overlapped_handle&) = delete; }; } // namespace windows diff --git a/3rdparty/asio/include/asio/windows/basic_random_access_handle.hpp b/3rdparty/asio/include/asio/windows/basic_random_access_handle.hpp index ab7a0a5b612..e66e943c6b5 100644 --- a/3rdparty/asio/include/asio/windows/basic_random_access_handle.hpp +++ b/3rdparty/asio/include/asio/windows/basic_random_access_handle.hpp @@ -2,7 +2,7 @@ // windows/basic_random_access_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -39,6 +39,10 @@ template <typename Executor = any_io_executor> class basic_random_access_handle : public basic_overlapped_handle<Executor> { +private: + class initiate_async_write_some_at; + class initiate_async_read_some_at; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -75,8 +79,8 @@ 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 or assigned before data can be sent or received - * on it. + * handle needs to be opened or assigned before data can be written to or read + * from it. * * @param context An execution context which provides the I/O executor that * the random-access handle will use, by default, to dispatch handlers for any @@ -84,10 +88,10 @@ public: */ template <typename ExecutionContext> explicit basic_random_access_handle(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : basic_overlapped_handle<Executor>(context) { } @@ -127,14 +131,13 @@ public: template <typename ExecutionContext> basic_random_access_handle(ExecutionContext& context, const native_handle_type& handle, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_overlapped_handle<Executor>(context, handle) { } -#if defined(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. @@ -168,7 +171,51 @@ public: basic_overlapped_handle<Executor>::operator=(std::move(other)); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Move-construct a random-access handle from a handle of another executor + /// type. + /** + * This constructor moves a random-access handle from one object to another. + * + * @param other The other random-access handle object from which the + * move will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_random_access_handle(const executor_type&) + * constructor. + */ + template<typename Executor1> + basic_random_access_handle(basic_random_access_handle<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_overlapped_handle<Executor>(std::move(other)) + { + } + + /// Move-assign a random-access handle from a handle of another executor + /// type. + /** + * This assignment operator moves a random-access handle from one object to + * another. + * + * @param other The other random-access handle object from which the + * move will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_random_access_handle(const executor_type&) + * constructor. + */ + template<typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_random_access_handle& + > operator=(basic_random_access_handle<Executor1>&& other) + { + basic_overlapped_handle<Executor>::operator=(std::move(other)); + return *this; + } /// Write some data to the handle at the specified offset. /** @@ -239,27 +286,33 @@ public: /// Start an asynchronous write at the specified offset. /** * This function is used to asynchronously write data to the random-access - * handle. The function call always returns immediately. + * handle. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param offset The offset at which the data will be written. * * @param buffers One or more data buffers to be written to the handle. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. + * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write_at function if you need to ensure that * all data is written before the asynchronous operation completes. @@ -285,18 +338,17 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_write_some_at(uint64_t offset, - const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_write_some_at(uint64_t offset, const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_write_some_at>(), token, offset, buffers)) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_write_some_at(this), handler, offset, buffers); + initiate_async_write_some_at(this), token, offset, buffers); } /// Read some data from the handle at the specified offset. @@ -370,27 +422,33 @@ public: /// Start an asynchronous read at the specified offset. /** * This function is used to asynchronously read data from the random-access - * handle. The function call always returns immediately. + * handle. It is an initiating function for an @ref asynchronous_operation, + * and always returns immediately. * * @param offset The offset at which the data will be read. * * @param buffers One or more buffers into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. + * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read_at function if you need to ensure that * the requested amount of data is read before the asynchronous operation @@ -417,18 +475,17 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_read_some_at(uint64_t offset, - const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_read_some_at(uint64_t offset, const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_read_some_at>(), token, offset, buffers)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_read_some_at(this), handler, offset, buffers); + initiate_async_read_some_at(this), token, offset, buffers); } private: @@ -442,13 +499,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, uint64_t offset, const ConstBufferSequence& buffers) const { // If you get an error on the following line it means that your handler @@ -475,13 +532,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, uint64_t offset, const MutableBufferSequence& buffers) const { // If you get an error on the following line it means that your handler diff --git a/3rdparty/asio/include/asio/windows/basic_stream_handle.hpp b/3rdparty/asio/include/asio/windows/basic_stream_handle.hpp index 1a35224a234..0331d9dfa03 100644 --- a/3rdparty/asio/include/asio/windows/basic_stream_handle.hpp +++ b/3rdparty/asio/include/asio/windows/basic_stream_handle.hpp @@ -2,7 +2,7 @@ // windows/basic_stream_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -42,6 +42,10 @@ template <typename Executor = any_io_executor> class basic_stream_handle : public basic_overlapped_handle<Executor> { +private: + class initiate_async_write_some; + class initiate_async_read_some; + public: /// The type of the executor associated with the object. typedef Executor executor_type; @@ -78,7 +82,8 @@ public: /// Construct a stream handle without opening it. /** * This constructor creates a stream handle without opening it. The handle - * needs to be opened or assigned before data can be sent or received on it. + * needs to be opened or assigned before data can be written to or read from + * it. * * @param context An execution context which provides the I/O executor that * the stream handle will use, by default, to dispatch handlers for any @@ -86,10 +91,10 @@ public: */ template <typename ExecutionContext> explicit basic_stream_handle(ExecutionContext& context, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value, defaulted_constraint - >::type = defaulted_constraint()) + > = defaulted_constraint()) : basic_overlapped_handle<Executor>(context) { } @@ -128,14 +133,13 @@ public: template <typename ExecutionContext> basic_stream_handle(ExecutionContext& context, const native_handle_type& handle, - typename constraint< + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) : basic_overlapped_handle<Executor>(context, handle) { } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) /// Move-construct a stream handle from another. /** * This constructor moves a stream handle from one object to another. @@ -168,7 +172,48 @@ public: basic_overlapped_handle<Executor>::operator=(std::move(other)); return *this; } -#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) + + /// Move-construct a stream handle from a handle of another executor type. + /** + * This constructor moves a stream handle from one object to another. + * + * @param other The other stream handle object from which the move + * will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_handle(const executor_type&) + * constructor. + */ + template<typename Executor1> + basic_stream_handle(basic_stream_handle<Executor1>&& other, + constraint_t< + is_convertible<Executor1, Executor>::value, + defaulted_constraint + > = defaulted_constraint()) + : basic_overlapped_handle<Executor>(std::move(other)) + { + } + + /// Move-assign a stream handle from a handle of another executor type. + /** + * This assignment operator moves a stream handle from one object to + * another. + * + * @param other The other stream handle object from which the move will occur. + * + * @note Following the move, the moved-from object is in the same state as if + * constructed using the @c basic_stream_handle(const executor_type&) + * constructor. + */ + template<typename Executor1> + constraint_t< + is_convertible<Executor1, Executor>::value, + basic_stream_handle& + > operator=(basic_stream_handle<Executor1>&& other) + { + basic_overlapped_handle<Executor>::operator=(std::move(other)); + return *this; + } /// Write some data to the handle. /** @@ -234,25 +279,31 @@ public: /// Start an asynchronous write. /** * This function is used to asynchronously write data to the stream handle. - * The function call always returns immediately. + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. * * @param buffers One or more data buffers to be written to the handle. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes written. + * std::size_t bytes_transferred // Number of bytes written. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The write operation may not transmit all of the data to the peer. * Consider using the @ref async_write function if you need to ensure that all * data is written before the asynchronous operation completes. @@ -278,17 +329,17 @@ public: */ template <typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) - async_write_some(const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) WriteToken = default_completion_token_t<executor_type>> + auto async_write_some(const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_write_some>(), token, buffers)) { - return async_initiate<WriteHandler, + return async_initiate<WriteToken, void (asio::error_code, std::size_t)>( - initiate_async_write_some(this), handler, buffers); + initiate_async_write_some(this), token, buffers); } /// Read some data from the handle. @@ -357,25 +408,31 @@ public: /// Start an asynchronous read. /** * This function is used to asynchronously read data from the stream handle. - * The function call always returns immediately. + * It is an initiating function for an @ref asynchronous_operation, and always + * returns immediately. * * @param buffers One or more buffers into which the data will be read. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the read operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the read completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * const asio::error_code& error, // Result of operation. - * std::size_t bytes_transferred // Number of bytes read. + * std::size_t bytes_transferred // Number of bytes read. * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @note The read operation may not read all of the requested number of bytes. * Consider using the @ref async_read function if you need to ensure that the * requested amount of data is read before the asynchronous operation @@ -402,17 +459,17 @@ public: */ template <typename MutableBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) ReadHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)> - ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler, - void (asio::error_code, std::size_t)) - async_read_some(const MutableBufferSequence& buffers, - ASIO_MOVE_ARG(ReadHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN(executor_type)) + std::size_t)) ReadToken = default_completion_token_t<executor_type>> + auto async_read_some(const MutableBufferSequence& buffers, + ReadToken&& token = default_completion_token_t<executor_type>()) + -> decltype( + async_initiate<ReadToken, + void (asio::error_code, std::size_t)>( + declval<initiate_async_read_some>(), token, buffers)) { - return async_initiate<ReadHandler, + return async_initiate<ReadToken, void (asio::error_code, std::size_t)>( - initiate_async_read_some(this), handler, buffers); + initiate_async_read_some(this), token, buffers); } private: @@ -426,13 +483,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename WriteHandler, typename ConstBufferSequence> - void operator()(ASIO_MOVE_ARG(WriteHandler) handler, + void operator()(WriteHandler&& handler, const ConstBufferSequence& buffers) const { // If you get an error on the following line it means that your handler @@ -459,13 +516,13 @@ private: { } - executor_type get_executor() const ASIO_NOEXCEPT + const executor_type& get_executor() const noexcept { return self_->get_executor(); } template <typename ReadHandler, typename MutableBufferSequence> - void operator()(ASIO_MOVE_ARG(ReadHandler) handler, + void operator()(ReadHandler&& handler, const MutableBufferSequence& buffers) const { // If you get an error on the following line it means that your handler diff --git a/3rdparty/asio/include/asio/windows/object_handle.hpp b/3rdparty/asio/include/asio/windows/object_handle.hpp index 14d6801c534..243d9455ce2 100644 --- a/3rdparty/asio/include/asio/windows/object_handle.hpp +++ b/3rdparty/asio/include/asio/windows/object_handle.hpp @@ -2,7 +2,7 @@ // windows/object_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // Copyright (c) 2011 Boris Schaeling (boris@highscore.de) // // Distributed under the Boost Software License, Version 1.0. (See accompanying diff --git a/3rdparty/asio/include/asio/windows/overlapped_handle.hpp b/3rdparty/asio/include/asio/windows/overlapped_handle.hpp index b2592b92052..fc12865b48c 100644 --- a/3rdparty/asio/include/asio/windows/overlapped_handle.hpp +++ b/3rdparty/asio/include/asio/windows/overlapped_handle.hpp @@ -2,7 +2,7 @@ // windows/overlapped_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/windows/overlapped_ptr.hpp b/3rdparty/asio/include/asio/windows/overlapped_ptr.hpp index 5ac2ab1a5e7..e1e6f8c841f 100644 --- a/3rdparty/asio/include/asio/windows/overlapped_ptr.hpp +++ b/3rdparty/asio/include/asio/windows/overlapped_ptr.hpp @@ -2,7 +2,7 @@ // windows/overlapped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -51,23 +51,23 @@ public: /// Construct an overlapped_ptr to contain the specified handler. template <typename ExecutionContext, typename Handler> explicit overlapped_ptr(ExecutionContext& context, - ASIO_MOVE_ARG(Handler) handler, - typename constraint< + Handler&& handler, + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) - : impl_(context.get_executor(), ASIO_MOVE_CAST(Handler)(handler)) + > = 0) + : impl_(context.get_executor(), static_cast<Handler&&>(handler)) { } /// Construct an overlapped_ptr to contain the specified handler. template <typename Executor, typename Handler> explicit overlapped_ptr(const Executor& ex, - ASIO_MOVE_ARG(Handler) handler, - typename constraint< + Handler&& handler, + constraint_t< execution::is_executor<Executor>::value || is_executor<Executor>::value - >::type = 0) - : impl_(ex, ASIO_MOVE_CAST(Handler)(handler)) + > = 0) + : impl_(ex, static_cast<Handler&&>(handler)) { } @@ -85,24 +85,24 @@ public: /// Reset to contain the specified handler, freeing any current OVERLAPPED /// object. template <typename ExecutionContext, typename Handler> - void reset(ExecutionContext& context, ASIO_MOVE_ARG(Handler) handler, - typename constraint< + void reset(ExecutionContext& context, Handler&& handler, + constraint_t< is_convertible<ExecutionContext&, execution_context&>::value - >::type = 0) + > = 0) { - impl_.reset(context.get_executor(), ASIO_MOVE_CAST(Handler)(handler)); + impl_.reset(context.get_executor(), static_cast<Handler&&>(handler)); } /// Reset to contain the specified handler, freeing any current OVERLAPPED /// object. template <typename Executor, typename Handler> - void reset(const Executor& ex, ASIO_MOVE_ARG(Handler) handler, - typename constraint< + void reset(const Executor& ex, Handler&& handler, + constraint_t< execution::is_executor<Executor>::value || is_executor<Executor>::value - >::type = 0) + > = 0) { - impl_.reset(ex, ASIO_MOVE_CAST(Handler)(handler)); + impl_.reset(ex, static_cast<Handler&&>(handler)); } /// Get the contained OVERLAPPED object. diff --git a/3rdparty/asio/include/asio/windows/random_access_handle.hpp b/3rdparty/asio/include/asio/windows/random_access_handle.hpp index aff4529423f..88dfa36ecdd 100644 --- a/3rdparty/asio/include/asio/windows/random_access_handle.hpp +++ b/3rdparty/asio/include/asio/windows/random_access_handle.hpp @@ -2,7 +2,7 @@ // windows/random_access_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/windows/stream_handle.hpp b/3rdparty/asio/include/asio/windows/stream_handle.hpp index fabf8862433..4b88b8cb699 100644 --- a/3rdparty/asio/include/asio/windows/stream_handle.hpp +++ b/3rdparty/asio/include/asio/windows/stream_handle.hpp @@ -2,7 +2,7 @@ // windows/stream_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/3rdparty/asio/include/asio/writable_pipe.hpp b/3rdparty/asio/include/asio/writable_pipe.hpp new file mode 100644 index 00000000000..27f408a4956 --- /dev/null +++ b/3rdparty/asio/include/asio/writable_pipe.hpp @@ -0,0 +1,35 @@ +// +// writable_pipe.hpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef ASIO_WRITABLE_PIPE_HPP +#define ASIO_WRITABLE_PIPE_HPP + +#if defined(_MSC_VER) && (_MSC_VER >= 1200) +# pragma once +#endif // defined(_MSC_VER) && (_MSC_VER >= 1200) + +#include "asio/detail/config.hpp" + +#if defined(ASIO_HAS_PIPE) \ + || defined(GENERATING_DOCUMENTATION) + +#include "asio/basic_writable_pipe.hpp" + +namespace asio { + +/// Typedef for the typical usage of a writable pipe. +typedef basic_writable_pipe<> writable_pipe; + +} // namespace asio + +#endif // defined(ASIO_HAS_PIPE) + // || defined(GENERATING_DOCUMENTATION) + +#endif // ASIO_WRITABLE_PIPE_HPP diff --git a/3rdparty/asio/include/asio/write.hpp b/3rdparty/asio/include/asio/write.hpp index df82e06aec1..ca3f002c025 100644 --- a/3rdparty/asio/include/asio/write.hpp +++ b/3rdparty/asio/include/asio/write.hpp @@ -2,7 +2,7 @@ // write.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -19,6 +19,7 @@ #include <cstddef> #include "asio/async_result.hpp" #include "asio/buffer.hpp" +#include "asio/completion_condition.hpp" #include "asio/error.hpp" #if !defined(ASIO_NO_EXTENSIONS) @@ -28,6 +29,15 @@ #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { + +template <typename> class initiate_async_write; +#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) +template <typename> class initiate_async_write_dynbuf_v1; +#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1) +template <typename> class initiate_async_write_dynbuf_v2; + +} // namespace detail /** * @defgroup write asio::write @@ -75,9 +85,9 @@ namespace asio { */ template <typename SyncWriteStream, typename ConstBufferSequence> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, - typename constraint< + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type = 0); + > = 0); /// Write all of the supplied data to a stream before returning. /** @@ -118,9 +128,9 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, template <typename SyncWriteStream, typename ConstBufferSequence> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, asio::error_code& ec, - typename constraint< + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type = 0); + > = 0); /// Write a certain amount of data to a stream before returning. /** @@ -172,9 +182,9 @@ template <typename SyncWriteStream, typename ConstBufferSequence, typename CompletionCondition> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, CompletionCondition completion_condition, - typename constraint< + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type = 0); + > = 0); /// Write a certain amount of data to a stream before returning. /** @@ -219,9 +229,9 @@ template <typename SyncWriteStream, typename ConstBufferSequence, typename CompletionCondition> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type = 0); + > = 0); #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -254,13 +264,13 @@ std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers, */ template <typename SyncWriteStream, typename DynamicBuffer_v1> std::size_t write(SyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + DynamicBuffer_v1&& buffers, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); /// Write all of the supplied data to a stream before returning. /** @@ -291,14 +301,14 @@ std::size_t write(SyncWriteStream& s, */ template <typename SyncWriteStream, typename DynamicBuffer_v1> std::size_t write(SyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); /// Write a certain amount of data to a stream before returning. /** @@ -339,14 +349,14 @@ std::size_t write(SyncWriteStream& s, template <typename SyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t write(SyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, CompletionCondition completion_condition, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); /// Write a certain amount of data to a stream before returning. /** @@ -388,14 +398,14 @@ std::size_t write(SyncWriteStream& s, template <typename SyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition> std::size_t write(SyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, + DynamicBuffer_v1&& buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM) @@ -573,9 +583,9 @@ std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b, */ template <typename SyncWriteStream, typename DynamicBuffer_v2> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /// Write all of the supplied data to a stream before returning. /** @@ -607,9 +617,9 @@ std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, template <typename SyncWriteStream, typename DynamicBuffer_v2> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /// Write a certain amount of data to a stream before returning. /** @@ -651,9 +661,9 @@ template <typename SyncWriteStream, typename DynamicBuffer_v2, typename CompletionCondition> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /// Write a certain amount of data to a stream before returning. /** @@ -696,9 +706,9 @@ template <typename SyncWriteStream, typename DynamicBuffer_v2, typename CompletionCondition> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, asio::error_code& ec, - typename constraint< + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0); /*@}*/ /** @@ -713,9 +723,9 @@ std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, /// stream. /** * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * data to a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied buffers has been written. That is, the * bytes transferred is equal to the sum of the buffer sizes. @@ -734,24 +744,29 @@ std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, * @param buffers One or more buffers containing the data to be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To write a single data buffer use the @ref buffer function as follows: * @code @@ -774,26 +789,27 @@ std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers, */ template <typename AsyncWriteStream, typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncWriteStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncWriteStream::executor_type), - typename constraint< + std::size_t)) WriteToken + = default_completion_token_t<typename AsyncWriteStream::executor_type>> +auto async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, + WriteToken&& token + = default_completion_token_t<typename AsyncWriteStream::executor_type>(), + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write<AsyncWriteStream>>(), + token, buffers, transfer_all())); /// Start an asynchronous operation to write a certain amount of data to a /// stream. /** * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * data to a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied buffers has been written. That is, the * bytes transferred is equal to the sum of the buffer sizes. @@ -812,7 +828,7 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, * @param buffers One or more buffers containing the data to be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object @@ -828,22 +844,27 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, * non-zero return value indicates the maximum number of bytes to be written on * the next call to the stream's async_write_some function. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To write a single data buffer use the @ref buffer function as follows: * @code asio::async_write(s, @@ -868,15 +889,19 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, template <typename AsyncWriteStream, typename ConstBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, + std::size_t)) WriteToken> +auto async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler, - typename constraint< + WriteToken&& token, + constraint_t< is_const_buffer_sequence<ConstBufferSequence>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write<AsyncWriteStream>>(), + token, buffers, + static_cast<CompletionCondition&&>(completion_condition))); #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -884,9 +909,9 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, /// stream. /** * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * data to a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied dynamic buffer sequence has been written. * @@ -904,25 +929,30 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, * @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: + * that they remain valid until the completion handler is called. Successfully + * written data is automatically consumed from the buffers. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -936,30 +966,31 @@ async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers, */ template <typename AsyncWriteStream, typename DynamicBuffer_v1, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncWriteStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncWriteStream::executor_type), - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + std::size_t)) WriteToken + = default_completion_token_t<typename AsyncWriteStream::executor_type>> +auto async_write(AsyncWriteStream& s, DynamicBuffer_v1&& buffers, + WriteToken&& token + = default_completion_token_t<typename AsyncWriteStream::executor_type>(), + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), + transfer_all())); /// Start an asynchronous operation to write a certain amount of data to a /// stream. /** * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * data to a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied dynamic buffer sequence has been written. * @@ -977,8 +1008,8 @@ async_write(AsyncWriteStream& s, * @param buffers The dynamic buffer sequence from which data will be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. Successfully written - * data is automatically consumed from the buffers. + * that they remain valid until the completion handler is called. Successfully + * written data is automatically consumed from the buffers. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object @@ -994,22 +1025,27 @@ async_write(AsyncWriteStream& s, * non-zero return value indicates the maximum number of bytes to be written on * the next call to the stream's async_write_some function. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -1024,19 +1060,21 @@ async_write(AsyncWriteStream& s, template <typename AsyncWriteStream, typename DynamicBuffer_v1, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, - ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler, - typename constraint< - is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0, - typename constraint< - !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value - >::type = 0); + std::size_t)) WriteToken> +auto async_write(AsyncWriteStream& s, DynamicBuffer_v1&& buffers, + CompletionCondition completion_condition, WriteToken&& token, + constraint_t< + is_dynamic_buffer_v1<decay_t<DynamicBuffer_v1>>::value + > = 0, + constraint_t< + !is_dynamic_buffer_v2<decay_t<DynamicBuffer_v1>>::value + > = 0) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(), + token, static_cast<DynamicBuffer_v1&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition))); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM) @@ -1045,9 +1083,9 @@ async_write(AsyncWriteStream& s, /// stream. /** * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * data to a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied basic_streambuf has been written. * @@ -1064,24 +1102,29 @@ async_write(AsyncWriteStream& s, * * @param b A basic_streambuf object from which data will be written. Ownership * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. + * remains valid until the completion handler is called. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -1095,23 +1138,24 @@ async_write(AsyncWriteStream& s, */ template <typename AsyncWriteStream, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncWriteStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncWriteStream::executor_type)); + std::size_t)) WriteToken + = default_completion_token_t<typename AsyncWriteStream::executor_type>> +auto async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, + WriteToken&& token + = default_completion_token_t<typename AsyncWriteStream::executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(), + token, basic_streambuf_ref<Allocator>(b), transfer_all())); /// Start an asynchronous operation to write a certain amount of data to a /// stream. /** * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * data to a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied basic_streambuf has been written. * @@ -1128,7 +1172,7 @@ async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, * * @param b A basic_streambuf object from which data will be written. Ownership * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. + * remains valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object @@ -1144,22 +1188,27 @@ async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, * non-zero return value indicates the maximum number of bytes to be written on * the next call to the stream's async_write_some function. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -1174,12 +1223,15 @@ async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, template <typename AsyncWriteStream, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, - CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler); + std::size_t)) WriteToken> +auto async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, + CompletionCondition completion_condition, WriteToken&& token) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>>(), + token, basic_streambuf_ref<Allocator>(b), + static_cast<CompletionCondition&&>(completion_condition))); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS) @@ -1189,9 +1241,9 @@ async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, /// stream. /** * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * data to a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied dynamic buffer sequence has been written. * @@ -1209,25 +1261,30 @@ async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, * @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: + * that they remain valid until the completion handler is called. Successfully + * written data is automatically consumed from the buffers. + * + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -1241,26 +1298,28 @@ async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b, */ template <typename AsyncWriteStream, typename DynamicBuffer_v2, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncWriteStream::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncWriteStream::executor_type), - typename constraint< + std::size_t)) WriteToken + = default_completion_token_t<typename AsyncWriteStream::executor_type>> +auto async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, + WriteToken&& token + = default_completion_token_t<typename AsyncWriteStream::executor_type>(), + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), + transfer_all())); /// Start an asynchronous operation to write a certain amount of data to a /// stream. /** * This function is used to asynchronously write a certain number of bytes of - * data to a stream. The function call always returns immediately. The - * asynchronous operation will continue until one of the following conditions - * is true: + * data to a stream. It is an initiating function for an @ref + * asynchronous_operation, and always returns immediately. The asynchronous + * operation will continue until one of the following conditions is true: * * @li All of the data in the supplied dynamic buffer sequence has been written. * @@ -1278,8 +1337,8 @@ async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, * @param buffers The dynamic buffer sequence from which data will be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. Successfully written - * data is automatically consumed from the buffers. + * that they remain valid until the completion handler is called. Successfully + * written data is automatically consumed from the buffers. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object @@ -1295,22 +1354,27 @@ async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, * non-zero return value indicates the maximum number of bytes to be written on * the next call to the stream's async_write_some function. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( - * const asio::error_code& error, // Result of operation. + * // Result of operation. + * const asio::error_code& error, * - * std::size_t bytes_transferred // Number of bytes written from the - * // buffers. If an error occurred, - * // this will be less than the sum - * // of the buffer sizes. + * // Number of bytes written from the buffers. If an error + * // occurred, this will be less than the sum of the buffer sizes. + * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -1325,15 +1389,19 @@ async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, template <typename AsyncWriteStream, typename DynamicBuffer_v2, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, + std::size_t)) WriteToken> +auto async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers, CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler, - typename constraint< + WriteToken&& token, + constraint_t< is_dynamic_buffer_v2<DynamicBuffer_v2>::value - >::type = 0); + > = 0) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>>(), + token, static_cast<DynamicBuffer_v2&&>(buffers), + static_cast<CompletionCondition&&>(completion_condition))); /*@}*/ diff --git a/3rdparty/asio/include/asio/write_at.hpp b/3rdparty/asio/include/asio/write_at.hpp index a4c98c0264f..a33514e61a0 100644 --- a/3rdparty/asio/include/asio/write_at.hpp +++ b/3rdparty/asio/include/asio/write_at.hpp @@ -2,7 +2,7 @@ // write_at.hpp // ~~~~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) @@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include <cstddef> #include "asio/async_result.hpp" +#include "asio/completion_condition.hpp" #include "asio/detail/cstdint.hpp" #include "asio/error.hpp" @@ -28,6 +29,14 @@ #include "asio/detail/push_options.hpp" namespace asio { +namespace detail { + +template <typename> class initiate_async_write_at; +#if !defined(ASIO_NO_IOSTREAM) +template <typename> class initiate_async_write_at_streambuf; +#endif // !defined(ASIO_NO_IOSTREAM) + +} // namespace detail /** * @defgroup write_at asio::write_at @@ -403,9 +412,10 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, uint64_t offset, /// specified offset. /** * This function is used to asynchronously write a certain number of bytes of - * data to a random access device at a specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: + * data to a random access device at a specified offset. It is an initiating + * function for an @ref asynchronous_operation, and always returns immediately. + * The asynchronous operation will continue until one of the following + * conditions is true: * * @li All of the data in the supplied buffers has been written. That is, the * bytes transferred is equal to the sum of the buffer sizes. @@ -428,11 +438,13 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, uint64_t offset, * @param buffers One or more buffers containing the data to be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of - * the handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -442,10 +454,13 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, uint64_t offset, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To write a single data buffer use the @ref buffer function as follows: * @code @@ -468,24 +483,27 @@ std::size_t write_at(SyncRandomAccessWriteDevice& d, uint64_t offset, */ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncRandomAccessWriteDevice::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, - const ConstBufferSequence& buffers, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncRandomAccessWriteDevice::executor_type)); + std::size_t)) WriteToken = default_completion_token_t< + typename AsyncRandomAccessWriteDevice::executor_type>> +auto async_write_at(AsyncRandomAccessWriteDevice& d, + uint64_t offset, const ConstBufferSequence& buffers, + WriteToken&& token = default_completion_token_t< + typename AsyncRandomAccessWriteDevice::executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_at< + AsyncRandomAccessWriteDevice>>(), + token, offset, buffers, transfer_all())); /// Start an asynchronous operation to write a certain amount of data at the /// specified offset. /** * This function is used to asynchronously write a certain number of bytes of - * data to a random access device at a specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: + * data to a random access device at a specified offset. It is an initiating + * function for an @ref asynchronous_operation, and always returns immediately. + * The asynchronous operation will continue until one of the following + * conditions is true: * * @li All of the data in the supplied buffers has been written. That is, the * bytes transferred is equal to the sum of the buffer sizes. @@ -508,7 +526,7 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, * @param buffers One or more buffers containing the data to be written. * Although the buffers object may be copied as necessary, ownership of the * underlying memory blocks is retained by the caller, which must guarantee - * that they remain valid until the handler is called. + * that they remain valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object @@ -524,9 +542,11 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, * non-zero return value indicates the maximum number of bytes to be written on * the next call to the device's async_write_some_at function. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -536,10 +556,13 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Example * To write a single data buffer use the @ref buffer function as follows: * @code asio::async_write_at(d, 42, @@ -564,17 +587,20 @@ async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncRandomAccessWriteDevice::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write_at(AsyncRandomAccessWriteDevice& d, + std::size_t)) WriteToken = default_completion_token_t< + typename AsyncRandomAccessWriteDevice::executor_type>> +auto async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, const ConstBufferSequence& buffers, CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncRandomAccessWriteDevice::executor_type)); + WriteToken&& token = default_completion_token_t< + typename AsyncRandomAccessWriteDevice::executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_at< + AsyncRandomAccessWriteDevice>>(), + token, offset, buffers, + static_cast<CompletionCondition&&>(completion_condition))); #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM) @@ -583,9 +609,10 @@ async_write_at(AsyncRandomAccessWriteDevice& d, /// specified offset. /** * This function is used to asynchronously write a certain number of bytes of - * data to a random access device at a specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: + * data to a random access device at a specified offset. It is an initiating + * function for an @ref asynchronous_operation, and always returns immediately. + * The asynchronous operation will continue until one of the following + * conditions is true: * * @li All of the data in the supplied basic_streambuf has been written. * @@ -606,11 +633,13 @@ async_write_at(AsyncRandomAccessWriteDevice& d, * * @param b A basic_streambuf object from which data will be written. Ownership * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. + * remains valid until the completion handler is called. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -620,10 +649,13 @@ async_write_at(AsyncRandomAccessWriteDevice& d, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -637,24 +669,27 @@ async_write_at(AsyncRandomAccessWriteDevice& d, */ template <typename AsyncRandomAccessWriteDevice, typename Allocator, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncRandomAccessWriteDevice::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write_at(AsyncRandomAccessWriteDevice& d, + std::size_t)) WriteToken = default_completion_token_t< + typename AsyncRandomAccessWriteDevice::executor_type>> +auto async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, basic_streambuf<Allocator>& b, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncRandomAccessWriteDevice::executor_type)); + WriteToken&& token = default_completion_token_t< + typename AsyncRandomAccessWriteDevice::executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_at_streambuf< + AsyncRandomAccessWriteDevice>>(), + token, offset, &b, transfer_all())); /// Start an asynchronous operation to write a certain amount of data at the /// specified offset. /** * This function is used to asynchronously write a certain number of bytes of - * data to a random access device at a specified offset. The function call - * always returns immediately. The asynchronous operation will continue until - * one of the following conditions is true: + * data to a random access device at a specified offset. It is an initiating + * function for an @ref asynchronous_operation, and always returns immediately. + * The asynchronous operation will continue until one of the following + * conditions is true: * * @li All of the data in the supplied basic_streambuf has been written. * @@ -675,7 +710,7 @@ async_write_at(AsyncRandomAccessWriteDevice& d, * * @param b A basic_streambuf object from which data will be written. Ownership * of the streambuf is retained by the caller, which must guarantee that it - * remains valid until the handler is called. + * remains valid until the completion handler is called. * * @param completion_condition The function object to be called to determine * whether the write operation is complete. The signature of the function object @@ -691,9 +726,11 @@ async_write_at(AsyncRandomAccessWriteDevice& d, * non-zero return value indicates the maximum number of bytes to be written on * the next call to the device's async_write_some_at function. * - * @param handler The handler to be called when the write operation completes. - * Copies will be made of the handler as required. The function signature of the - * handler must be: + * @param token The @ref completion_token that will be used to produce a + * completion handler, which will be called when the write completes. + * Potential completion tokens include @ref use_future, @ref use_awaitable, + * @ref yield_context, or a function object with the correct completion + * signature. The function signature of the completion handler must be: * @code void handler( * // Result of operation. * const asio::error_code& error, @@ -703,10 +740,13 @@ async_write_at(AsyncRandomAccessWriteDevice& d, * std::size_t bytes_transferred * ); @endcode * Regardless of whether the asynchronous operation completes immediately or - * not, the handler will not be invoked from within this function. On - * immediate completion, invocation of the handler will be performed in a + * not, the completion handler will not be invoked from within this function. + * On immediate completion, invocation of the handler will be performed in a * manner equivalent to using asio::post(). * + * @par Completion Signature + * @code void(asio::error_code, std::size_t) @endcode + * * @par Per-Operation Cancellation * This asynchronous operation supports cancellation for the following * asio::cancellation_type values: @@ -721,16 +761,19 @@ async_write_at(AsyncRandomAccessWriteDevice& d, template <typename AsyncRandomAccessWriteDevice, typename Allocator, typename CompletionCondition, ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, - std::size_t)) WriteHandler - ASIO_DEFAULT_COMPLETION_TOKEN_TYPE( - typename AsyncRandomAccessWriteDevice::executor_type)> -ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler, - void (asio::error_code, std::size_t)) -async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, + std::size_t)) WriteToken = default_completion_token_t< + typename AsyncRandomAccessWriteDevice::executor_type>> +auto async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset, basic_streambuf<Allocator>& b, CompletionCondition completion_condition, - ASIO_MOVE_ARG(WriteHandler) handler - ASIO_DEFAULT_COMPLETION_TOKEN( - typename AsyncRandomAccessWriteDevice::executor_type)); + WriteToken&& token = default_completion_token_t< + typename AsyncRandomAccessWriteDevice::executor_type>()) + -> decltype( + async_initiate<WriteToken, + void (asio::error_code, std::size_t)>( + declval<detail::initiate_async_write_at_streambuf< + AsyncRandomAccessWriteDevice>>(), + token, offset, &b, + static_cast<CompletionCondition&&>(completion_condition))); #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS) diff --git a/3rdparty/asio/include/asio/yield.hpp b/3rdparty/asio/include/asio/yield.hpp index 5c090a65c4e..c180503dda9 100644 --- a/3rdparty/asio/include/asio/yield.hpp +++ b/3rdparty/asio/include/asio/yield.hpp @@ -2,7 +2,7 @@ // yield.hpp // ~~~~~~~~~ // -// Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |