diff options
Diffstat (limited to '3rdparty/asio/src/examples/cpp14')
43 files changed, 4878 insertions, 269 deletions
diff --git a/3rdparty/asio/src/examples/cpp14/Makefile.am b/3rdparty/asio/src/examples/cpp14/Makefile.am index fb8c35689c6..2ddf12a8a2f 100644 --- a/3rdparty/asio/src/examples/cpp14/Makefile.am +++ b/3rdparty/asio/src/examples/cpp14/Makefile.am @@ -10,6 +10,13 @@ LDADD = libasio.a endif noinst_PROGRAMS = \ + deferred/deferred_1 \ + deferred/deferred_2 \ + deferred/deferred_3 \ + deferred/deferred_4 \ + deferred/deferred_5 \ + deferred/deferred_6 \ + deferred/deferred_7 \ echo/async_tcp_echo_server \ echo/async_udp_echo_server \ echo/blocking_tcp_echo_client \ @@ -24,10 +31,34 @@ noinst_PROGRAMS = \ executors/fork_join \ executors/pipeline \ executors/priority_scheduler \ - iostreams/http_client + iostreams/http_client \ + operations/c_callback_wrapper \ + operations/callback_wrapper \ + operations/composed_1 \ + operations/composed_1 \ + operations/composed_2 \ + operations/composed_3 \ + operations/composed_4 \ + operations/composed_5 \ + operations/composed_6 \ + operations/composed_7 \ + operations/composed_8 \ + parallel_group/parallel_sort \ + parallel_group/ranged_wait_for_all \ + parallel_group/wait_for_all \ + parallel_group/wait_for_one \ + parallel_group/wait_for_one_error \ + parallel_group/wait_for_one_success AM_CXXFLAGS = -I$(srcdir)/../../../include +deferred_deferred_1_SOURCES = deferred/deferred_1.cpp +deferred_deferred_2_SOURCES = deferred/deferred_2.cpp +deferred_deferred_3_SOURCES = deferred/deferred_3.cpp +deferred_deferred_4_SOURCES = deferred/deferred_4.cpp +deferred_deferred_5_SOURCES = deferred/deferred_5.cpp +deferred_deferred_6_SOURCES = deferred/deferred_6.cpp +deferred_deferred_7_SOURCES = deferred/deferred_7.cpp echo_async_tcp_echo_server_SOURCES = echo/async_tcp_echo_server.cpp echo_async_udp_echo_server_SOURCES = echo/async_udp_echo_server.cpp echo_blocking_tcp_echo_client_SOURCES = echo/blocking_tcp_echo_client.cpp @@ -43,6 +74,22 @@ executors_fork_join_SOURCES = executors/fork_join.cpp executors_pipeline_SOURCES = executors/pipeline.cpp executors_priority_scheduler_SOURCES = executors/priority_scheduler.cpp iostreams_http_client_SOURCES = iostreams/http_client.cpp +operations_c_callback_wrapper_SOURCES = operations/c_callback_wrapper.cpp +operations_callback_wrapper_SOURCES = operations/callback_wrapper.cpp +operations_composed_1_SOURCES = operations/composed_1.cpp +operations_composed_2_SOURCES = operations/composed_2.cpp +operations_composed_3_SOURCES = operations/composed_3.cpp +operations_composed_4_SOURCES = operations/composed_4.cpp +operations_composed_5_SOURCES = operations/composed_5.cpp +operations_composed_6_SOURCES = operations/composed_6.cpp +operations_composed_7_SOURCES = operations/composed_7.cpp +operations_composed_8_SOURCES = operations/composed_8.cpp +parallel_group_parallel_sort_SOURCES = parallel_group/parallel_sort.cpp +parallel_group_ranged_wait_for_all_SOURCES = parallel_group/ranged_wait_for_all.cpp +parallel_group_wait_for_all_SOURCES = parallel_group/wait_for_all.cpp +parallel_group_wait_for_one_SOURCES = parallel_group/wait_for_one.cpp +parallel_group_wait_for_one_error_SOURCES = parallel_group/wait_for_one_error.cpp +parallel_group_wait_for_one_success_SOURCES = parallel_group/wait_for_one_success.cpp MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in diff --git a/3rdparty/asio/src/examples/cpp14/Makefile.in b/3rdparty/asio/src/examples/cpp14/Makefile.in new file mode 100644 index 00000000000..23fdb3fc1e2 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/Makefile.in @@ -0,0 +1,1378 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# 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, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@HAVE_OPENSSL_TRUE@@SEPARATE_COMPILATION_TRUE@am__append_1 = ../../asio_ssl.cpp +noinst_PROGRAMS = deferred/deferred_1$(EXEEXT) \ + deferred/deferred_2$(EXEEXT) deferred/deferred_3$(EXEEXT) \ + deferred/deferred_4$(EXEEXT) deferred/deferred_5$(EXEEXT) \ + deferred/deferred_6$(EXEEXT) deferred/deferred_7$(EXEEXT) \ + echo/async_tcp_echo_server$(EXEEXT) \ + echo/async_udp_echo_server$(EXEEXT) \ + echo/blocking_tcp_echo_client$(EXEEXT) \ + echo/blocking_tcp_echo_server$(EXEEXT) \ + echo/blocking_udp_echo_client$(EXEEXT) \ + echo/blocking_udp_echo_server$(EXEEXT) \ + executors/actor$(EXEEXT) executors/async_1$(EXEEXT) \ + executors/async_2$(EXEEXT) executors/bank_account_1$(EXEEXT) \ + executors/bank_account_2$(EXEEXT) executors/fork_join$(EXEEXT) \ + executors/pipeline$(EXEEXT) \ + executors/priority_scheduler$(EXEEXT) \ + iostreams/http_client$(EXEEXT) \ + operations/c_callback_wrapper$(EXEEXT) \ + operations/callback_wrapper$(EXEEXT) \ + operations/composed_1$(EXEEXT) operations/composed_1$(EXEEXT) \ + operations/composed_2$(EXEEXT) operations/composed_3$(EXEEXT) \ + operations/composed_4$(EXEEXT) operations/composed_5$(EXEEXT) \ + operations/composed_6$(EXEEXT) operations/composed_7$(EXEEXT) \ + operations/composed_8$(EXEEXT) \ + parallel_group/parallel_sort$(EXEEXT) \ + parallel_group/ranged_wait_for_all$(EXEEXT) \ + parallel_group/wait_for_all$(EXEEXT) \ + parallel_group/wait_for_one$(EXEEXT) \ + parallel_group/wait_for_one_error$(EXEEXT) \ + parallel_group/wait_for_one_success$(EXEEXT) +subdir = src/examples/cpp14 +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +LIBRARIES = $(noinst_LIBRARIES) +AR = ar +ARFLAGS = cru +AM_V_AR = $(am__v_AR_@AM_V@) +am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) +am__v_AR_0 = @echo " AR " $@; +am__v_AR_1 = +libasio_a_AR = $(AR) $(ARFLAGS) +libasio_a_LIBADD = +am__libasio_a_SOURCES_DIST = ../../asio.cpp ../../asio_ssl.cpp +am__dirstamp = $(am__leading_dot)dirstamp +@HAVE_OPENSSL_TRUE@@SEPARATE_COMPILATION_TRUE@am__objects_1 = ../../asio_ssl.$(OBJEXT) +@SEPARATE_COMPILATION_TRUE@am_libasio_a_OBJECTS = \ +@SEPARATE_COMPILATION_TRUE@ ../../asio.$(OBJEXT) \ +@SEPARATE_COMPILATION_TRUE@ $(am__objects_1) +libasio_a_OBJECTS = $(am_libasio_a_OBJECTS) +am_deferred_deferred_1_OBJECTS = deferred/deferred_1.$(OBJEXT) +deferred_deferred_1_OBJECTS = $(am_deferred_deferred_1_OBJECTS) +deferred_deferred_1_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@deferred_deferred_1_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_deferred_deferred_2_OBJECTS = deferred/deferred_2.$(OBJEXT) +deferred_deferred_2_OBJECTS = $(am_deferred_deferred_2_OBJECTS) +deferred_deferred_2_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@deferred_deferred_2_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_deferred_deferred_3_OBJECTS = deferred/deferred_3.$(OBJEXT) +deferred_deferred_3_OBJECTS = $(am_deferred_deferred_3_OBJECTS) +deferred_deferred_3_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@deferred_deferred_3_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_deferred_deferred_4_OBJECTS = deferred/deferred_4.$(OBJEXT) +deferred_deferred_4_OBJECTS = $(am_deferred_deferred_4_OBJECTS) +deferred_deferred_4_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@deferred_deferred_4_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_deferred_deferred_5_OBJECTS = deferred/deferred_5.$(OBJEXT) +deferred_deferred_5_OBJECTS = $(am_deferred_deferred_5_OBJECTS) +deferred_deferred_5_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@deferred_deferred_5_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_deferred_deferred_6_OBJECTS = deferred/deferred_6.$(OBJEXT) +deferred_deferred_6_OBJECTS = $(am_deferred_deferred_6_OBJECTS) +deferred_deferred_6_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@deferred_deferred_6_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_deferred_deferred_7_OBJECTS = deferred/deferred_7.$(OBJEXT) +deferred_deferred_7_OBJECTS = $(am_deferred_deferred_7_OBJECTS) +deferred_deferred_7_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@deferred_deferred_7_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_echo_async_tcp_echo_server_OBJECTS = \ + echo/async_tcp_echo_server.$(OBJEXT) +echo_async_tcp_echo_server_OBJECTS = \ + $(am_echo_async_tcp_echo_server_OBJECTS) +echo_async_tcp_echo_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@echo_async_tcp_echo_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_echo_async_udp_echo_server_OBJECTS = \ + echo/async_udp_echo_server.$(OBJEXT) +echo_async_udp_echo_server_OBJECTS = \ + $(am_echo_async_udp_echo_server_OBJECTS) +echo_async_udp_echo_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@echo_async_udp_echo_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_echo_blocking_tcp_echo_client_OBJECTS = \ + echo/blocking_tcp_echo_client.$(OBJEXT) +echo_blocking_tcp_echo_client_OBJECTS = \ + $(am_echo_blocking_tcp_echo_client_OBJECTS) +echo_blocking_tcp_echo_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@echo_blocking_tcp_echo_client_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_echo_blocking_tcp_echo_server_OBJECTS = \ + echo/blocking_tcp_echo_server.$(OBJEXT) +echo_blocking_tcp_echo_server_OBJECTS = \ + $(am_echo_blocking_tcp_echo_server_OBJECTS) +echo_blocking_tcp_echo_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@echo_blocking_tcp_echo_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_echo_blocking_udp_echo_client_OBJECTS = \ + echo/blocking_udp_echo_client.$(OBJEXT) +echo_blocking_udp_echo_client_OBJECTS = \ + $(am_echo_blocking_udp_echo_client_OBJECTS) +echo_blocking_udp_echo_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@echo_blocking_udp_echo_client_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_echo_blocking_udp_echo_server_OBJECTS = \ + echo/blocking_udp_echo_server.$(OBJEXT) +echo_blocking_udp_echo_server_OBJECTS = \ + $(am_echo_blocking_udp_echo_server_OBJECTS) +echo_blocking_udp_echo_server_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@echo_blocking_udp_echo_server_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_executors_actor_OBJECTS = executors/actor.$(OBJEXT) +executors_actor_OBJECTS = $(am_executors_actor_OBJECTS) +executors_actor_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@executors_actor_DEPENDENCIES = libasio.a +am_executors_async_1_OBJECTS = executors/async_1.$(OBJEXT) +executors_async_1_OBJECTS = $(am_executors_async_1_OBJECTS) +executors_async_1_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@executors_async_1_DEPENDENCIES = libasio.a +am_executors_async_2_OBJECTS = executors/async_2.$(OBJEXT) +executors_async_2_OBJECTS = $(am_executors_async_2_OBJECTS) +executors_async_2_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@executors_async_2_DEPENDENCIES = libasio.a +am_executors_bank_account_1_OBJECTS = \ + executors/bank_account_1.$(OBJEXT) +executors_bank_account_1_OBJECTS = \ + $(am_executors_bank_account_1_OBJECTS) +executors_bank_account_1_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@executors_bank_account_1_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_executors_bank_account_2_OBJECTS = \ + executors/bank_account_2.$(OBJEXT) +executors_bank_account_2_OBJECTS = \ + $(am_executors_bank_account_2_OBJECTS) +executors_bank_account_2_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@executors_bank_account_2_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_executors_fork_join_OBJECTS = executors/fork_join.$(OBJEXT) +executors_fork_join_OBJECTS = $(am_executors_fork_join_OBJECTS) +executors_fork_join_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@executors_fork_join_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_executors_pipeline_OBJECTS = executors/pipeline.$(OBJEXT) +executors_pipeline_OBJECTS = $(am_executors_pipeline_OBJECTS) +executors_pipeline_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@executors_pipeline_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_executors_priority_scheduler_OBJECTS = \ + executors/priority_scheduler.$(OBJEXT) +executors_priority_scheduler_OBJECTS = \ + $(am_executors_priority_scheduler_OBJECTS) +executors_priority_scheduler_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@executors_priority_scheduler_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_iostreams_http_client_OBJECTS = iostreams/http_client.$(OBJEXT) +iostreams_http_client_OBJECTS = $(am_iostreams_http_client_OBJECTS) +iostreams_http_client_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@iostreams_http_client_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_operations_c_callback_wrapper_OBJECTS = \ + operations/c_callback_wrapper.$(OBJEXT) +operations_c_callback_wrapper_OBJECTS = \ + $(am_operations_c_callback_wrapper_OBJECTS) +operations_c_callback_wrapper_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@operations_c_callback_wrapper_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_operations_callback_wrapper_OBJECTS = \ + operations/callback_wrapper.$(OBJEXT) +operations_callback_wrapper_OBJECTS = \ + $(am_operations_callback_wrapper_OBJECTS) +operations_callback_wrapper_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@operations_callback_wrapper_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_operations_composed_1_OBJECTS = operations/composed_1.$(OBJEXT) +operations_composed_1_OBJECTS = $(am_operations_composed_1_OBJECTS) +operations_composed_1_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@operations_composed_1_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_operations_composed_2_OBJECTS = operations/composed_2.$(OBJEXT) +operations_composed_2_OBJECTS = $(am_operations_composed_2_OBJECTS) +operations_composed_2_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@operations_composed_2_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_operations_composed_3_OBJECTS = operations/composed_3.$(OBJEXT) +operations_composed_3_OBJECTS = $(am_operations_composed_3_OBJECTS) +operations_composed_3_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@operations_composed_3_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_operations_composed_4_OBJECTS = operations/composed_4.$(OBJEXT) +operations_composed_4_OBJECTS = $(am_operations_composed_4_OBJECTS) +operations_composed_4_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@operations_composed_4_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_operations_composed_5_OBJECTS = operations/composed_5.$(OBJEXT) +operations_composed_5_OBJECTS = $(am_operations_composed_5_OBJECTS) +operations_composed_5_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@operations_composed_5_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_operations_composed_6_OBJECTS = operations/composed_6.$(OBJEXT) +operations_composed_6_OBJECTS = $(am_operations_composed_6_OBJECTS) +operations_composed_6_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@operations_composed_6_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_operations_composed_7_OBJECTS = operations/composed_7.$(OBJEXT) +operations_composed_7_OBJECTS = $(am_operations_composed_7_OBJECTS) +operations_composed_7_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@operations_composed_7_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_operations_composed_8_OBJECTS = operations/composed_8.$(OBJEXT) +operations_composed_8_OBJECTS = $(am_operations_composed_8_OBJECTS) +operations_composed_8_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@operations_composed_8_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_parallel_group_parallel_sort_OBJECTS = \ + parallel_group/parallel_sort.$(OBJEXT) +parallel_group_parallel_sort_OBJECTS = \ + $(am_parallel_group_parallel_sort_OBJECTS) +parallel_group_parallel_sort_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@parallel_group_parallel_sort_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_parallel_group_ranged_wait_for_all_OBJECTS = \ + parallel_group/ranged_wait_for_all.$(OBJEXT) +parallel_group_ranged_wait_for_all_OBJECTS = \ + $(am_parallel_group_ranged_wait_for_all_OBJECTS) +parallel_group_ranged_wait_for_all_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@parallel_group_ranged_wait_for_all_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_parallel_group_wait_for_all_OBJECTS = \ + parallel_group/wait_for_all.$(OBJEXT) +parallel_group_wait_for_all_OBJECTS = \ + $(am_parallel_group_wait_for_all_OBJECTS) +parallel_group_wait_for_all_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@parallel_group_wait_for_all_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_parallel_group_wait_for_one_OBJECTS = \ + parallel_group/wait_for_one.$(OBJEXT) +parallel_group_wait_for_one_OBJECTS = \ + $(am_parallel_group_wait_for_one_OBJECTS) +parallel_group_wait_for_one_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@parallel_group_wait_for_one_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_parallel_group_wait_for_one_error_OBJECTS = \ + parallel_group/wait_for_one_error.$(OBJEXT) +parallel_group_wait_for_one_error_OBJECTS = \ + $(am_parallel_group_wait_for_one_error_OBJECTS) +parallel_group_wait_for_one_error_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@parallel_group_wait_for_one_error_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +am_parallel_group_wait_for_one_success_OBJECTS = \ + parallel_group/wait_for_one_success.$(OBJEXT) +parallel_group_wait_for_one_success_OBJECTS = \ + $(am_parallel_group_wait_for_one_success_OBJECTS) +parallel_group_wait_for_one_success_LDADD = $(LDADD) +@SEPARATE_COMPILATION_TRUE@parallel_group_wait_for_one_success_DEPENDENCIES = \ +@SEPARATE_COMPILATION_TRUE@ libasio.a +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ../../$(DEPDIR)/asio.Po \ + ../../$(DEPDIR)/asio_ssl.Po deferred/$(DEPDIR)/deferred_1.Po \ + deferred/$(DEPDIR)/deferred_2.Po \ + deferred/$(DEPDIR)/deferred_3.Po \ + deferred/$(DEPDIR)/deferred_4.Po \ + deferred/$(DEPDIR)/deferred_5.Po \ + deferred/$(DEPDIR)/deferred_6.Po \ + deferred/$(DEPDIR)/deferred_7.Po \ + echo/$(DEPDIR)/async_tcp_echo_server.Po \ + echo/$(DEPDIR)/async_udp_echo_server.Po \ + echo/$(DEPDIR)/blocking_tcp_echo_client.Po \ + echo/$(DEPDIR)/blocking_tcp_echo_server.Po \ + echo/$(DEPDIR)/blocking_udp_echo_client.Po \ + echo/$(DEPDIR)/blocking_udp_echo_server.Po \ + executors/$(DEPDIR)/actor.Po executors/$(DEPDIR)/async_1.Po \ + executors/$(DEPDIR)/async_2.Po \ + executors/$(DEPDIR)/bank_account_1.Po \ + executors/$(DEPDIR)/bank_account_2.Po \ + executors/$(DEPDIR)/fork_join.Po \ + executors/$(DEPDIR)/pipeline.Po \ + executors/$(DEPDIR)/priority_scheduler.Po \ + iostreams/$(DEPDIR)/http_client.Po \ + operations/$(DEPDIR)/c_callback_wrapper.Po \ + operations/$(DEPDIR)/callback_wrapper.Po \ + operations/$(DEPDIR)/composed_1.Po \ + operations/$(DEPDIR)/composed_2.Po \ + operations/$(DEPDIR)/composed_3.Po \ + operations/$(DEPDIR)/composed_4.Po \ + operations/$(DEPDIR)/composed_5.Po \ + operations/$(DEPDIR)/composed_6.Po \ + operations/$(DEPDIR)/composed_7.Po \ + operations/$(DEPDIR)/composed_8.Po \ + parallel_group/$(DEPDIR)/parallel_sort.Po \ + parallel_group/$(DEPDIR)/ranged_wait_for_all.Po \ + parallel_group/$(DEPDIR)/wait_for_all.Po \ + parallel_group/$(DEPDIR)/wait_for_one.Po \ + parallel_group/$(DEPDIR)/wait_for_one_error.Po \ + parallel_group/$(DEPDIR)/wait_for_one_success.Po +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ + -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +SOURCES = $(libasio_a_SOURCES) $(deferred_deferred_1_SOURCES) \ + $(deferred_deferred_2_SOURCES) $(deferred_deferred_3_SOURCES) \ + $(deferred_deferred_4_SOURCES) $(deferred_deferred_5_SOURCES) \ + $(deferred_deferred_6_SOURCES) $(deferred_deferred_7_SOURCES) \ + $(echo_async_tcp_echo_server_SOURCES) \ + $(echo_async_udp_echo_server_SOURCES) \ + $(echo_blocking_tcp_echo_client_SOURCES) \ + $(echo_blocking_tcp_echo_server_SOURCES) \ + $(echo_blocking_udp_echo_client_SOURCES) \ + $(echo_blocking_udp_echo_server_SOURCES) \ + $(executors_actor_SOURCES) $(executors_async_1_SOURCES) \ + $(executors_async_2_SOURCES) \ + $(executors_bank_account_1_SOURCES) \ + $(executors_bank_account_2_SOURCES) \ + $(executors_fork_join_SOURCES) $(executors_pipeline_SOURCES) \ + $(executors_priority_scheduler_SOURCES) \ + $(iostreams_http_client_SOURCES) \ + $(operations_c_callback_wrapper_SOURCES) \ + $(operations_callback_wrapper_SOURCES) \ + $(operations_composed_1_SOURCES) \ + $(operations_composed_2_SOURCES) \ + $(operations_composed_3_SOURCES) \ + $(operations_composed_4_SOURCES) \ + $(operations_composed_5_SOURCES) \ + $(operations_composed_6_SOURCES) \ + $(operations_composed_7_SOURCES) \ + $(operations_composed_8_SOURCES) \ + $(parallel_group_parallel_sort_SOURCES) \ + $(parallel_group_ranged_wait_for_all_SOURCES) \ + $(parallel_group_wait_for_all_SOURCES) \ + $(parallel_group_wait_for_one_SOURCES) \ + $(parallel_group_wait_for_one_error_SOURCES) \ + $(parallel_group_wait_for_one_success_SOURCES) +DIST_SOURCES = $(am__libasio_a_SOURCES_DIST) \ + $(deferred_deferred_1_SOURCES) $(deferred_deferred_2_SOURCES) \ + $(deferred_deferred_3_SOURCES) $(deferred_deferred_4_SOURCES) \ + $(deferred_deferred_5_SOURCES) $(deferred_deferred_6_SOURCES) \ + $(deferred_deferred_7_SOURCES) \ + $(echo_async_tcp_echo_server_SOURCES) \ + $(echo_async_udp_echo_server_SOURCES) \ + $(echo_blocking_tcp_echo_client_SOURCES) \ + $(echo_blocking_tcp_echo_server_SOURCES) \ + $(echo_blocking_udp_echo_client_SOURCES) \ + $(echo_blocking_udp_echo_server_SOURCES) \ + $(executors_actor_SOURCES) $(executors_async_1_SOURCES) \ + $(executors_async_2_SOURCES) \ + $(executors_bank_account_1_SOURCES) \ + $(executors_bank_account_2_SOURCES) \ + $(executors_fork_join_SOURCES) $(executors_pipeline_SOURCES) \ + $(executors_priority_scheduler_SOURCES) \ + $(iostreams_http_client_SOURCES) \ + $(operations_c_callback_wrapper_SOURCES) \ + $(operations_callback_wrapper_SOURCES) \ + $(operations_composed_1_SOURCES) \ + $(operations_composed_2_SOURCES) \ + $(operations_composed_3_SOURCES) \ + $(operations_composed_4_SOURCES) \ + $(operations_composed_5_SOURCES) \ + $(operations_composed_6_SOURCES) \ + $(operations_composed_7_SOURCES) \ + $(operations_composed_8_SOURCES) \ + $(parallel_group_parallel_sort_SOURCES) \ + $(parallel_group_ranged_wait_for_all_SOURCES) \ + $(parallel_group_wait_for_all_SOURCES) \ + $(parallel_group_wait_for_one_SOURCES) \ + $(parallel_group_wait_for_one_error_SOURCES) \ + $(parallel_group_wait_for_one_success_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +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@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = subdir-objects +@SEPARATE_COMPILATION_TRUE@noinst_LIBRARIES = libasio.a +@SEPARATE_COMPILATION_TRUE@libasio_a_SOURCES = ../../asio.cpp \ +@SEPARATE_COMPILATION_TRUE@ $(am__append_1) +@SEPARATE_COMPILATION_TRUE@LDADD = libasio.a +AM_CXXFLAGS = -I$(srcdir)/../../../include +deferred_deferred_1_SOURCES = deferred/deferred_1.cpp +deferred_deferred_2_SOURCES = deferred/deferred_2.cpp +deferred_deferred_3_SOURCES = deferred/deferred_3.cpp +deferred_deferred_4_SOURCES = deferred/deferred_4.cpp +deferred_deferred_5_SOURCES = deferred/deferred_5.cpp +deferred_deferred_6_SOURCES = deferred/deferred_6.cpp +deferred_deferred_7_SOURCES = deferred/deferred_7.cpp +echo_async_tcp_echo_server_SOURCES = echo/async_tcp_echo_server.cpp +echo_async_udp_echo_server_SOURCES = echo/async_udp_echo_server.cpp +echo_blocking_tcp_echo_client_SOURCES = echo/blocking_tcp_echo_client.cpp +echo_blocking_tcp_echo_server_SOURCES = echo/blocking_tcp_echo_server.cpp +echo_blocking_udp_echo_client_SOURCES = echo/blocking_udp_echo_client.cpp +echo_blocking_udp_echo_server_SOURCES = echo/blocking_udp_echo_server.cpp +executors_actor_SOURCES = executors/actor.cpp +executors_async_1_SOURCES = executors/async_1.cpp +executors_async_2_SOURCES = executors/async_2.cpp +executors_bank_account_1_SOURCES = executors/bank_account_1.cpp +executors_bank_account_2_SOURCES = executors/bank_account_2.cpp +executors_fork_join_SOURCES = executors/fork_join.cpp +executors_pipeline_SOURCES = executors/pipeline.cpp +executors_priority_scheduler_SOURCES = executors/priority_scheduler.cpp +iostreams_http_client_SOURCES = iostreams/http_client.cpp +operations_c_callback_wrapper_SOURCES = operations/c_callback_wrapper.cpp +operations_callback_wrapper_SOURCES = operations/callback_wrapper.cpp +operations_composed_1_SOURCES = operations/composed_1.cpp +operations_composed_2_SOURCES = operations/composed_2.cpp +operations_composed_3_SOURCES = operations/composed_3.cpp +operations_composed_4_SOURCES = operations/composed_4.cpp +operations_composed_5_SOURCES = operations/composed_5.cpp +operations_composed_6_SOURCES = operations/composed_6.cpp +operations_composed_7_SOURCES = operations/composed_7.cpp +operations_composed_8_SOURCES = operations/composed_8.cpp +parallel_group_parallel_sort_SOURCES = parallel_group/parallel_sort.cpp +parallel_group_ranged_wait_for_all_SOURCES = parallel_group/ranged_wait_for_all.cpp +parallel_group_wait_for_all_SOURCES = parallel_group/wait_for_all.cpp +parallel_group_wait_for_one_SOURCES = parallel_group/wait_for_one.cpp +parallel_group_wait_for_one_error_SOURCES = parallel_group/wait_for_one_error.cpp +parallel_group_wait_for_one_success_SOURCES = parallel_group/wait_for_one_success.cpp +MAINTAINERCLEANFILES = \ + $(srcdir)/Makefile.in + +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/examples/cpp14/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/examples/cpp14/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) +../../$(am__dirstamp): + @$(MKDIR_P) ../.. + @: > ../../$(am__dirstamp) +../../$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) ../../$(DEPDIR) + @: > ../../$(DEPDIR)/$(am__dirstamp) +../../asio.$(OBJEXT): ../../$(am__dirstamp) \ + ../../$(DEPDIR)/$(am__dirstamp) +../../asio_ssl.$(OBJEXT): ../../$(am__dirstamp) \ + ../../$(DEPDIR)/$(am__dirstamp) + +libasio.a: $(libasio_a_OBJECTS) $(libasio_a_DEPENDENCIES) $(EXTRA_libasio_a_DEPENDENCIES) + $(AM_V_at)-rm -f libasio.a + $(AM_V_AR)$(libasio_a_AR) libasio.a $(libasio_a_OBJECTS) $(libasio_a_LIBADD) + $(AM_V_at)$(RANLIB) libasio.a +deferred/$(am__dirstamp): + @$(MKDIR_P) deferred + @: > deferred/$(am__dirstamp) +deferred/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) deferred/$(DEPDIR) + @: > deferred/$(DEPDIR)/$(am__dirstamp) +deferred/deferred_1.$(OBJEXT): deferred/$(am__dirstamp) \ + deferred/$(DEPDIR)/$(am__dirstamp) + +deferred/deferred_1$(EXEEXT): $(deferred_deferred_1_OBJECTS) $(deferred_deferred_1_DEPENDENCIES) $(EXTRA_deferred_deferred_1_DEPENDENCIES) deferred/$(am__dirstamp) + @rm -f deferred/deferred_1$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(deferred_deferred_1_OBJECTS) $(deferred_deferred_1_LDADD) $(LIBS) +deferred/deferred_2.$(OBJEXT): deferred/$(am__dirstamp) \ + deferred/$(DEPDIR)/$(am__dirstamp) + +deferred/deferred_2$(EXEEXT): $(deferred_deferred_2_OBJECTS) $(deferred_deferred_2_DEPENDENCIES) $(EXTRA_deferred_deferred_2_DEPENDENCIES) deferred/$(am__dirstamp) + @rm -f deferred/deferred_2$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(deferred_deferred_2_OBJECTS) $(deferred_deferred_2_LDADD) $(LIBS) +deferred/deferred_3.$(OBJEXT): deferred/$(am__dirstamp) \ + deferred/$(DEPDIR)/$(am__dirstamp) + +deferred/deferred_3$(EXEEXT): $(deferred_deferred_3_OBJECTS) $(deferred_deferred_3_DEPENDENCIES) $(EXTRA_deferred_deferred_3_DEPENDENCIES) deferred/$(am__dirstamp) + @rm -f deferred/deferred_3$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(deferred_deferred_3_OBJECTS) $(deferred_deferred_3_LDADD) $(LIBS) +deferred/deferred_4.$(OBJEXT): deferred/$(am__dirstamp) \ + deferred/$(DEPDIR)/$(am__dirstamp) + +deferred/deferred_4$(EXEEXT): $(deferred_deferred_4_OBJECTS) $(deferred_deferred_4_DEPENDENCIES) $(EXTRA_deferred_deferred_4_DEPENDENCIES) deferred/$(am__dirstamp) + @rm -f deferred/deferred_4$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(deferred_deferred_4_OBJECTS) $(deferred_deferred_4_LDADD) $(LIBS) +deferred/deferred_5.$(OBJEXT): deferred/$(am__dirstamp) \ + deferred/$(DEPDIR)/$(am__dirstamp) + +deferred/deferred_5$(EXEEXT): $(deferred_deferred_5_OBJECTS) $(deferred_deferred_5_DEPENDENCIES) $(EXTRA_deferred_deferred_5_DEPENDENCIES) deferred/$(am__dirstamp) + @rm -f deferred/deferred_5$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(deferred_deferred_5_OBJECTS) $(deferred_deferred_5_LDADD) $(LIBS) +deferred/deferred_6.$(OBJEXT): deferred/$(am__dirstamp) \ + deferred/$(DEPDIR)/$(am__dirstamp) + +deferred/deferred_6$(EXEEXT): $(deferred_deferred_6_OBJECTS) $(deferred_deferred_6_DEPENDENCIES) $(EXTRA_deferred_deferred_6_DEPENDENCIES) deferred/$(am__dirstamp) + @rm -f deferred/deferred_6$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(deferred_deferred_6_OBJECTS) $(deferred_deferred_6_LDADD) $(LIBS) +deferred/deferred_7.$(OBJEXT): deferred/$(am__dirstamp) \ + deferred/$(DEPDIR)/$(am__dirstamp) + +deferred/deferred_7$(EXEEXT): $(deferred_deferred_7_OBJECTS) $(deferred_deferred_7_DEPENDENCIES) $(EXTRA_deferred_deferred_7_DEPENDENCIES) deferred/$(am__dirstamp) + @rm -f deferred/deferred_7$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(deferred_deferred_7_OBJECTS) $(deferred_deferred_7_LDADD) $(LIBS) +echo/$(am__dirstamp): + @$(MKDIR_P) echo + @: > echo/$(am__dirstamp) +echo/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) echo/$(DEPDIR) + @: > echo/$(DEPDIR)/$(am__dirstamp) +echo/async_tcp_echo_server.$(OBJEXT): echo/$(am__dirstamp) \ + echo/$(DEPDIR)/$(am__dirstamp) + +echo/async_tcp_echo_server$(EXEEXT): $(echo_async_tcp_echo_server_OBJECTS) $(echo_async_tcp_echo_server_DEPENDENCIES) $(EXTRA_echo_async_tcp_echo_server_DEPENDENCIES) echo/$(am__dirstamp) + @rm -f echo/async_tcp_echo_server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(echo_async_tcp_echo_server_OBJECTS) $(echo_async_tcp_echo_server_LDADD) $(LIBS) +echo/async_udp_echo_server.$(OBJEXT): echo/$(am__dirstamp) \ + echo/$(DEPDIR)/$(am__dirstamp) + +echo/async_udp_echo_server$(EXEEXT): $(echo_async_udp_echo_server_OBJECTS) $(echo_async_udp_echo_server_DEPENDENCIES) $(EXTRA_echo_async_udp_echo_server_DEPENDENCIES) echo/$(am__dirstamp) + @rm -f echo/async_udp_echo_server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(echo_async_udp_echo_server_OBJECTS) $(echo_async_udp_echo_server_LDADD) $(LIBS) +echo/blocking_tcp_echo_client.$(OBJEXT): echo/$(am__dirstamp) \ + echo/$(DEPDIR)/$(am__dirstamp) + +echo/blocking_tcp_echo_client$(EXEEXT): $(echo_blocking_tcp_echo_client_OBJECTS) $(echo_blocking_tcp_echo_client_DEPENDENCIES) $(EXTRA_echo_blocking_tcp_echo_client_DEPENDENCIES) echo/$(am__dirstamp) + @rm -f echo/blocking_tcp_echo_client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(echo_blocking_tcp_echo_client_OBJECTS) $(echo_blocking_tcp_echo_client_LDADD) $(LIBS) +echo/blocking_tcp_echo_server.$(OBJEXT): echo/$(am__dirstamp) \ + echo/$(DEPDIR)/$(am__dirstamp) + +echo/blocking_tcp_echo_server$(EXEEXT): $(echo_blocking_tcp_echo_server_OBJECTS) $(echo_blocking_tcp_echo_server_DEPENDENCIES) $(EXTRA_echo_blocking_tcp_echo_server_DEPENDENCIES) echo/$(am__dirstamp) + @rm -f echo/blocking_tcp_echo_server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(echo_blocking_tcp_echo_server_OBJECTS) $(echo_blocking_tcp_echo_server_LDADD) $(LIBS) +echo/blocking_udp_echo_client.$(OBJEXT): echo/$(am__dirstamp) \ + echo/$(DEPDIR)/$(am__dirstamp) + +echo/blocking_udp_echo_client$(EXEEXT): $(echo_blocking_udp_echo_client_OBJECTS) $(echo_blocking_udp_echo_client_DEPENDENCIES) $(EXTRA_echo_blocking_udp_echo_client_DEPENDENCIES) echo/$(am__dirstamp) + @rm -f echo/blocking_udp_echo_client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(echo_blocking_udp_echo_client_OBJECTS) $(echo_blocking_udp_echo_client_LDADD) $(LIBS) +echo/blocking_udp_echo_server.$(OBJEXT): echo/$(am__dirstamp) \ + echo/$(DEPDIR)/$(am__dirstamp) + +echo/blocking_udp_echo_server$(EXEEXT): $(echo_blocking_udp_echo_server_OBJECTS) $(echo_blocking_udp_echo_server_DEPENDENCIES) $(EXTRA_echo_blocking_udp_echo_server_DEPENDENCIES) echo/$(am__dirstamp) + @rm -f echo/blocking_udp_echo_server$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(echo_blocking_udp_echo_server_OBJECTS) $(echo_blocking_udp_echo_server_LDADD) $(LIBS) +executors/$(am__dirstamp): + @$(MKDIR_P) executors + @: > executors/$(am__dirstamp) +executors/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) executors/$(DEPDIR) + @: > executors/$(DEPDIR)/$(am__dirstamp) +executors/actor.$(OBJEXT): executors/$(am__dirstamp) \ + executors/$(DEPDIR)/$(am__dirstamp) + +executors/actor$(EXEEXT): $(executors_actor_OBJECTS) $(executors_actor_DEPENDENCIES) $(EXTRA_executors_actor_DEPENDENCIES) executors/$(am__dirstamp) + @rm -f executors/actor$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(executors_actor_OBJECTS) $(executors_actor_LDADD) $(LIBS) +executors/async_1.$(OBJEXT): executors/$(am__dirstamp) \ + executors/$(DEPDIR)/$(am__dirstamp) + +executors/async_1$(EXEEXT): $(executors_async_1_OBJECTS) $(executors_async_1_DEPENDENCIES) $(EXTRA_executors_async_1_DEPENDENCIES) executors/$(am__dirstamp) + @rm -f executors/async_1$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(executors_async_1_OBJECTS) $(executors_async_1_LDADD) $(LIBS) +executors/async_2.$(OBJEXT): executors/$(am__dirstamp) \ + executors/$(DEPDIR)/$(am__dirstamp) + +executors/async_2$(EXEEXT): $(executors_async_2_OBJECTS) $(executors_async_2_DEPENDENCIES) $(EXTRA_executors_async_2_DEPENDENCIES) executors/$(am__dirstamp) + @rm -f executors/async_2$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(executors_async_2_OBJECTS) $(executors_async_2_LDADD) $(LIBS) +executors/bank_account_1.$(OBJEXT): executors/$(am__dirstamp) \ + executors/$(DEPDIR)/$(am__dirstamp) + +executors/bank_account_1$(EXEEXT): $(executors_bank_account_1_OBJECTS) $(executors_bank_account_1_DEPENDENCIES) $(EXTRA_executors_bank_account_1_DEPENDENCIES) executors/$(am__dirstamp) + @rm -f executors/bank_account_1$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(executors_bank_account_1_OBJECTS) $(executors_bank_account_1_LDADD) $(LIBS) +executors/bank_account_2.$(OBJEXT): executors/$(am__dirstamp) \ + executors/$(DEPDIR)/$(am__dirstamp) + +executors/bank_account_2$(EXEEXT): $(executors_bank_account_2_OBJECTS) $(executors_bank_account_2_DEPENDENCIES) $(EXTRA_executors_bank_account_2_DEPENDENCIES) executors/$(am__dirstamp) + @rm -f executors/bank_account_2$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(executors_bank_account_2_OBJECTS) $(executors_bank_account_2_LDADD) $(LIBS) +executors/fork_join.$(OBJEXT): executors/$(am__dirstamp) \ + executors/$(DEPDIR)/$(am__dirstamp) + +executors/fork_join$(EXEEXT): $(executors_fork_join_OBJECTS) $(executors_fork_join_DEPENDENCIES) $(EXTRA_executors_fork_join_DEPENDENCIES) executors/$(am__dirstamp) + @rm -f executors/fork_join$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(executors_fork_join_OBJECTS) $(executors_fork_join_LDADD) $(LIBS) +executors/pipeline.$(OBJEXT): executors/$(am__dirstamp) \ + executors/$(DEPDIR)/$(am__dirstamp) + +executors/pipeline$(EXEEXT): $(executors_pipeline_OBJECTS) $(executors_pipeline_DEPENDENCIES) $(EXTRA_executors_pipeline_DEPENDENCIES) executors/$(am__dirstamp) + @rm -f executors/pipeline$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(executors_pipeline_OBJECTS) $(executors_pipeline_LDADD) $(LIBS) +executors/priority_scheduler.$(OBJEXT): executors/$(am__dirstamp) \ + executors/$(DEPDIR)/$(am__dirstamp) + +executors/priority_scheduler$(EXEEXT): $(executors_priority_scheduler_OBJECTS) $(executors_priority_scheduler_DEPENDENCIES) $(EXTRA_executors_priority_scheduler_DEPENDENCIES) executors/$(am__dirstamp) + @rm -f executors/priority_scheduler$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(executors_priority_scheduler_OBJECTS) $(executors_priority_scheduler_LDADD) $(LIBS) +iostreams/$(am__dirstamp): + @$(MKDIR_P) iostreams + @: > iostreams/$(am__dirstamp) +iostreams/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) iostreams/$(DEPDIR) + @: > iostreams/$(DEPDIR)/$(am__dirstamp) +iostreams/http_client.$(OBJEXT): iostreams/$(am__dirstamp) \ + iostreams/$(DEPDIR)/$(am__dirstamp) + +iostreams/http_client$(EXEEXT): $(iostreams_http_client_OBJECTS) $(iostreams_http_client_DEPENDENCIES) $(EXTRA_iostreams_http_client_DEPENDENCIES) iostreams/$(am__dirstamp) + @rm -f iostreams/http_client$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(iostreams_http_client_OBJECTS) $(iostreams_http_client_LDADD) $(LIBS) +operations/$(am__dirstamp): + @$(MKDIR_P) operations + @: > operations/$(am__dirstamp) +operations/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) operations/$(DEPDIR) + @: > operations/$(DEPDIR)/$(am__dirstamp) +operations/c_callback_wrapper.$(OBJEXT): operations/$(am__dirstamp) \ + operations/$(DEPDIR)/$(am__dirstamp) + +operations/c_callback_wrapper$(EXEEXT): $(operations_c_callback_wrapper_OBJECTS) $(operations_c_callback_wrapper_DEPENDENCIES) $(EXTRA_operations_c_callback_wrapper_DEPENDENCIES) operations/$(am__dirstamp) + @rm -f operations/c_callback_wrapper$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(operations_c_callback_wrapper_OBJECTS) $(operations_c_callback_wrapper_LDADD) $(LIBS) +operations/callback_wrapper.$(OBJEXT): operations/$(am__dirstamp) \ + operations/$(DEPDIR)/$(am__dirstamp) + +operations/callback_wrapper$(EXEEXT): $(operations_callback_wrapper_OBJECTS) $(operations_callback_wrapper_DEPENDENCIES) $(EXTRA_operations_callback_wrapper_DEPENDENCIES) operations/$(am__dirstamp) + @rm -f operations/callback_wrapper$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(operations_callback_wrapper_OBJECTS) $(operations_callback_wrapper_LDADD) $(LIBS) +operations/composed_1.$(OBJEXT): operations/$(am__dirstamp) \ + operations/$(DEPDIR)/$(am__dirstamp) + +operations/composed_1$(EXEEXT): $(operations_composed_1_OBJECTS) $(operations_composed_1_DEPENDENCIES) $(EXTRA_operations_composed_1_DEPENDENCIES) operations/$(am__dirstamp) + @rm -f operations/composed_1$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(operations_composed_1_OBJECTS) $(operations_composed_1_LDADD) $(LIBS) +operations/composed_2.$(OBJEXT): operations/$(am__dirstamp) \ + operations/$(DEPDIR)/$(am__dirstamp) + +operations/composed_2$(EXEEXT): $(operations_composed_2_OBJECTS) $(operations_composed_2_DEPENDENCIES) $(EXTRA_operations_composed_2_DEPENDENCIES) operations/$(am__dirstamp) + @rm -f operations/composed_2$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(operations_composed_2_OBJECTS) $(operations_composed_2_LDADD) $(LIBS) +operations/composed_3.$(OBJEXT): operations/$(am__dirstamp) \ + operations/$(DEPDIR)/$(am__dirstamp) + +operations/composed_3$(EXEEXT): $(operations_composed_3_OBJECTS) $(operations_composed_3_DEPENDENCIES) $(EXTRA_operations_composed_3_DEPENDENCIES) operations/$(am__dirstamp) + @rm -f operations/composed_3$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(operations_composed_3_OBJECTS) $(operations_composed_3_LDADD) $(LIBS) +operations/composed_4.$(OBJEXT): operations/$(am__dirstamp) \ + operations/$(DEPDIR)/$(am__dirstamp) + +operations/composed_4$(EXEEXT): $(operations_composed_4_OBJECTS) $(operations_composed_4_DEPENDENCIES) $(EXTRA_operations_composed_4_DEPENDENCIES) operations/$(am__dirstamp) + @rm -f operations/composed_4$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(operations_composed_4_OBJECTS) $(operations_composed_4_LDADD) $(LIBS) +operations/composed_5.$(OBJEXT): operations/$(am__dirstamp) \ + operations/$(DEPDIR)/$(am__dirstamp) + +operations/composed_5$(EXEEXT): $(operations_composed_5_OBJECTS) $(operations_composed_5_DEPENDENCIES) $(EXTRA_operations_composed_5_DEPENDENCIES) operations/$(am__dirstamp) + @rm -f operations/composed_5$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(operations_composed_5_OBJECTS) $(operations_composed_5_LDADD) $(LIBS) +operations/composed_6.$(OBJEXT): operations/$(am__dirstamp) \ + operations/$(DEPDIR)/$(am__dirstamp) + +operations/composed_6$(EXEEXT): $(operations_composed_6_OBJECTS) $(operations_composed_6_DEPENDENCIES) $(EXTRA_operations_composed_6_DEPENDENCIES) operations/$(am__dirstamp) + @rm -f operations/composed_6$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(operations_composed_6_OBJECTS) $(operations_composed_6_LDADD) $(LIBS) +operations/composed_7.$(OBJEXT): operations/$(am__dirstamp) \ + operations/$(DEPDIR)/$(am__dirstamp) + +operations/composed_7$(EXEEXT): $(operations_composed_7_OBJECTS) $(operations_composed_7_DEPENDENCIES) $(EXTRA_operations_composed_7_DEPENDENCIES) operations/$(am__dirstamp) + @rm -f operations/composed_7$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(operations_composed_7_OBJECTS) $(operations_composed_7_LDADD) $(LIBS) +operations/composed_8.$(OBJEXT): operations/$(am__dirstamp) \ + operations/$(DEPDIR)/$(am__dirstamp) + +operations/composed_8$(EXEEXT): $(operations_composed_8_OBJECTS) $(operations_composed_8_DEPENDENCIES) $(EXTRA_operations_composed_8_DEPENDENCIES) operations/$(am__dirstamp) + @rm -f operations/composed_8$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(operations_composed_8_OBJECTS) $(operations_composed_8_LDADD) $(LIBS) +parallel_group/$(am__dirstamp): + @$(MKDIR_P) parallel_group + @: > parallel_group/$(am__dirstamp) +parallel_group/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) parallel_group/$(DEPDIR) + @: > parallel_group/$(DEPDIR)/$(am__dirstamp) +parallel_group/parallel_sort.$(OBJEXT): \ + parallel_group/$(am__dirstamp) \ + parallel_group/$(DEPDIR)/$(am__dirstamp) + +parallel_group/parallel_sort$(EXEEXT): $(parallel_group_parallel_sort_OBJECTS) $(parallel_group_parallel_sort_DEPENDENCIES) $(EXTRA_parallel_group_parallel_sort_DEPENDENCIES) parallel_group/$(am__dirstamp) + @rm -f parallel_group/parallel_sort$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parallel_group_parallel_sort_OBJECTS) $(parallel_group_parallel_sort_LDADD) $(LIBS) +parallel_group/ranged_wait_for_all.$(OBJEXT): \ + parallel_group/$(am__dirstamp) \ + parallel_group/$(DEPDIR)/$(am__dirstamp) + +parallel_group/ranged_wait_for_all$(EXEEXT): $(parallel_group_ranged_wait_for_all_OBJECTS) $(parallel_group_ranged_wait_for_all_DEPENDENCIES) $(EXTRA_parallel_group_ranged_wait_for_all_DEPENDENCIES) parallel_group/$(am__dirstamp) + @rm -f parallel_group/ranged_wait_for_all$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parallel_group_ranged_wait_for_all_OBJECTS) $(parallel_group_ranged_wait_for_all_LDADD) $(LIBS) +parallel_group/wait_for_all.$(OBJEXT): parallel_group/$(am__dirstamp) \ + parallel_group/$(DEPDIR)/$(am__dirstamp) + +parallel_group/wait_for_all$(EXEEXT): $(parallel_group_wait_for_all_OBJECTS) $(parallel_group_wait_for_all_DEPENDENCIES) $(EXTRA_parallel_group_wait_for_all_DEPENDENCIES) parallel_group/$(am__dirstamp) + @rm -f parallel_group/wait_for_all$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parallel_group_wait_for_all_OBJECTS) $(parallel_group_wait_for_all_LDADD) $(LIBS) +parallel_group/wait_for_one.$(OBJEXT): parallel_group/$(am__dirstamp) \ + parallel_group/$(DEPDIR)/$(am__dirstamp) + +parallel_group/wait_for_one$(EXEEXT): $(parallel_group_wait_for_one_OBJECTS) $(parallel_group_wait_for_one_DEPENDENCIES) $(EXTRA_parallel_group_wait_for_one_DEPENDENCIES) parallel_group/$(am__dirstamp) + @rm -f parallel_group/wait_for_one$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parallel_group_wait_for_one_OBJECTS) $(parallel_group_wait_for_one_LDADD) $(LIBS) +parallel_group/wait_for_one_error.$(OBJEXT): \ + parallel_group/$(am__dirstamp) \ + parallel_group/$(DEPDIR)/$(am__dirstamp) + +parallel_group/wait_for_one_error$(EXEEXT): $(parallel_group_wait_for_one_error_OBJECTS) $(parallel_group_wait_for_one_error_DEPENDENCIES) $(EXTRA_parallel_group_wait_for_one_error_DEPENDENCIES) parallel_group/$(am__dirstamp) + @rm -f parallel_group/wait_for_one_error$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parallel_group_wait_for_one_error_OBJECTS) $(parallel_group_wait_for_one_error_LDADD) $(LIBS) +parallel_group/wait_for_one_success.$(OBJEXT): \ + parallel_group/$(am__dirstamp) \ + parallel_group/$(DEPDIR)/$(am__dirstamp) + +parallel_group/wait_for_one_success$(EXEEXT): $(parallel_group_wait_for_one_success_OBJECTS) $(parallel_group_wait_for_one_success_DEPENDENCIES) $(EXTRA_parallel_group_wait_for_one_success_DEPENDENCIES) parallel_group/$(am__dirstamp) + @rm -f parallel_group/wait_for_one_success$(EXEEXT) + $(AM_V_CXXLD)$(CXXLINK) $(parallel_group_wait_for_one_success_OBJECTS) $(parallel_group_wait_for_one_success_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + -rm -f ../../*.$(OBJEXT) + -rm -f deferred/*.$(OBJEXT) + -rm -f echo/*.$(OBJEXT) + -rm -f executors/*.$(OBJEXT) + -rm -f iostreams/*.$(OBJEXT) + -rm -f operations/*.$(OBJEXT) + -rm -f parallel_group/*.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@../../$(DEPDIR)/asio.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@../../$(DEPDIR)/asio_ssl.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@deferred/$(DEPDIR)/deferred_1.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@deferred/$(DEPDIR)/deferred_2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@deferred/$(DEPDIR)/deferred_3.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@deferred/$(DEPDIR)/deferred_4.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@deferred/$(DEPDIR)/deferred_5.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@deferred/$(DEPDIR)/deferred_6.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@deferred/$(DEPDIR)/deferred_7.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@echo/$(DEPDIR)/async_tcp_echo_server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@echo/$(DEPDIR)/async_udp_echo_server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@echo/$(DEPDIR)/blocking_tcp_echo_client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@echo/$(DEPDIR)/blocking_tcp_echo_server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@echo/$(DEPDIR)/blocking_udp_echo_client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@echo/$(DEPDIR)/blocking_udp_echo_server.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@executors/$(DEPDIR)/actor.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@executors/$(DEPDIR)/async_1.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@executors/$(DEPDIR)/async_2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@executors/$(DEPDIR)/bank_account_1.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@executors/$(DEPDIR)/bank_account_2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@executors/$(DEPDIR)/fork_join.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@executors/$(DEPDIR)/pipeline.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@executors/$(DEPDIR)/priority_scheduler.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@iostreams/$(DEPDIR)/http_client.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/c_callback_wrapper.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/callback_wrapper.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/composed_1.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/composed_2.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/composed_3.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/composed_4.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/composed_5.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/composed_6.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/composed_7.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@operations/$(DEPDIR)/composed_8.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@parallel_group/$(DEPDIR)/parallel_sort.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@parallel_group/$(DEPDIR)/ranged_wait_for_all.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@parallel_group/$(DEPDIR)/wait_for_all.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@parallel_group/$(DEPDIR)/wait_for_one.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@parallel_group/$(DEPDIR)/wait_for_one_error.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@parallel_group/$(DEPDIR)/wait_for_one_success.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCXX_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(LIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f ../../$(DEPDIR)/$(am__dirstamp) + -rm -f ../../$(am__dirstamp) + -rm -f deferred/$(DEPDIR)/$(am__dirstamp) + -rm -f deferred/$(am__dirstamp) + -rm -f echo/$(DEPDIR)/$(am__dirstamp) + -rm -f echo/$(am__dirstamp) + -rm -f executors/$(DEPDIR)/$(am__dirstamp) + -rm -f executors/$(am__dirstamp) + -rm -f iostreams/$(DEPDIR)/$(am__dirstamp) + -rm -f iostreams/$(am__dirstamp) + -rm -f operations/$(DEPDIR)/$(am__dirstamp) + -rm -f operations/$(am__dirstamp) + -rm -f parallel_group/$(DEPDIR)/$(am__dirstamp) + -rm -f parallel_group/$(am__dirstamp) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -f ../../$(DEPDIR)/asio.Po + -rm -f ../../$(DEPDIR)/asio_ssl.Po + -rm -f deferred/$(DEPDIR)/deferred_1.Po + -rm -f deferred/$(DEPDIR)/deferred_2.Po + -rm -f deferred/$(DEPDIR)/deferred_3.Po + -rm -f deferred/$(DEPDIR)/deferred_4.Po + -rm -f deferred/$(DEPDIR)/deferred_5.Po + -rm -f deferred/$(DEPDIR)/deferred_6.Po + -rm -f deferred/$(DEPDIR)/deferred_7.Po + -rm -f echo/$(DEPDIR)/async_tcp_echo_server.Po + -rm -f echo/$(DEPDIR)/async_udp_echo_server.Po + -rm -f echo/$(DEPDIR)/blocking_tcp_echo_client.Po + -rm -f echo/$(DEPDIR)/blocking_tcp_echo_server.Po + -rm -f echo/$(DEPDIR)/blocking_udp_echo_client.Po + -rm -f echo/$(DEPDIR)/blocking_udp_echo_server.Po + -rm -f executors/$(DEPDIR)/actor.Po + -rm -f executors/$(DEPDIR)/async_1.Po + -rm -f executors/$(DEPDIR)/async_2.Po + -rm -f executors/$(DEPDIR)/bank_account_1.Po + -rm -f executors/$(DEPDIR)/bank_account_2.Po + -rm -f executors/$(DEPDIR)/fork_join.Po + -rm -f executors/$(DEPDIR)/pipeline.Po + -rm -f executors/$(DEPDIR)/priority_scheduler.Po + -rm -f iostreams/$(DEPDIR)/http_client.Po + -rm -f operations/$(DEPDIR)/c_callback_wrapper.Po + -rm -f operations/$(DEPDIR)/callback_wrapper.Po + -rm -f operations/$(DEPDIR)/composed_1.Po + -rm -f operations/$(DEPDIR)/composed_2.Po + -rm -f operations/$(DEPDIR)/composed_3.Po + -rm -f operations/$(DEPDIR)/composed_4.Po + -rm -f operations/$(DEPDIR)/composed_5.Po + -rm -f operations/$(DEPDIR)/composed_6.Po + -rm -f operations/$(DEPDIR)/composed_7.Po + -rm -f operations/$(DEPDIR)/composed_8.Po + -rm -f parallel_group/$(DEPDIR)/parallel_sort.Po + -rm -f parallel_group/$(DEPDIR)/ranged_wait_for_all.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_all.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one_error.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one_success.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ../../$(DEPDIR)/asio.Po + -rm -f ../../$(DEPDIR)/asio_ssl.Po + -rm -f deferred/$(DEPDIR)/deferred_1.Po + -rm -f deferred/$(DEPDIR)/deferred_2.Po + -rm -f deferred/$(DEPDIR)/deferred_3.Po + -rm -f deferred/$(DEPDIR)/deferred_4.Po + -rm -f deferred/$(DEPDIR)/deferred_5.Po + -rm -f deferred/$(DEPDIR)/deferred_6.Po + -rm -f deferred/$(DEPDIR)/deferred_7.Po + -rm -f echo/$(DEPDIR)/async_tcp_echo_server.Po + -rm -f echo/$(DEPDIR)/async_udp_echo_server.Po + -rm -f echo/$(DEPDIR)/blocking_tcp_echo_client.Po + -rm -f echo/$(DEPDIR)/blocking_tcp_echo_server.Po + -rm -f echo/$(DEPDIR)/blocking_udp_echo_client.Po + -rm -f echo/$(DEPDIR)/blocking_udp_echo_server.Po + -rm -f executors/$(DEPDIR)/actor.Po + -rm -f executors/$(DEPDIR)/async_1.Po + -rm -f executors/$(DEPDIR)/async_2.Po + -rm -f executors/$(DEPDIR)/bank_account_1.Po + -rm -f executors/$(DEPDIR)/bank_account_2.Po + -rm -f executors/$(DEPDIR)/fork_join.Po + -rm -f executors/$(DEPDIR)/pipeline.Po + -rm -f executors/$(DEPDIR)/priority_scheduler.Po + -rm -f iostreams/$(DEPDIR)/http_client.Po + -rm -f operations/$(DEPDIR)/c_callback_wrapper.Po + -rm -f operations/$(DEPDIR)/callback_wrapper.Po + -rm -f operations/$(DEPDIR)/composed_1.Po + -rm -f operations/$(DEPDIR)/composed_2.Po + -rm -f operations/$(DEPDIR)/composed_3.Po + -rm -f operations/$(DEPDIR)/composed_4.Po + -rm -f operations/$(DEPDIR)/composed_5.Po + -rm -f operations/$(DEPDIR)/composed_6.Po + -rm -f operations/$(DEPDIR)/composed_7.Po + -rm -f operations/$(DEPDIR)/composed_8.Po + -rm -f parallel_group/$(DEPDIR)/parallel_sort.Po + -rm -f parallel_group/$(DEPDIR)/ranged_wait_for_all.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_all.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one_error.Po + -rm -f parallel_group/$(DEPDIR)/wait_for_one_success.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-noinstLIBRARIES clean-noinstPROGRAMS \ + cscopelist-am ctags ctags-am distclean distclean-compile \ + distclean-generic distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \ + uninstall-am + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/3rdparty/asio/src/examples/cpp14/deferred/deferred_1.cpp b/3rdparty/asio/src/examples/cpp14/deferred/deferred_1.cpp new file mode 100644 index 00000000000..db9213eb3be --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/deferred/deferred_1.cpp @@ -0,0 +1,35 @@ +// +// deferred_1.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <iostream> + +using asio::deferred; + +int main() +{ + asio::io_context ctx; + + asio::steady_timer timer(ctx); + timer.expires_after(std::chrono::seconds(1)); + + auto deferred_op = timer.async_wait(deferred); + + std::move(deferred_op)( + [](std::error_code ec) + { + std::cout << "timer wait finished: " << ec.message() << "\n"; + } + ); + + ctx.run(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp14/deferred/deferred_2.cpp b/3rdparty/asio/src/examples/cpp14/deferred/deferred_2.cpp new file mode 100644 index 00000000000..07528282de5 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/deferred/deferred_2.cpp @@ -0,0 +1,44 @@ +// +// deferred_2.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <iostream> + +using asio::deferred; + +int main() +{ + asio::io_context ctx; + + asio::steady_timer timer(ctx); + timer.expires_after(std::chrono::seconds(1)); + + auto deferred_op = timer.async_wait( + deferred( + [&](std::error_code ec) + { + std::cout << "first timer wait finished: " << ec.message() << "\n"; + timer.expires_after(std::chrono::seconds(1)); + return timer.async_wait(deferred); + } + ) + ); + + std::move(deferred_op)( + [](std::error_code ec) + { + std::cout << "second timer wait finished: " << ec.message() << "\n"; + } + ); + + ctx.run(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp14/deferred/deferred_3.cpp b/3rdparty/asio/src/examples/cpp14/deferred/deferred_3.cpp new file mode 100644 index 00000000000..396e40840a1 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/deferred/deferred_3.cpp @@ -0,0 +1,51 @@ +// +// deferred_3.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <iostream> + +using asio::deferred; + +template <typename CompletionToken> +auto async_wait_twice(asio::steady_timer& timer, CompletionToken&& token) +{ + return timer.async_wait( + deferred( + [&](std::error_code ec) + { + std::cout << "first timer wait finished: " << ec.message() << "\n"; + timer.expires_after(std::chrono::seconds(1)); + return timer.async_wait(deferred); + } + ) + )( + std::forward<CompletionToken>(token) + ); +} + +int main() +{ + asio::io_context ctx; + + asio::steady_timer timer(ctx); + timer.expires_after(std::chrono::seconds(1)); + + async_wait_twice( + timer, + [](std::error_code ec) + { + std::cout << "second timer wait finished: " << ec.message() << "\n"; + } + ); + + ctx.run(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp14/deferred/deferred_4.cpp b/3rdparty/asio/src/examples/cpp14/deferred/deferred_4.cpp new file mode 100644 index 00000000000..a8ea73336d2 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/deferred/deferred_4.cpp @@ -0,0 +1,59 @@ +// +// deferred_4.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <iostream> + +using asio::deferred; + +template <typename CompletionToken> +auto async_wait_twice(asio::steady_timer& timer, CompletionToken&& token) +{ + return timer.async_wait( + deferred( + [&](std::error_code ec) + { + std::cout << "first timer wait finished: " << ec.message() << "\n"; + timer.expires_after(std::chrono::seconds(1)); + return timer.async_wait(deferred); + } + ) + )( + deferred( + [&](std::error_code ec) + { + std::cout << "second timer wait finished: " << ec.message() << "\n"; + return deferred.values(42); + } + ) + )( + std::forward<CompletionToken>(token) + ); +} + +int main() +{ + asio::io_context ctx; + + asio::steady_timer timer(ctx); + timer.expires_after(std::chrono::seconds(1)); + + async_wait_twice( + timer, + [](int result) + { + std::cout << "result is " << result << "\n"; + } + ); + + ctx.run(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp14/deferred/deferred_5.cpp b/3rdparty/asio/src/examples/cpp14/deferred/deferred_5.cpp new file mode 100644 index 00000000000..d262b977811 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/deferred/deferred_5.cpp @@ -0,0 +1,66 @@ +// +// deferred_5.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <iostream> + +using asio::deferred; + +template <typename CompletionToken> +auto async_wait_twice(asio::steady_timer& timer, CompletionToken&& token) +{ + return timer.async_wait( + deferred( + [&](std::error_code ec) + { + std::cout << "first timer wait finished: " << ec.message() << "\n"; + timer.expires_after(std::chrono::seconds(1)); + return deferred.when(!ec) + .then(timer.async_wait(deferred)) + .otherwise(deferred.values(ec)); + } + ) + )( + deferred( + [&](std::error_code ec) + { + std::cout << "second timer wait finished: " << ec.message() << "\n"; + return deferred.when(!ec) + .then(deferred.values(42)) + .otherwise(deferred.values(0)); + } + ) + )( + std::forward<CompletionToken>(token) + ); +} + +int main() +{ + asio::io_context ctx; + + asio::steady_timer timer(ctx); + timer.expires_after(std::chrono::seconds(1)); + + async_wait_twice( + timer, + [](int result) + { + std::cout << "result is " << result << "\n"; + } + ); + + // Uncomment the following line to trigger an error in async_wait_twice. + //timer.cancel(); + + ctx.run(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp14/deferred/deferred_6.cpp b/3rdparty/asio/src/examples/cpp14/deferred/deferred_6.cpp new file mode 100644 index 00000000000..7ccef58cc5c --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/deferred/deferred_6.cpp @@ -0,0 +1,75 @@ +// +// deferred_6.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <iostream> + +using asio::append; +using asio::deferred; + +template <typename CompletionToken> +auto async_wait_twice(asio::steady_timer& timer, CompletionToken&& token) +{ + return deferred.values(&timer)( + deferred( + [](asio::steady_timer* timer) + { + timer->expires_after(std::chrono::seconds(1)); + return timer->async_wait(append(deferred, timer)); + } + ) + )( + deferred( + [](std::error_code ec, asio::steady_timer* timer) + { + std::cout << "first timer wait finished: " << ec.message() << "\n"; + timer->expires_after(std::chrono::seconds(1)); + return deferred.when(!ec) + .then(timer->async_wait(deferred)) + .otherwise(deferred.values(ec)); + } + ) + )( + deferred( + [](std::error_code ec) + { + std::cout << "second timer wait finished: " << ec.message() << "\n"; + return deferred.when(!ec) + .then(deferred.values(42)) + .otherwise(deferred.values(0)); + } + ) + )( + std::forward<CompletionToken>(token) + ); +} + +int main() +{ + asio::io_context ctx; + + asio::steady_timer timer(ctx); + timer.expires_after(std::chrono::seconds(1)); + + async_wait_twice( + timer, + [](int result) + { + std::cout << "result is " << result << "\n"; + } + ); + + // Uncomment the following line to trigger an error in async_wait_twice. + //timer.cancel(); + + ctx.run(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp14/deferred/deferred_7.cpp b/3rdparty/asio/src/examples/cpp14/deferred/deferred_7.cpp new file mode 100644 index 00000000000..b0734542c79 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/deferred/deferred_7.cpp @@ -0,0 +1,71 @@ +// +// deferred_7.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <iostream> + +using asio::append; +using asio::deferred; + +template <typename CompletionToken> +auto async_wait_twice(asio::steady_timer& timer, CompletionToken&& token) +{ + return deferred.values(&timer) + | deferred( + [](asio::steady_timer* timer) + { + timer->expires_after(std::chrono::seconds(1)); + return timer->async_wait(append(deferred, timer)); + } + ) + | deferred( + [](std::error_code ec, asio::steady_timer* timer) + { + std::cout << "first timer wait finished: " << ec.message() << "\n"; + timer->expires_after(std::chrono::seconds(1)); + return deferred.when(!ec) + .then(timer->async_wait(deferred)) + .otherwise(deferred.values(ec)); + } + ) + | deferred( + [](std::error_code ec) + { + std::cout << "second timer wait finished: " << ec.message() << "\n"; + return deferred.when(!ec) + .then(deferred.values(42)) + .otherwise(deferred.values(0)); + } + ) + | std::forward<CompletionToken>(token); +} + +int main() +{ + asio::io_context ctx; + + asio::steady_timer timer(ctx); + timer.expires_after(std::chrono::seconds(1)); + + async_wait_twice( + timer, + [](int result) + { + std::cout << "result is " << result << "\n"; + } + ); + + // Uncomment the following line to trigger an error in async_wait_twice. + //timer.cancel(); + + ctx.run(); + + return 0; +} diff --git a/3rdparty/asio/src/examples/cpp14/echo/.gitignore b/3rdparty/asio/src/examples/cpp14/echo/.gitignore deleted file mode 100644 index 0882fa6ced3..00000000000 --- a/3rdparty/asio/src/examples/cpp14/echo/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -.deps -.dirstamp -*.o -*.obj -*.exe -*_server -*_client -*.ilk -*.manifest -*.pdb -*.tds diff --git a/3rdparty/asio/src/examples/cpp14/echo/async_tcp_echo_server.cpp b/3rdparty/asio/src/examples/cpp14/echo/async_tcp_echo_server.cpp index c6004c0a0e5..9bd1b727500 100644 --- a/3rdparty/asio/src/examples/cpp14/echo/async_tcp_echo_server.cpp +++ b/3rdparty/asio/src/examples/cpp14/echo/async_tcp_echo_server.cpp @@ -2,7 +2,7 @@ // async_tcp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the 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/src/examples/cpp14/echo/async_udp_echo_server.cpp b/3rdparty/asio/src/examples/cpp14/echo/async_udp_echo_server.cpp index fee8aed6e66..b059af95b82 100644 --- a/3rdparty/asio/src/examples/cpp14/echo/async_udp_echo_server.cpp +++ b/3rdparty/asio/src/examples/cpp14/echo/async_udp_echo_server.cpp @@ -2,7 +2,7 @@ // async_udp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the 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/src/examples/cpp14/echo/blocking_tcp_echo_client.cpp b/3rdparty/asio/src/examples/cpp14/echo/blocking_tcp_echo_client.cpp index c7c648df97f..8a281203f89 100644 --- a/3rdparty/asio/src/examples/cpp14/echo/blocking_tcp_echo_client.cpp +++ b/3rdparty/asio/src/examples/cpp14/echo/blocking_tcp_echo_client.cpp @@ -2,7 +2,7 @@ // blocking_tcp_echo_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the 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/src/examples/cpp14/echo/blocking_tcp_echo_server.cpp b/3rdparty/asio/src/examples/cpp14/echo/blocking_tcp_echo_server.cpp index d9a4f075a8d..2116712616a 100644 --- a/3rdparty/asio/src/examples/cpp14/echo/blocking_tcp_echo_server.cpp +++ b/3rdparty/asio/src/examples/cpp14/echo/blocking_tcp_echo_server.cpp @@ -2,7 +2,7 @@ // blocking_tcp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the 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/src/examples/cpp14/echo/blocking_udp_echo_client.cpp b/3rdparty/asio/src/examples/cpp14/echo/blocking_udp_echo_client.cpp index 603a591f47a..4c8a2849d5b 100644 --- a/3rdparty/asio/src/examples/cpp14/echo/blocking_udp_echo_client.cpp +++ b/3rdparty/asio/src/examples/cpp14/echo/blocking_udp_echo_client.cpp @@ -2,7 +2,7 @@ // blocking_udp_echo_client.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the 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/src/examples/cpp14/echo/blocking_udp_echo_server.cpp b/3rdparty/asio/src/examples/cpp14/echo/blocking_udp_echo_server.cpp index 646fd136649..c3098bdb8fc 100644 --- a/3rdparty/asio/src/examples/cpp14/echo/blocking_udp_echo_server.cpp +++ b/3rdparty/asio/src/examples/cpp14/echo/blocking_udp_echo_server.cpp @@ -2,7 +2,7 @@ // blocking_udp_echo_server.cpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the 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/src/examples/cpp14/executors/.gitignore b/3rdparty/asio/src/examples/cpp14/executors/.gitignore deleted file mode 100644 index d51d7f00295..00000000000 --- a/3rdparty/asio/src/examples/cpp14/executors/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -actor -async_[0-9] -bank_account_[0-9] -fork_join -pipeline -priority_scheduler diff --git a/3rdparty/asio/src/examples/cpp14/executors/actor.cpp b/3rdparty/asio/src/examples/cpp14/executors/actor.cpp index 26d2fb4bf11..a46caf45a68 100644 --- a/3rdparty/asio/src/examples/cpp14/executors/actor.cpp +++ b/3rdparty/asio/src/examples/cpp14/executors/actor.cpp @@ -1,4 +1,8 @@ -#include <asio/ts/executor.hpp> +#include <asio/any_io_executor.hpp> +#include <asio/defer.hpp> +#include <asio/post.hpp> +#include <asio/strand.hpp> +#include <asio/system_executor.hpp> #include <condition_variable> #include <deque> #include <memory> @@ -6,8 +10,8 @@ #include <typeinfo> #include <vector> +using asio::any_io_executor; using asio::defer; -using asio::executor; using asio::post; using asio::strand; using asio::system_executor; @@ -94,7 +98,7 @@ public: { // Execute the message handler in the context of the target's executor. post(to->executor_, - [=, msg=std::move(msg)] + [=, msg=std::move(msg)]() mutable { to->call_handler(std::move(msg), from); }); @@ -102,7 +106,7 @@ public: protected: // Construct the actor to use the specified executor for all message handlers. - actor(executor e) + actor(any_io_executor e) : executor_(std::move(e)) { } @@ -120,7 +124,7 @@ protected: template <class Actor, class Message> void deregister_handler(void (Actor::* mf)(Message, actor_address)) { - const std::type_info& id = typeid(message_handler<Message>); + const std::type_info& id = typeid(Message); for (auto iter = handlers_.begin(); iter != handlers_.end(); ++iter) { if ((*iter)->message_id() == id) @@ -166,7 +170,7 @@ private: // All messages associated with a single actor object should be processed // non-concurrently. We use a strand to ensure non-concurrent execution even // if the underlying executor may use multiple threads. - strand<executor> executor_; + strand<any_io_executor> executor_; std::vector<std::shared_ptr<message_handler_base>> handlers_; }; @@ -216,7 +220,7 @@ using asio::thread_pool; class member : public actor { public: - explicit member(executor e) + explicit member(any_io_executor e) : actor(std::move(e)) { register_handler(&member::init_handler); diff --git a/3rdparty/asio/src/examples/cpp14/executors/async_1.cpp b/3rdparty/asio/src/examples/cpp14/executors/async_1.cpp index d282b74f206..0d1bdfcb8bd 100644 --- a/3rdparty/asio/src/examples/cpp14/executors/async_1.cpp +++ b/3rdparty/asio/src/examples/cpp14/executors/async_1.cpp @@ -1,29 +1,33 @@ -#include <asio/ts/executor.hpp> -#include <asio/thread_pool.hpp> +#include <asio/associated_executor.hpp> +#include <asio/bind_executor.hpp> +#include <asio/execution.hpp> +#include <asio/static_thread_pool.hpp> #include <iostream> #include <string> using asio::bind_executor; -using asio::dispatch; -using asio::make_work_guard; -using asio::post; -using asio::thread_pool; +using asio::get_associated_executor; +using asio::static_thread_pool; +namespace execution = asio::execution; // A function to asynchronously read a single line from an input stream. -template <class Handler> -void async_getline(std::istream& is, Handler handler) +template <class IoExecutor, class Handler> +void async_getline(IoExecutor io_ex, std::istream& is, Handler handler) { - // Create executor_work for the handler's associated executor. - auto work = make_work_guard(handler); + // Track work for the handler's associated executor. + auto work_ex = asio::prefer( + get_associated_executor(handler, io_ex), + execution::outstanding_work.tracked); // Post a function object to do the work asynchronously. - post([&is, work, handler=std::move(handler)]() mutable + asio::require(io_ex, execution::blocking.never).execute( + [&is, work_ex, handler=std::move(handler)]() mutable { std::string line; std::getline(is, line); // Pass the result to the handler, via the associated executor. - dispatch(work.get_executor(), + asio::prefer(work_ex, execution::blocking.possibly).execute( [line=std::move(line), handler=std::move(handler)]() mutable { handler(std::move(line)); @@ -33,15 +37,18 @@ void async_getline(std::istream& is, Handler handler) int main() { - thread_pool pool; + static_thread_pool io_pool(1); + static_thread_pool completion_pool(1); std::cout << "Enter a line: "; - async_getline(std::cin, - bind_executor(pool, [](std::string line) + async_getline(io_pool.executor(), std::cin, + bind_executor(completion_pool.executor(), + [](std::string line) { std::cout << "Line: " << line << "\n"; })); - pool.join(); + io_pool.wait(); + completion_pool.wait(); } diff --git a/3rdparty/asio/src/examples/cpp14/executors/async_2.cpp b/3rdparty/asio/src/examples/cpp14/executors/async_2.cpp index b39156dcb23..ee4a72e80c3 100644 --- a/3rdparty/asio/src/examples/cpp14/executors/async_2.cpp +++ b/3rdparty/asio/src/examples/cpp14/executors/async_2.cpp @@ -1,30 +1,33 @@ -#include <asio/ts/executor.hpp> -#include <asio/thread_pool.hpp> +#include <asio/associated_executor.hpp> +#include <asio/bind_executor.hpp> +#include <asio/execution.hpp> +#include <asio/static_thread_pool.hpp> #include <iostream> #include <string> using asio::bind_executor; -using asio::dispatch; using asio::get_associated_executor; -using asio::make_work_guard; -using asio::post; -using asio::thread_pool; +using asio::static_thread_pool; +namespace execution = asio::execution; // A function to asynchronously read a single line from an input stream. -template <class Handler> -void async_getline(std::istream& is, Handler handler) +template <class IoExecutor, class Handler> +void async_getline(IoExecutor io_ex, std::istream& is, Handler handler) { - // Create executor_work for the handler's associated executor. - auto work = make_work_guard(handler); + // Track work for the handler's associated executor. + auto work_ex = asio::prefer( + get_associated_executor(handler, io_ex), + execution::outstanding_work.tracked); // Post a function object to do the work asynchronously. - post([&is, work, handler=std::move(handler)]() mutable + asio::require(io_ex, execution::blocking.never).execute( + [&is, work_ex, handler=std::move(handler)]() mutable { std::string line; std::getline(is, line); // Pass the result to the handler, via the associated executor. - dispatch(work.get_executor(), + asio::prefer(work_ex, execution::blocking.possibly).execute( [line=std::move(line), handler=std::move(handler)]() mutable { handler(std::move(line)); @@ -33,36 +36,44 @@ void async_getline(std::istream& is, Handler handler) } // A function to asynchronously read multiple lines from an input stream. -template <class Handler> -void async_getlines(std::istream& is, std::string init, Handler handler) +template <class IoExecutor, class Handler> +void async_getlines(IoExecutor io_ex, std::istream& is, std::string init, Handler handler) { - // Get the final handler's associated executor. - auto ex = get_associated_executor(handler); + // Track work for the I/O executor. + auto io_work_ex = asio::prefer(io_ex, + execution::outstanding_work.tracked); + + // Track work for the handler's associated executor. + auto handler_work_ex = asio::prefer( + get_associated_executor(handler, io_ex), + execution::outstanding_work.tracked); // Use the associated executor for each operation in the composition. - async_getline(is, - bind_executor(ex, - [&is, lines=std::move(init), handler=std::move(handler)] + async_getline(io_work_ex, is, + bind_executor(handler_work_ex, + [io_work_ex, &is, lines=std::move(init), handler=std::move(handler)] (std::string line) mutable { if (line.empty()) handler(lines); else - async_getlines(is, lines + line + "\n", std::move(handler)); + async_getlines(io_work_ex, is, lines + line + "\n", std::move(handler)); })); } int main() { - thread_pool pool; + static_thread_pool io_pool(1); + static_thread_pool completion_pool(1); std::cout << "Enter text, terminating with a blank line:\n"; - async_getlines(std::cin, "", - bind_executor(pool, [](std::string lines) + async_getlines(io_pool.executor(), std::cin, "", + bind_executor(completion_pool.executor(), [](std::string lines) { std::cout << "Lines:\n" << lines << "\n"; })); - pool.join(); + io_pool.wait(); + completion_pool.wait(); } diff --git a/3rdparty/asio/src/examples/cpp14/executors/bank_account_1.cpp b/3rdparty/asio/src/examples/cpp14/executors/bank_account_1.cpp index f85a1852b56..a63d7fc059b 100644 --- a/3rdparty/asio/src/examples/cpp14/executors/bank_account_1.cpp +++ b/3rdparty/asio/src/examples/cpp14/executors/bank_account_1.cpp @@ -1,9 +1,9 @@ -#include <asio/ts/executor.hpp> -#include <asio/thread_pool.hpp> +#include <asio/execution.hpp> +#include <asio/static_thread_pool.hpp> #include <iostream> -using asio::post; -using asio::thread_pool; +using asio::static_thread_pool; +namespace execution = asio::execution; // Traditional active object pattern. // Member functions do not block. @@ -11,37 +11,40 @@ using asio::thread_pool; class bank_account { int balance_ = 0; - mutable thread_pool pool_{1}; + mutable static_thread_pool pool_{1}; public: void deposit(int amount) { - post(pool_, [=] - { - balance_ += amount; - }); + pool_.executor().execute( + [this, amount] + { + balance_ += amount; + }); } void withdraw(int amount) { - post(pool_, [=] - { - if (balance_ >= amount) - balance_ -= amount; - }); + pool_.executor().execute( + [this, amount] + { + if (balance_ >= amount) + balance_ -= amount; + }); } void print_balance() const { - post(pool_, [=] - { - std::cout << "balance = " << balance_ << "\n"; - }); + pool_.executor().execute( + [this] + { + std::cout << "balance = " << balance_ << "\n"; + }); } ~bank_account() { - pool_.join(); + pool_.wait(); } }; diff --git a/3rdparty/asio/src/examples/cpp14/executors/bank_account_2.cpp b/3rdparty/asio/src/examples/cpp14/executors/bank_account_2.cpp index 5233e77dec3..c2de05156e8 100644 --- a/3rdparty/asio/src/examples/cpp14/executors/bank_account_2.cpp +++ b/3rdparty/asio/src/examples/cpp14/executors/bank_account_2.cpp @@ -1,10 +1,9 @@ -#include <asio/ts/executor.hpp> -#include <asio/thread_pool.hpp> +#include <asio/execution.hpp> +#include <asio/static_thread_pool.hpp> #include <iostream> -using asio::post; -using asio::thread_pool; -using asio::use_future; +using asio::static_thread_pool; +namespace execution = asio::execution; // Traditional active object pattern. // Member functions block until operation is finished. @@ -12,35 +11,38 @@ using asio::use_future; class bank_account { int balance_ = 0; - mutable thread_pool pool_{1}; + mutable static_thread_pool pool_{1}; public: void deposit(int amount) { - post(pool_, - use_future([=] + asio::require(pool_.executor(), execution::blocking.always).execute( + [this, amount] { balance_ += amount; - })).get(); + }); } void withdraw(int amount) { - post(pool_, - use_future([=] + asio::require(pool_.executor(), + execution::blocking.always).execute( + [this, amount] { if (balance_ >= amount) balance_ -= amount; - })).get(); + }); } int balance() const { - return post(pool_, - use_future([=] + int result = 0; + asio::require(pool_.executor(), execution::blocking.always).execute( + [this, &result] { - return balance_; - })).get(); + result = balance_; + }); + return result; } }; diff --git a/3rdparty/asio/src/examples/cpp14/executors/fork_join.cpp b/3rdparty/asio/src/examples/cpp14/executors/fork_join.cpp index fe6746ad7e0..7e8a827356d 100644 --- a/3rdparty/asio/src/examples/cpp14/executors/fork_join.cpp +++ b/3rdparty/asio/src/examples/cpp14/executors/fork_join.cpp @@ -1,19 +1,20 @@ -#include <asio/ts/executor.hpp> -#include <asio/thread_pool.hpp> +#include <asio/execution.hpp> +#include <asio/static_thread_pool.hpp> +#include <algorithm> #include <condition_variable> #include <memory> #include <mutex> #include <queue> #include <thread> +#include <numeric> -using asio::dispatch; -using asio::execution_context; -using asio::thread_pool; +using asio::static_thread_pool; +namespace execution = asio::execution; // A fixed-size thread pool used to implement fork/join semantics. Functions // are scheduled using a simple FIFO queue. Implementing work stealing, or // using a queue based on atomic operations, are left as tasks for the reader. -class fork_join_pool : public execution_context +class fork_join_pool { public: // The constructor starts a thread pool with the specified number of threads. @@ -21,7 +22,7 @@ public: // Additional threads may temporarily be added to the pool if they join a // fork_executor. explicit fork_join_pool( - std::size_t thread_count = std::thread::hardware_concurrency() * 2) + std::size_t thread_count = std::max(std::thread::hardware_concurrency(), 1u) * 2) : use_count_(1), threads_(thread_count) { @@ -31,7 +32,8 @@ public: // it is time to shut down, i.e. the use count is zero. for (thread_count_ = 0; thread_count_ < thread_count; ++thread_count_) { - dispatch(threads_, [&] + threads_.executor().execute( + [this] { std::unique_lock<std::mutex> lock(mutex_); while (use_count_ > 0) @@ -43,7 +45,7 @@ public: catch (...) { stop_threads(); - threads_.join(); + threads_.wait(); throw; } } @@ -52,7 +54,7 @@ public: ~fork_join_pool() { stop_threads(); - threads_.join(); + threads_.wait(); } private: @@ -116,7 +118,7 @@ private: // Dispatch a function, executing it immediately if the queue is already // loaded. Otherwise adds the function to the queue and wakes a thread. - void do_dispatch(std::shared_ptr<function_base> p, + void do_execute(std::shared_ptr<function_base> p, const std::shared_ptr<std::size_t>& work_count) { std::unique_lock<std::mutex> lock(mutex_); @@ -134,16 +136,6 @@ private: } } - // Add a function to the queue and wake a thread. - void do_post(std::shared_ptr<function_base> p, - const std::shared_ptr<std::size_t>& work_count) - { - std::lock_guard<std::mutex> lock(mutex_); - queue_.push(p); - do_work_started(work_count); - condition_.notify_one(); - } - // Ask all threads to shut down. void stop_threads() { @@ -157,7 +149,7 @@ private: std::queue<std::shared_ptr<function_base>> queue_; std::size_t use_count_; std::size_t thread_count_; - thread_pool threads_; + static_thread_pool threads_; }; // A class that satisfies the Executor requirements. Every function or piece of @@ -171,45 +163,16 @@ public: { } - fork_join_pool& context() const noexcept + fork_join_pool& query(execution::context_t) const noexcept { return context_; } - void on_work_started() const noexcept - { - std::lock_guard<std::mutex> lock(context_.mutex_); - context_.do_work_started(work_count_); - } - - void on_work_finished() const noexcept - { - std::lock_guard<std::mutex> lock(context_.mutex_); - context_.do_work_finished(work_count_); - } - - template <class Func, class Alloc> - void dispatch(Func&& f, const Alloc& a) const - { - auto p(std::allocate_shared<function<Func>>( - typename std::allocator_traits<Alloc>::template rebind_alloc<char>(a), - std::move(f), work_count_)); - context_.do_dispatch(p, work_count_); - } - - template <class Func, class Alloc> - void post(Func f, const Alloc& a) const - { - auto p(std::allocate_shared<function<Func>>( - typename std::allocator_traits<Alloc>::template rebind_alloc<char>(a), - std::move(f), work_count_)); - context_.do_post(p, work_count_); - } - - template <class Func, class Alloc> - void defer(Func&& f, const Alloc& a) const + template <class Func> + void execute(Func f) const { - post(std::forward<Func>(f), a); + auto p(std::make_shared<function<Func>>(std::move(f), work_count_)); + context_.do_execute(p, work_count_); } friend bool operator==(const fork_executor& a, @@ -288,8 +251,8 @@ void fork_join_sort(Iterator begin, Iterator end) { fork_executor fork(pool); join_guard join(fork); - dispatch(fork, [=]{ fork_join_sort(begin, begin + n / 2); }); - dispatch(fork, [=]{ fork_join_sort(begin + n / 2, end); }); + fork.execute([=]{ fork_join_sort(begin, begin + n / 2); }); + fork.execute([=]{ fork_join_sort(begin + n / 2, end); }); } std::inplace_merge(begin, begin + n / 2, end); } diff --git a/3rdparty/asio/src/examples/cpp14/executors/pipeline.cpp b/3rdparty/asio/src/examples/cpp14/executors/pipeline.cpp index c66e283fcbc..9754a27d425 100644 --- a/3rdparty/asio/src/examples/cpp14/executors/pipeline.cpp +++ b/3rdparty/asio/src/examples/cpp14/executors/pipeline.cpp @@ -1,4 +1,6 @@ -#include <asio/ts/executor.hpp> +#include <asio/associated_executor.hpp> +#include <asio/bind_executor.hpp> +#include <asio/execution.hpp> #include <condition_variable> #include <future> #include <memory> @@ -6,30 +8,21 @@ #include <queue> #include <thread> #include <vector> +#include <cctype> -using asio::execution_context; using asio::executor_binder; using asio::get_associated_executor; -using asio::post; -using asio::system_executor; -using asio::use_future; -using asio::use_service; +namespace execution = asio::execution; // An executor that launches a new thread for each function submitted to it. -// This class satisfies the Executor requirements. +// This class satisfies the executor requirements. class thread_executor { private: - // Service to track all threads started through a thread_executor. - class thread_bag : public execution_context::service + // Singleton execution context that manages threads launched by the new_thread_executor. + class thread_bag { - public: - typedef thread_bag key_type; - - explicit thread_bag(execution_context& ctx) - : execution_context::service(ctx) - { - } + friend class thread_executor; void add_thread(std::thread&& t) { @@ -37,8 +30,9 @@ private: threads_.push_back(std::move(t)); } - private: - virtual void shutdown() + thread_bag() = default; + + ~thread_bag() { for (auto& t : threads_) t.join(); @@ -49,40 +43,24 @@ private: }; public: - execution_context& context() const noexcept + static thread_bag& query(execution::context_t) { - return system_executor().context(); + static thread_bag threads; + return threads; } - void on_work_started() const noexcept + static constexpr auto query(execution::blocking_t) { - // This executor doesn't count work. + return execution::blocking.never; } - void on_work_finished() const noexcept + template <class Func> + void execute(Func f) const { - // This executor doesn't count work. - } - - template <class Func, class Alloc> - void dispatch(Func&& f, const Alloc& a) const - { - post(std::forward<Func>(f), a); - } - - template <class Func, class Alloc> - void post(Func f, const Alloc&) const - { - thread_bag& bag = use_service<thread_bag>(context()); + thread_bag& bag = query(execution::context); bag.add_thread(std::thread(std::move(f))); } - template <class Func, class Alloc> - void defer(Func&& f, const Alloc& a) const - { - post(std::forward<Func>(f), a); - } - friend bool operator==(const thread_executor&, const thread_executor&) noexcept { @@ -185,7 +163,14 @@ std::future<void> pipeline(queue_back<T> in, F f) // Run the function, and as we're the last stage return a future so that the // caller can wait for the pipeline to finish. - return post(ex, use_future([in, f = std::move(f)]() mutable { f(in); })); + std::packaged_task<void()> task( + [in, f = std::move(f)]() mutable + { + f(in); + }); + std::future<void> fut = task.get_future(); + asio::require(ex, execution::blocking.never).execute(std::move(task)); + return fut; } // Launch an intermediate stage in a pipeline. @@ -204,7 +189,8 @@ std::future<void> pipeline(queue_back<T> in, F f, Tail... t) auto ex = get_associated_executor(f, thread_executor()); // Run the function. - post(ex, [in, out, f = std::move(f)]() mutable + asio::require(ex, execution::blocking.never).execute( + [in, out, f = std::move(f)]() mutable { f(in, out); out.stop(); @@ -230,7 +216,8 @@ std::future<void> pipeline(F f, Tail... t) auto ex = get_associated_executor(f, thread_executor()); // Run the function. - post(ex, [out, f = std::move(f)]() mutable + asio::require(ex, execution::blocking.never).execute( + [out, f = std::move(f)]() mutable { f(out); out.stop(); @@ -242,12 +229,12 @@ std::future<void> pipeline(F f, Tail... t) //------------------------------------------------------------------------------ -#include <asio/thread_pool.hpp> +#include <asio/static_thread_pool.hpp> #include <iostream> #include <string> using asio::bind_executor; -using asio::thread_pool; +using asio::static_thread_pool; void reader(queue_front<std::string> out) { @@ -286,8 +273,8 @@ void writer(queue_back<std::string> in) int main() { - thread_pool pool; + static_thread_pool pool(1); - auto f = pipeline(reader, filter, bind_executor(pool, upper), writer); + auto f = pipeline(reader, filter, bind_executor(pool.executor(), upper), writer); f.wait(); } diff --git a/3rdparty/asio/src/examples/cpp14/executors/priority_scheduler.cpp b/3rdparty/asio/src/examples/cpp14/executors/priority_scheduler.cpp index 3b28af1eec0..20d36db933a 100644 --- a/3rdparty/asio/src/examples/cpp14/executors/priority_scheduler.cpp +++ b/3rdparty/asio/src/examples/cpp14/executors/priority_scheduler.cpp @@ -1,66 +1,74 @@ -#include <asio/ts/executor.hpp> +#include <asio/execution.hpp> #include <condition_variable> #include <iostream> #include <memory> #include <mutex> #include <queue> -using asio::dispatch; -using asio::execution_context; +namespace execution = asio::execution; -class priority_scheduler : public execution_context +namespace custom_props { + + struct priority + { + template <typename T> + static constexpr bool is_applicable_property_v = + execution::is_executor<T>::value; + + static constexpr bool is_requirable = true; + static constexpr bool is_preferable = true; + + using polymorphic_query_result_type = int; + + int value() const { return value_; } + + int value_ = 1; + }; + + constexpr priority low_priority{0}; + constexpr priority normal_priority{1}; + constexpr priority high_priority{2}; + +} // namespace custom_props + +class priority_scheduler { public: // A class that satisfies the Executor requirements. class executor_type { public: - executor_type(priority_scheduler& ctx, int pri) noexcept - : context_(ctx), priority_(pri) + executor_type(priority_scheduler& ctx) noexcept + : context_(ctx), priority_(custom_props::normal_priority.value()) { } - priority_scheduler& context() const noexcept + priority_scheduler& query(execution::context_t) const noexcept { return context_; } - void on_work_started() const noexcept - { - // This executor doesn't count work. Instead, the scheduler simply runs - // until explicitly stopped. - } - - void on_work_finished() const noexcept + int query(custom_props::priority) const noexcept { - // This executor doesn't count work. Instead, the scheduler simply runs - // until explicitly stopped. + return priority_; } - template <class Func, class Alloc> - void dispatch(Func&& f, const Alloc& a) const + executor_type require(custom_props::priority pri) const { - post(std::forward<Func>(f), a); + executor_type new_ex(*this); + new_ex.priority_ = pri.value(); + return new_ex; } - template <class Func, class Alloc> - void post(Func f, const Alloc& a) const + template <class Func> + void execute(Func f) const { - auto p(std::allocate_shared<item<Func>>( - typename std::allocator_traits< - Alloc>::template rebind_alloc<char>(a), - priority_, std::move(f))); + auto p(std::make_shared<item<Func>>(priority_, std::move(f))); std::lock_guard<std::mutex> lock(context_.mutex_); context_.queue_.push(p); context_.condition_.notify_one(); } - template <class Func, class Alloc> - void defer(Func&& f, const Alloc& a) const - { - post(std::forward<Func>(f), a); - } - friend bool operator==(const executor_type& a, const executor_type& b) noexcept { @@ -78,9 +86,9 @@ public: int priority_; }; - executor_type get_executor(int pri = 0) noexcept + executor_type executor() noexcept { - return executor_type(*const_cast<priority_scheduler*>(this), pri); + return executor_type(*const_cast<priority_scheduler*>(this)); } void run() @@ -152,16 +160,22 @@ private: int main() { priority_scheduler sched; - auto low = sched.get_executor(0); - auto med = sched.get_executor(1); - auto high = sched.get_executor(2); - dispatch(low, []{ std::cout << "1\n"; }); - dispatch(low, []{ std::cout << "11\n"; }); - dispatch(med, []{ std::cout << "2\n"; }); - dispatch(med, []{ std::cout << "22\n"; }); - dispatch(high, []{ std::cout << "3\n"; }); - dispatch(high, []{ std::cout << "33\n"; }); - dispatch(high, []{ std::cout << "333\n"; }); - dispatch(sched.get_executor(-1), [&]{ sched.stop(); }); + auto ex = sched.executor(); + auto prefer_low = asio::prefer(ex, custom_props::low_priority); + auto low = asio::require(ex, custom_props::low_priority); + auto med = asio::require(ex, custom_props::normal_priority); + auto high = asio::require(ex, custom_props::high_priority); + execution::any_executor<custom_props::priority> poly_high(high); + prefer_low.execute([]{ std::cout << "1\n"; }); + low.execute([]{ std::cout << "11\n"; }); + low.execute([]{ std::cout << "111\n"; }); + med.execute([]{ std::cout << "2\n"; }); + med.execute([]{ std::cout << "22\n"; }); + high.execute([]{ std::cout << "3\n"; }); + high.execute([]{ std::cout << "33\n"; }); + high.execute([]{ std::cout << "333\n"; }); + poly_high.execute([]{ std::cout << "3333\n"; }); + asio::require(ex, custom_props::priority{-1}).execute([&]{ sched.stop(); }); sched.run(); + std::cout << "polymorphic query result = " << asio::query(poly_high, custom_props::priority{}) << "\n"; } diff --git a/3rdparty/asio/src/examples/cpp14/iostreams/.gitignore b/3rdparty/asio/src/examples/cpp14/iostreams/.gitignore deleted file mode 100644 index bc2b4f8f7fe..00000000000 --- a/3rdparty/asio/src/examples/cpp14/iostreams/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -.deps -.dirstamp -*.o -*.obj -*.exe -*_client -*_server -*.ilk -*.manifest -*.pdb -*.tds diff --git a/3rdparty/asio/src/examples/cpp14/iostreams/http_client.cpp b/3rdparty/asio/src/examples/cpp14/iostreams/http_client.cpp index 36f14b459e5..3ae02e4f825 100644 --- a/3rdparty/asio/src/examples/cpp14/iostreams/http_client.cpp +++ b/3rdparty/asio/src/examples/cpp14/iostreams/http_client.cpp @@ -2,7 +2,7 @@ // http_client.cpp // ~~~~~~~~~~~~~~~ // -// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the 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/src/examples/cpp14/operations/c_callback_wrapper.cpp b/3rdparty/asio/src/examples/cpp14/operations/c_callback_wrapper.cpp new file mode 100644 index 00000000000..33b1c26e8ae --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/operations/c_callback_wrapper.cpp @@ -0,0 +1,230 @@ +// +// c_callback_wrapper.cpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <iostream> +#include <memory> +#include <new> + +//------------------------------------------------------------------------------ + +// This is a mock implementation of a C-based API that uses the function pointer +// plus void* context idiom for exposing a callback. + +void read_input(const char* prompt, void (*cb)(void*, const char*), void* arg) +{ + std::thread( + [prompt = std::string(prompt), cb, arg] + { + std::cout << prompt << ": "; + std::cout.flush(); + std::string line; + std::getline(std::cin, line); + cb(arg, line.c_str()); + }).detach(); +} + +//------------------------------------------------------------------------------ + +// This is an asynchronous operation that wraps the C-based API. + +// To map our completion handler into a function pointer / void* callback, we +// need to allocate some state that will live for the duration of the +// operation. A pointer to this state will be passed to the C-based API. +template <typename Handler> +class read_input_state +{ +public: + read_input_state(Handler&& handler) + : handler_(std::move(handler)), + work_(asio::make_work_guard(handler_)) + { + } + + // Create the state using the handler's associated allocator. + static read_input_state* create(Handler&& handler) + { + // A unique_ptr deleter that is used to destroy uninitialised objects. + struct deleter + { + // Get the handler's associated allocator type. If the handler does not + // specify an associated allocator, we will use a recycling allocator as + // the default. As the associated allocator is a proto-allocator, we must + // rebind it to the correct type before we can use it to allocate objects. + typename std::allocator_traits< + asio::associated_allocator_t<Handler, + asio::recycling_allocator<void>>>::template + rebind_alloc<read_input_state> alloc; + + void operator()(read_input_state* ptr) + { + std::allocator_traits<decltype(alloc)>::deallocate(alloc, ptr, 1); + } + } d{asio::get_associated_allocator(handler, + asio::recycling_allocator<void>())}; + + // Allocate memory for the state. + std::unique_ptr<read_input_state, deleter> uninit_ptr( + std::allocator_traits<decltype(d.alloc)>::allocate(d.alloc, 1), d); + + // Construct the state into the newly allocated memory. This might throw. + read_input_state* ptr = + new (uninit_ptr.get()) read_input_state(std::move(handler)); + + // Release ownership of the memory and return the newly allocated state. + uninit_ptr.release(); + return ptr; + } + + static void callback(void* arg, const char* result) + { + read_input_state* self = static_cast<read_input_state*>(arg); + + // A unique_ptr deleter that is used to destroy initialised objects. + struct deleter + { + // Get the handler's associated allocator type. If the handler does not + // specify an associated allocator, we will use a recycling allocator as + // the default. As the associated allocator is a proto-allocator, we must + // rebind it to the correct type before we can use it to allocate objects. + typename std::allocator_traits< + asio::associated_allocator_t<Handler, + asio::recycling_allocator<void>>>::template + rebind_alloc<read_input_state> alloc; + + void operator()(read_input_state* ptr) + { + std::allocator_traits<decltype(alloc)>::destroy(alloc, ptr); + std::allocator_traits<decltype(alloc)>::deallocate(alloc, ptr, 1); + } + } d{asio::get_associated_allocator(self->handler_, + asio::recycling_allocator<void>())}; + + // To conform to the rules regarding asynchronous operations and memory + // allocation, we must make a copy of the state and deallocate the memory + // before dispatching the completion handler. + std::unique_ptr<read_input_state, deleter> state_ptr(self, d); + read_input_state state(std::move(*self)); + state_ptr.reset(); + + // Dispatch the completion handler through the handler's associated + // executor, using the handler's associated allocator. + asio::dispatch(state.work_.get_executor(), + asio::bind_allocator(d.alloc, + [ + handler = std::move(state.handler_), + result = std::string(result) + ]() mutable + { + std::move(handler)(result); + })); + } + +private: + Handler handler_; + + // According to the rules for asynchronous operations, we need to track + // outstanding work against the handler's associated executor until the + // asynchronous operation is complete. + asio::executor_work_guard< + asio::associated_executor_t<Handler>> work_; +}; + +// The initiating function for the asynchronous operation. +template <typename CompletionToken> +auto async_read_input(const std::string& prompt, CompletionToken&& token) +{ + // Define a function object that contains the code to launch the asynchronous + // operation. This is passed the concrete completion handler, followed by any + // additional arguments that were passed through the call to async_initiate. + auto init = [](auto handler, const std::string& prompt) + { + // The body of the initiation function object creates the long-lived state + // and passes it to the C-based API, along with the function pointer. + using state_type = read_input_state<decltype(handler)>; + read_input(prompt.c_str(), &state_type::callback, + state_type::create(std::move(handler))); + }; + + // The async_initiate function is used to transform the supplied completion + // token to the completion handler. When calling this function we explicitly + // specify the completion signature of the operation. We must also return the + // result of the call since the completion token may produce a return value, + // such as a future. + return asio::async_initiate<CompletionToken, void(std::string)>( + init, // First, pass the function object that launches the operation, + token, // then the completion token that will be transformed to a handler, + prompt); // and, finally, any additional arguments to the function object. +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + asio::io_context io_context; + + // Test our asynchronous operation using a lambda as a callback. We will use + // an io_context to obtain an associated executor. + async_read_input("Enter your name", + asio::bind_executor(io_context, + [](const std::string& result) + { + std::cout << "Hello " << result << "\n"; + })); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_deferred() +{ + asio::io_context io_context; + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation with its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_read_input("Enter your name", asio::deferred); + + // Launch our asynchronous operation using a lambda as a callback. We will use + // an io_context to obtain an associated executor. + std::move(op)( + asio::bind_executor(io_context, + [](const std::string& result) + { + std::cout << "Hello " << result << "\n"; + })); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<std::string> f = + async_read_input("Enter your name", asio::use_future); + + std::string result = f.get(); + std::cout << "Hello " << result << "\n"; +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_deferred(); + test_future(); +} diff --git a/3rdparty/asio/src/examples/cpp14/operations/callback_wrapper.cpp b/3rdparty/asio/src/examples/cpp14/operations/callback_wrapper.cpp new file mode 100644 index 00000000000..3d5774c7421 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/operations/callback_wrapper.cpp @@ -0,0 +1,152 @@ +// +// callback_wrapper.cpp +// ~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <iostream> + +//------------------------------------------------------------------------------ + +// This is a mock implementation of an API that uses a move-only function object +// for exposing a callback. The callback has the signature void(std::string). + +template <typename Callback> +void read_input(const std::string& prompt, Callback cb) +{ + std::thread( + [prompt, cb = std::move(cb)]() mutable + { + std::cout << prompt << ": "; + std::cout.flush(); + std::string line; + std::getline(std::cin, line); + std::move(cb)(std::move(line)); + }).detach(); +} + +//------------------------------------------------------------------------------ + +// This is an asynchronous operation that wraps the callback-based API. + +// The initiating function for the asynchronous operation. +template <typename CompletionToken> +auto async_read_input(const std::string& prompt, CompletionToken&& token) +{ + // Define a function object that contains the code to launch the asynchronous + // operation. This is passed the concrete completion handler, followed by any + // additional arguments that were passed through the call to async_initiate. + auto init = [](auto handler, const std::string& prompt) + { + // According to the rules for asynchronous operations, we need to track + // outstanding work against the handler's associated executor until the + // asynchronous operation is complete. + auto work = asio::make_work_guard(handler); + + // Launch the operation with a callback that will receive the result and + // pass it through to the asynchronous operation's completion handler. + read_input(prompt, + [ + handler = std::move(handler), + work = std::move(work) + ](std::string result) mutable + { + // Get the handler's associated allocator. If the handler does not + // specify an allocator, use the recycling allocator as the default. + auto alloc = asio::get_associated_allocator( + handler, asio::recycling_allocator<void>()); + + // Dispatch the completion handler through the handler's associated + // executor, using the handler's associated allocator. + asio::dispatch(work.get_executor(), + asio::bind_allocator(alloc, + [ + handler = std::move(handler), + result = std::string(result) + ]() mutable + { + std::move(handler)(result); + })); + }); + }; + + // The async_initiate function is used to transform the supplied completion + // token to the completion handler. When calling this function we explicitly + // specify the completion signature of the operation. We must also return the + // result of the call since the completion token may produce a return value, + // such as a future. + return asio::async_initiate<CompletionToken, void(std::string)>( + init, // First, pass the function object that launches the operation, + token, // then the completion token that will be transformed to a handler, + prompt); // and, finally, any additional arguments to the function object. +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + asio::io_context io_context; + + // Test our asynchronous operation using a lambda as a callback. We will use + // an io_context to specify an associated executor. + async_read_input("Enter your name", + asio::bind_executor(io_context, + [](const std::string& result) + { + std::cout << "Hello " << result << "\n"; + })); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_deferred() +{ + asio::io_context io_context; + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation with its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_read_input("Enter your name", asio::deferred); + + // Launch our asynchronous operation using a lambda as a callback. We will use + // an io_context to obtain an associated executor. + std::move(op)( + asio::bind_executor(io_context, + [](const std::string& result) + { + std::cout << "Hello " << result << "\n"; + })); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<std::string> f = + async_read_input("Enter your name", asio::use_future); + + std::string result = f.get(); + std::cout << "Hello " << result << "\n"; +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_deferred(); + test_future(); +} diff --git a/3rdparty/asio/src/examples/cpp14/operations/composed_1.cpp b/3rdparty/asio/src/examples/cpp14/operations/composed_1.cpp new file mode 100644 index 00000000000..80eaceddf71 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/operations/composed_1.cpp @@ -0,0 +1,155 @@ +// +// composed_1.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio/deferred.hpp> +#include <asio/io_context.hpp> +#include <asio/ip/tcp.hpp> +#include <asio/use_future.hpp> +#include <asio/write.hpp> +#include <cstring> +#include <iostream> +#include <string> +#include <type_traits> +#include <utility> + +using asio::ip::tcp; + +//------------------------------------------------------------------------------ + +// This is the simplest example of a composed asynchronous operation, where we +// simply repackage an existing operation. The asynchronous operation +// requirements are met by delegating responsibility to the underlying +// operation. + +template <typename CompletionToken> +auto async_write_message(tcp::socket& socket, + const char* message, CompletionToken&& token) + // The return type of the initiating function is deduced from the combination + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is void. + // However, when the completion token is asio::yield_context (used for + // stackful coroutines) the return type would be std::size_t, and when the + // completion token is asio::use_future it would be std::future<std::size_t>. + // When the completion token is asio::deferred, the return type differs for + // each asynchronous operation. + // + // In C++14 we can omit the return type as it is automatically deduced from + // the return type of our underlying asynchronous operation. +{ + // When delegating to the underlying operation we must take care to perfectly + // forward the completion token. This ensures that our operation works + // correctly with move-only function objects as callbacks, as well as other + // completion token types. + return asio::async_write(socket, + asio::buffer(message, std::strlen(message)), + std::forward<CompletionToken>(token)); +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using a lambda as a callback. + async_write_message(socket, "Testing callback\r\n", + [](const std::error_code& error, std::size_t n) + { + if (!error) + { + std::cout << n << " bytes transferred\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation with its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_message(socket, + "Testing deferred\r\n", asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error, std::size_t n) + { + if (!error) + { + std::cout << n << " bytes transferred\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<std::size_t> f = async_write_message( + socket, "Testing future\r\n", asio::use_future); + + io_context.run(); + + try + { + // Get the result of the operation. + std::size_t n = f.get(); + std::cout << n << " bytes transferred\n"; + } + catch (const std::exception& e) + { + std::cout << "Error: " << e.what() << "\n"; + } +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_deferred(); + test_future(); +} diff --git a/3rdparty/asio/src/examples/cpp14/operations/composed_2.cpp b/3rdparty/asio/src/examples/cpp14/operations/composed_2.cpp new file mode 100644 index 00000000000..18086bd0627 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/operations/composed_2.cpp @@ -0,0 +1,219 @@ +// +// composed_2.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio/deferred.hpp> +#include <asio/io_context.hpp> +#include <asio/ip/tcp.hpp> +#include <asio/use_future.hpp> +#include <asio/write.hpp> +#include <cstring> +#include <iostream> +#include <string> +#include <type_traits> +#include <utility> + +using asio::ip::tcp; + +// NOTE: This example requires the new asio::async_initiate function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + +//------------------------------------------------------------------------------ + +// This next simplest example of a composed asynchronous operation involves +// repackaging multiple operations but choosing to invoke just one of them. All +// of these underlying operations have the same completion signature. The +// asynchronous operation requirements are met by delegating responsibility to +// the underlying operations. + +template <typename CompletionToken> +auto async_write_message(tcp::socket& socket, + const char* message, bool allow_partial_write, + CompletionToken&& token) + // The return type of the initiating function is deduced from the combination + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is void. + // However, when the completion token is asio::yield_context (used for + // stackful coroutines) the return type would be std::size_t, and when the + // completion token is asio::use_future it would be std::future<std::size_t>. + // When the completion token is asio::deferred, the return type differs for + // each asynchronous operation. + // + // In C++14 we can omit the return type as it is automatically deduced from + // the return type of asio::async_initiate. +{ + // In addition to determining the mechanism by which an asynchronous + // operation delivers its result, a completion token also determines the time + // when the operation commences. For example, when the completion token is a + // simple callback the operation commences before the initiating function + // returns. However, if the completion token's delivery mechanism uses a + // future, we might instead want to defer initiation of the operation until + // the returned future object is waited upon. + // + // To enable this, when implementing an asynchronous operation we must + // package the initiation step as a function object. The initiation function + // object's call operator is passed the concrete completion handler produced + // by the completion token. This completion handler matches the asynchronous + // operation's completion handler signature, which in this example is: + // + // void(std::error_code error, std::size_t) + // + // The initiation function object also receives any additional arguments + // required to start the operation. (Note: We could have instead passed these + // arguments in the lambda capture set. However, we should prefer to + // propagate them as function call arguments as this allows the completion + // token to optimise how they are passed. For example, a lazy future which + // defers initiation would need to make a decay-copy of the arguments, but + // when using a simple callback the arguments can be trivially forwarded + // straight through.) + auto initiation = [](auto&& completion_handler, tcp::socket& socket, + const char* message, bool allow_partial_write) + { + if (allow_partial_write) + { + // When delegating to an underlying operation we must take care to + // perfectly forward the completion handler. This ensures that our + // operation works correctly with move-only function objects as + // callbacks. + return socket.async_write_some( + asio::buffer(message, std::strlen(message)), + std::forward<decltype(completion_handler)>(completion_handler)); + } + else + { + // As above, we must perfectly forward the completion handler when calling + // the alternate underlying operation. + return asio::async_write(socket, + asio::buffer(message, std::strlen(message)), + std::forward<decltype(completion_handler)>(completion_handler)); + } + }; + + // The asio::async_initiate function takes: + // + // - our initiation function object, + // - the completion token, + // - the completion handler signature, and + // - any additional arguments we need to initiate the operation. + // + // It then asks the completion token to create a completion handler (i.e. a + // callback) with the specified signature, and invoke the initiation function + // object with this completion handler as well as the additional arguments. + // The return value of async_initiate is the result of our operation's + // initiating function. + // + // Note that we wrap non-const reference arguments in std::reference_wrapper + // to prevent incorrect decay-copies of these objects. + return asio::async_initiate< + CompletionToken, void(std::error_code, std::size_t)>( + initiation, token, std::ref(socket), message, allow_partial_write); +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using a lambda as a callback. + async_write_message(socket, "Testing callback\r\n", false, + [](const std::error_code& error, std::size_t n) + { + if (!error) + { + std::cout << n << " bytes transferred\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation with its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_message(socket, + "Testing deferred\r\n", false, asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error, std::size_t n) + { + if (!error) + { + std::cout << n << " bytes transferred\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<std::size_t> f = async_write_message( + socket, "Testing future\r\n", false, asio::use_future); + + io_context.run(); + + try + { + // Get the result of the operation. + std::size_t n = f.get(); + std::cout << n << " bytes transferred\n"; + } + catch (const std::exception& e) + { + std::cout << "Error: " << e.what() << "\n"; + } +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_deferred(); + test_future(); +} diff --git a/3rdparty/asio/src/examples/cpp14/operations/composed_3.cpp b/3rdparty/asio/src/examples/cpp14/operations/composed_3.cpp new file mode 100644 index 00000000000..7b347944768 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/operations/composed_3.cpp @@ -0,0 +1,228 @@ +// +// composed_3.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio/bind_executor.hpp> +#include <asio/deferred.hpp> +#include <asio/io_context.hpp> +#include <asio/ip/tcp.hpp> +#include <asio/use_future.hpp> +#include <asio/write.hpp> +#include <cstring> +#include <functional> +#include <iostream> +#include <string> +#include <type_traits> +#include <utility> + +using asio::ip::tcp; + +// NOTE: This example requires the new asio::async_initiate function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + +//------------------------------------------------------------------------------ + +// In this composed operation we repackage an existing operation, but with a +// different completion handler signature. The asynchronous operation +// requirements are met by delegating responsibility to the underlying +// operation. + +template <typename CompletionToken> +auto async_write_message(tcp::socket& socket, + const char* message, CompletionToken&& token) + // The return type of the initiating function is deduced from the combination + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as + // there is no non-error argument to the completion handler. When the + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++14 we can omit the return type as it is automatically deduced from + // the return type of asio::async_initiate. +{ + // In addition to determining the mechanism by which an asynchronous + // operation delivers its result, a completion token also determines the time + // when the operation commences. For example, when the completion token is a + // simple callback the operation commences before the initiating function + // returns. However, if the completion token's delivery mechanism uses a + // future, we might instead want to defer initiation of the operation until + // the returned future object is waited upon. + // + // To enable this, when implementing an asynchronous operation we must + // package the initiation step as a function object. The initiation function + // object's call operator is passed the concrete completion handler produced + // by the completion token. This completion handler matches the asynchronous + // operation's completion handler signature, which in this example is: + // + // void(std::error_code error) + // + // The initiation function object also receives any additional arguments + // required to start the operation. (Note: We could have instead passed these + // arguments in the lambda capture set. However, we should prefer to + // propagate them as function call arguments as this allows the completion + // token to optimise how they are passed. For example, a lazy future which + // defers initiation would need to make a decay-copy of the arguments, but + // when using a simple callback the arguments can be trivially forwarded + // straight through.) + auto initiation = [](auto&& completion_handler, + tcp::socket& socket, const char* message) + { + // The async_write operation has a completion handler signature of: + // + // void(std::error_code error, std::size n) + // + // This differs from our operation's signature in that it is also passed + // the number of bytes transferred as an argument of type std::size_t. We + // will adapt our completion handler to async_write's completion handler + // signature by using std::bind, which drops the additional argument. + // + // However, it is essential to the correctness of our composed operation + // that we preserve the executor of the user-supplied completion handler. + // The std::bind function will not do this for us, so we must do this by + // first obtaining the completion handler's associated executor (defaulting + // to the I/O executor - in this case the executor of the socket - if the + // completion handler does not have its own) ... + auto executor = asio::get_associated_executor( + completion_handler, socket.get_executor()); + + // ... and then binding this executor to our adapted completion handler + // using the asio::bind_executor function. + asio::async_write(socket, + asio::buffer(message, std::strlen(message)), + asio::bind_executor(executor, + std::bind(std::forward<decltype(completion_handler)>( + completion_handler), std::placeholders::_1))); + }; + + // The asio::async_initiate function takes: + // + // - our initiation function object, + // - the completion token, + // - the completion handler signature, and + // - any additional arguments we need to initiate the operation. + // + // It then asks the completion token to create a completion handler (i.e. a + // callback) with the specified signature, and invoke the initiation function + // object with this completion handler as well as the additional arguments. + // The return value of async_initiate is the result of our operation's + // initiating function. + // + // Note that we wrap non-const reference arguments in std::reference_wrapper + // to prevent incorrect decay-copies of these objects. + return asio::async_initiate< + CompletionToken, void(std::error_code)>( + initiation, token, std::ref(socket), message); +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using a lambda as a callback. + async_write_message(socket, "Testing callback\r\n", + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Message sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation with its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_message(socket, + "Testing deferred\r\n", asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Message sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<void> f = async_write_message( + socket, "Testing future\r\n", asio::use_future); + + io_context.run(); + + // Get the result of the operation. + try + { + // Get the result of the operation. + f.get(); + std::cout << "Message sent\n"; + } + catch (const std::exception& e) + { + std::cout << "Error: " << e.what() << "\n"; + } +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_deferred(); + test_future(); +} diff --git a/3rdparty/asio/src/examples/cpp14/operations/composed_4.cpp b/3rdparty/asio/src/examples/cpp14/operations/composed_4.cpp new file mode 100644 index 00000000000..808a179e2d3 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/operations/composed_4.cpp @@ -0,0 +1,242 @@ +// +// composed_4.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio/bind_executor.hpp> +#include <asio/deferred.hpp> +#include <asio/io_context.hpp> +#include <asio/ip/tcp.hpp> +#include <asio/use_future.hpp> +#include <asio/write.hpp> +#include <cstring> +#include <functional> +#include <iostream> +#include <string> +#include <type_traits> +#include <utility> + +using asio::ip::tcp; + +// NOTE: This example requires the new asio::async_initiate function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + +//------------------------------------------------------------------------------ + +// In this composed operation we repackage an existing operation, but with a +// different completion handler signature. We will also intercept an empty +// message as an invalid argument, and propagate the corresponding error to the +// user. The asynchronous operation requirements are met by delegating +// responsibility to the underlying operation. + +template <typename CompletionToken> +auto async_write_message(tcp::socket& socket, + const char* message, CompletionToken&& token) + // The return type of the initiating function is deduced from the combination + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as + // there is no non-error argument to the completion handler. When the + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++14 we can omit the return type as it is automatically deduced from + // the return type of asio::async_initiate. +{ + // In addition to determining the mechanism by which an asynchronous + // operation delivers its result, a completion token also determines the time + // when the operation commences. For example, when the completion token is a + // simple callback the operation commences before the initiating function + // returns. However, if the completion token's delivery mechanism uses a + // future, we might instead want to defer initiation of the operation until + // the returned future object is waited upon. + // + // To enable this, when implementing an asynchronous operation we must + // package the initiation step as a function object. The initiation function + // object's call operator is passed the concrete completion handler produced + // by the completion token. This completion handler matches the asynchronous + // operation's completion handler signature, which in this example is: + // + // void(std::error_code error) + // + // The initiation function object also receives any additional arguments + // required to start the operation. (Note: We could have instead passed these + // arguments in the lambda capture set. However, we should prefer to + // propagate them as function call arguments as this allows the completion + // token to optimise how they are passed. For example, a lazy future which + // defers initiation would need to make a decay-copy of the arguments, but + // when using a simple callback the arguments can be trivially forwarded + // straight through.) + auto initiation = [](auto&& completion_handler, + tcp::socket& socket, const char* message) + { + // The post operation has a completion handler signature of: + // + // void() + // + // and the async_write operation has a completion handler signature of: + // + // void(std::error_code error, std::size n) + // + // Both of these operations' completion handler signatures differ from our + // operation's completion handler signature. We will adapt our completion + // handler to these signatures by using std::bind, which drops the + // additional arguments. + // + // However, it is essential to the correctness of our composed operation + // that we preserve the executor of the user-supplied completion handler. + // The std::bind function will not do this for us, so we must do this by + // first obtaining the completion handler's associated executor (defaulting + // to the I/O executor - in this case the executor of the socket - if the + // completion handler does not have its own) ... + auto executor = asio::get_associated_executor( + completion_handler, socket.get_executor()); + + // ... and then binding this executor to our adapted completion handler + // using the asio::bind_executor function. + std::size_t length = std::strlen(message); + if (length == 0) + { + asio::post( + asio::bind_executor(executor, + std::bind(std::forward<decltype(completion_handler)>( + completion_handler), asio::error::invalid_argument))); + } + else + { + asio::async_write(socket, + asio::buffer(message, length), + asio::bind_executor(executor, + std::bind(std::forward<decltype(completion_handler)>( + completion_handler), std::placeholders::_1))); + } + }; + + // The asio::async_initiate function takes: + // + // - our initiation function object, + // - the completion token, + // - the completion handler signature, and + // - any additional arguments we need to initiate the operation. + // + // It then asks the completion token to create a completion handler (i.e. a + // callback) with the specified signature, and invoke the initiation function + // object with this completion handler as well as the additional arguments. + // The return value of async_initiate is the result of our operation's + // initiating function. + // + // Note that we wrap non-const reference arguments in std::reference_wrapper + // to prevent incorrect decay-copies of these objects. + return asio::async_initiate< + CompletionToken, void(std::error_code)>( + initiation, token, std::ref(socket), message); +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using a lambda as a callback. + async_write_message(socket, "", + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Message sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation with its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_message(socket, "", asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Message sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<void> f = async_write_message( + socket, "", asio::use_future); + + io_context.run(); + + try + { + // Get the result of the operation. + f.get(); + std::cout << "Message sent\n"; + } + catch (const std::exception& e) + { + std::cout << "Exception: " << e.what() << "\n"; + } +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_deferred(); + test_future(); +} diff --git a/3rdparty/asio/src/examples/cpp14/operations/composed_5.cpp b/3rdparty/asio/src/examples/cpp14/operations/composed_5.cpp new file mode 100644 index 00000000000..c28cc8af129 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/operations/composed_5.cpp @@ -0,0 +1,280 @@ +// +// composed_5.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio/deferred.hpp> +#include <asio/io_context.hpp> +#include <asio/ip/tcp.hpp> +#include <asio/use_future.hpp> +#include <asio/write.hpp> +#include <functional> +#include <iostream> +#include <memory> +#include <sstream> +#include <string> +#include <type_traits> +#include <utility> + +using asio::ip::tcp; + +// NOTE: This example requires the new asio::async_initiate function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + +//------------------------------------------------------------------------------ + +// This composed operation automatically serialises a message, using its I/O +// streams insertion operator, before sending it on the socket. To do this, it +// must allocate a buffer for the encoded message and ensure this buffer's +// validity until the underlying async_write operation completes. + +template <typename T, typename CompletionToken> +auto async_write_message(tcp::socket& socket, + const T& message, CompletionToken&& token) + // The return type of the initiating function is deduced from the combination + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as + // there is no non-error argument to the completion handler. When the + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++14 we can omit the return type as it is automatically deduced from + // the return type of asio::async_initiate. +{ + // In addition to determining the mechanism by which an asynchronous + // operation delivers its result, a completion token also determines the time + // when the operation commences. For example, when the completion token is a + // simple callback the operation commences before the initiating function + // returns. However, if the completion token's delivery mechanism uses a + // future, we might instead want to defer initiation of the operation until + // the returned future object is waited upon. + // + // To enable this, when implementing an asynchronous operation we must + // package the initiation step as a function object. The initiation function + // object's call operator is passed the concrete completion handler produced + // by the completion token. This completion handler matches the asynchronous + // operation's completion handler signature, which in this example is: + // + // void(std::error_code error) + // + // The initiation function object also receives any additional arguments + // required to start the operation. (Note: We could have instead passed these + // arguments in the lambda capture set. However, we should prefer to + // propagate them as function call arguments as this allows the completion + // token to optimise how they are passed. For example, a lazy future which + // defers initiation would need to make a decay-copy of the arguments, but + // when using a simple callback the arguments can be trivially forwarded + // straight through.) + auto initiation = [](auto&& completion_handler, + tcp::socket& socket, std::unique_ptr<std::string> encoded_message) + { + // In this example, the composed operation's intermediate completion + // handler is implemented as a hand-crafted function object, rather than + // using a lambda or std::bind. + struct intermediate_completion_handler + { + // The intermediate completion handler holds a reference to the socket so + // that it can obtain the I/O executor (see get_executor below). + tcp::socket& socket_; + + // The allocated buffer for the encoded message. The std::unique_ptr + // smart pointer is move-only, and as a consequence our intermediate + // completion handler is also move-only. + std::unique_ptr<std::string> encoded_message_; + + // The user-supplied completion handler. + typename std::decay<decltype(completion_handler)>::type handler_; + + // The function call operator matches the completion signature of the + // async_write operation. + void operator()(const std::error_code& error, std::size_t /*n*/) + { + // Deallocate the encoded message before calling the user-supplied + // completion handler. + encoded_message_.reset(); + + // Call the user-supplied handler with the result of the operation. + // The arguments must match the completion signature of our composed + // operation. + handler_(error); + } + + // It is essential to the correctness of our composed operation that we + // preserve the executor of the user-supplied completion handler. With a + // hand-crafted function object we can do this by defining a nested type + // executor_type and member function get_executor. These obtain the + // completion handler's associated executor, and default to the I/O + // executor - in this case the executor of the socket - if the completion + // handler does not have its own. + using executor_type = asio::associated_executor_t< + typename std::decay<decltype(completion_handler)>::type, + tcp::socket::executor_type>; + + executor_type get_executor() const noexcept + { + return asio::get_associated_executor( + handler_, socket_.get_executor()); + } + + // Although not necessary for correctness, we may also preserve the + // allocator of the user-supplied completion handler. This is achieved by + // defining a nested type allocator_type and member function + // get_allocator. These obtain the completion handler's associated + // allocator, and default to std::allocator<void> if the completion + // handler does not have its own. + using allocator_type = asio::associated_allocator_t< + typename std::decay<decltype(completion_handler)>::type, + std::allocator<void>>; + + allocator_type get_allocator() const noexcept + { + return asio::get_associated_allocator( + handler_, std::allocator<void>{}); + } + }; + + // Initiate the underlying async_write operation using our intermediate + // completion handler. + auto encoded_message_buffer = asio::buffer(*encoded_message); + asio::async_write(socket, encoded_message_buffer, + intermediate_completion_handler{socket, std::move(encoded_message), + std::forward<decltype(completion_handler)>(completion_handler)}); + }; + + // Encode the message and copy it into an allocated buffer. The buffer will + // be maintained for the lifetime of the asynchronous operation. + std::ostringstream os; + os << message; + std::unique_ptr<std::string> encoded_message(new std::string(os.str())); + + // The asio::async_initiate function takes: + // + // - our initiation function object, + // - the completion token, + // - the completion handler signature, and + // - any additional arguments we need to initiate the operation. + // + // It then asks the completion token to create a completion handler (i.e. a + // callback) with the specified signature, and invoke the initiation function + // object with this completion handler as well as the additional arguments. + // The return value of async_initiate is the result of our operation's + // initiating function. + // + // Note that we wrap non-const reference arguments in std::reference_wrapper + // to prevent incorrect decay-copies of these objects. + return asio::async_initiate< + CompletionToken, void(std::error_code)>( + initiation, token, std::ref(socket), + std::move(encoded_message)); +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using a lambda as a callback. + async_write_message(socket, 123456, + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Message sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation with its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_message(socket, + std::string("abcdef"), asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Message sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<void> f = async_write_message( + socket, 654.321, asio::use_future); + + io_context.run(); + + try + { + // Get the result of the operation. + f.get(); + std::cout << "Message sent\n"; + } + catch (const std::exception& e) + { + std::cout << "Exception: " << e.what() << "\n"; + } +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_deferred(); + test_future(); +} diff --git a/3rdparty/asio/src/examples/cpp14/operations/composed_6.cpp b/3rdparty/asio/src/examples/cpp14/operations/composed_6.cpp new file mode 100644 index 00000000000..82c0cd72237 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/operations/composed_6.cpp @@ -0,0 +1,340 @@ +// +// composed_6.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio/deferred.hpp> +#include <asio/executor_work_guard.hpp> +#include <asio/io_context.hpp> +#include <asio/ip/tcp.hpp> +#include <asio/steady_timer.hpp> +#include <asio/use_future.hpp> +#include <asio/write.hpp> +#include <functional> +#include <iostream> +#include <memory> +#include <sstream> +#include <string> +#include <type_traits> +#include <utility> + +using asio::ip::tcp; + +// NOTE: This example requires the new asio::async_initiate function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + +//------------------------------------------------------------------------------ + +// This composed operation shows composition of multiple underlying operations. +// It automatically serialises a message, using its I/O streams insertion +// operator, before sending it N times on the socket. To do this, it must +// allocate a buffer for the encoded message and ensure this buffer's validity +// until all underlying async_write operation complete. A one second delay is +// inserted prior to each write operation, using a steady_timer. + +template <typename T, typename CompletionToken> +auto async_write_messages(tcp::socket& socket, + const T& message, std::size_t repeat_count, + CompletionToken&& token) + // The return type of the initiating function is deduced from the combination + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as + // there is no non-error argument to the completion handler. When the + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++14 we can omit the return type as it is automatically deduced from + // the return type of asio::async_initiate. +{ + // In addition to determining the mechanism by which an asynchronous + // operation delivers its result, a completion token also determines the time + // when the operation commences. For example, when the completion token is a + // simple callback the operation commences before the initiating function + // returns. However, if the completion token's delivery mechanism uses a + // future, we might instead want to defer initiation of the operation until + // the returned future object is waited upon. + // + // To enable this, when implementing an asynchronous operation we must + // package the initiation step as a function object. The initiation function + // object's call operator is passed the concrete completion handler produced + // by the completion token. This completion handler matches the asynchronous + // operation's completion handler signature, which in this example is: + // + // void(std::error_code error) + // + // The initiation function object also receives any additional arguments + // required to start the operation. (Note: We could have instead passed these + // arguments in the lambda capture set. However, we should prefer to + // propagate them as function call arguments as this allows the completion + // token to optimise how they are passed. For example, a lazy future which + // defers initiation would need to make a decay-copy of the arguments, but + // when using a simple callback the arguments can be trivially forwarded + // straight through.) + auto initiation = [](auto&& completion_handler, tcp::socket& socket, + std::unique_ptr<std::string> encoded_message, std::size_t repeat_count, + std::unique_ptr<asio::steady_timer> delay_timer) + { + // In this example, the composed operation's intermediate completion + // handler is implemented as a hand-crafted function object. + struct intermediate_completion_handler + { + // The intermediate completion handler holds a reference to the socket as + // it is used for multiple async_write operations, as well as for + // obtaining the I/O executor (see get_executor below). + tcp::socket& socket_; + + // The allocated buffer for the encoded message. The std::unique_ptr + // smart pointer is move-only, and as a consequence our intermediate + // completion handler is also move-only. + std::unique_ptr<std::string> encoded_message_; + + // The repeat count remaining. + std::size_t repeat_count_; + + // A steady timer used for introducing a delay. + std::unique_ptr<asio::steady_timer> delay_timer_; + + // To manage the cycle between the multiple underlying asychronous + // operations, our intermediate completion handler is implemented as a + // state machine. + enum { starting, waiting, writing } state_; + + // As our composed operation performs multiple underlying I/O operations, + // we should maintain a work object against the I/O executor. This tells + // the I/O executor that there is still more work to come in the future. + asio::executor_work_guard<tcp::socket::executor_type> io_work_; + + // The user-supplied completion handler, called once only on completion + // of the entire composed operation. + typename std::decay<decltype(completion_handler)>::type handler_; + + // By having a default value for the second argument, this function call + // operator matches the completion signature of both the async_write and + // steady_timer::async_wait operations. + void operator()(const std::error_code& error, std::size_t = 0) + { + if (!error) + { + switch (state_) + { + case starting: + case writing: + if (repeat_count_ > 0) + { + --repeat_count_; + state_ = waiting; + delay_timer_->expires_after(std::chrono::seconds(1)); + delay_timer_->async_wait(std::move(*this)); + return; // Composed operation not yet complete. + } + break; // Composed operation complete, continue below. + case waiting: + state_ = writing; + asio::async_write(socket_, + asio::buffer(*encoded_message_), std::move(*this)); + return; // Composed operation not yet complete. + } + } + + // This point is reached only on completion of the entire composed + // operation. + + // We no longer have any future work coming for the I/O executor. + io_work_.reset(); + + // Deallocate the encoded message before calling the user-supplied + // completion handler. + encoded_message_.reset(); + + // Call the user-supplied handler with the result of the operation. + handler_(error); + } + + // It is essential to the correctness of our composed operation that we + // preserve the executor of the user-supplied completion handler. With a + // hand-crafted function object we can do this by defining a nested type + // executor_type and member function get_executor. These obtain the + // completion handler's associated executor, and default to the I/O + // executor - in this case the executor of the socket - if the completion + // handler does not have its own. + using executor_type = asio::associated_executor_t< + typename std::decay<decltype(completion_handler)>::type, + tcp::socket::executor_type>; + + executor_type get_executor() const noexcept + { + return asio::get_associated_executor( + handler_, socket_.get_executor()); + } + + // Although not necessary for correctness, we may also preserve the + // allocator of the user-supplied completion handler. This is achieved by + // defining a nested type allocator_type and member function + // get_allocator. These obtain the completion handler's associated + // allocator, and default to std::allocator<void> if the completion + // handler does not have its own. + using allocator_type = asio::associated_allocator_t< + typename std::decay<decltype(completion_handler)>::type, + std::allocator<void>>; + + allocator_type get_allocator() const noexcept + { + return asio::get_associated_allocator( + handler_, std::allocator<void>{}); + } + }; + + // Initiate the underlying async_write operation using our intermediate + // completion handler. + auto encoded_message_buffer = asio::buffer(*encoded_message); + asio::async_write(socket, encoded_message_buffer, + intermediate_completion_handler{ + socket, std::move(encoded_message), + repeat_count, std::move(delay_timer), + intermediate_completion_handler::starting, + asio::make_work_guard(socket.get_executor()), + std::forward<decltype(completion_handler)>(completion_handler)}); + }; + + // Encode the message and copy it into an allocated buffer. The buffer will + // be maintained for the lifetime of the composed asynchronous operation. + std::ostringstream os; + os << message; + std::unique_ptr<std::string> encoded_message(new std::string(os.str())); + + // Create a steady_timer to be used for the delay between messages. + std::unique_ptr<asio::steady_timer> delay_timer( + new asio::steady_timer(socket.get_executor())); + + // The asio::async_initiate function takes: + // + // - our initiation function object, + // - the completion token, + // - the completion handler signature, and + // - any additional arguments we need to initiate the operation. + // + // It then asks the completion token to create a completion handler (i.e. a + // callback) with the specified signature, and invoke the initiation function + // object with this completion handler as well as the additional arguments. + // The return value of async_initiate is the result of our operation's + // initiating function. + // + // Note that we wrap non-const reference arguments in std::reference_wrapper + // to prevent incorrect decay-copies of these objects. + return asio::async_initiate< + CompletionToken, void(std::error_code)>( + initiation, token, std::ref(socket), + std::move(encoded_message), repeat_count, + std::move(delay_timer)); +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using a lambda as a callback. + async_write_messages(socket, "Testing callback\r\n", 5, + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation with its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_messages(socket, + "Testing deferred\r\n", 5, asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<void> f = async_write_messages( + socket, "Testing future\r\n", 5, asio::use_future); + + io_context.run(); + + try + { + // Get the result of the operation. + f.get(); + std::cout << "Messages sent\n"; + } + catch (const std::exception& e) + { + std::cout << "Error: " << e.what() << "\n"; + } +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_deferred(); + test_future(); +} diff --git a/3rdparty/asio/src/examples/cpp14/operations/composed_7.cpp b/3rdparty/asio/src/examples/cpp14/operations/composed_7.cpp new file mode 100644 index 00000000000..841249bef5b --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/operations/composed_7.cpp @@ -0,0 +1,261 @@ +// +// composed_7.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio/compose.hpp> +#include <asio/deferred.hpp> +#include <asio/io_context.hpp> +#include <asio/ip/tcp.hpp> +#include <asio/steady_timer.hpp> +#include <asio/use_future.hpp> +#include <asio/write.hpp> +#include <functional> +#include <iostream> +#include <memory> +#include <sstream> +#include <string> +#include <type_traits> +#include <utility> + +using asio::ip::tcp; + +// NOTE: This example requires the new asio::async_compose function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + +//------------------------------------------------------------------------------ + +// This composed operation shows composition of multiple underlying operations. +// It automatically serialises a message, using its I/O streams insertion +// operator, before sending it N times on the socket. To do this, it must +// allocate a buffer for the encoded message and ensure this buffer's validity +// until all underlying async_write operation complete. A one second delay is +// inserted prior to each write operation, using a steady_timer. + +template <typename T, typename CompletionToken> +auto async_write_messages(tcp::socket& socket, + const T& message, std::size_t repeat_count, + CompletionToken&& token) + // The return type of the initiating function is deduced from the combination + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as + // there is no non-error argument to the completion handler. When the + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++14 we can omit the return type as it is automatically deduced from + // the return type of asio::async_compose. +{ + // Encode the message and copy it into an allocated buffer. The buffer will + // be maintained for the lifetime of the composed asynchronous operation. + std::ostringstream os; + os << message; + std::unique_ptr<std::string> encoded_message(new std::string(os.str())); + + // Create a steady_timer to be used for the delay between messages. + std::unique_ptr<asio::steady_timer> delay_timer( + new asio::steady_timer(socket.get_executor())); + + // To manage the cycle between the multiple underlying asychronous + // operations, our implementation is a state machine. + enum { starting, waiting, writing }; + + // The asio::async_compose function takes: + // + // - our asynchronous operation implementation, + // - the completion token, + // - the completion handler signature, and + // - any I/O objects (or executors) used by the operation + // + // It then wraps our implementation, which is implemented here as a state + // machine in a lambda, in an intermediate completion handler that meets the + // requirements of a conforming asynchronous operation. This includes + // tracking outstanding work against the I/O executors associated with the + // operation (in this example, this is the socket's executor). + // + // The first argument to our lambda is a reference to the enclosing + // intermediate completion handler. This intermediate completion handler is + // provided for us by the asio::async_compose function, and takes care + // of all the details required to implement a conforming asynchronous + // operation. When calling an underlying asynchronous operation, we pass it + // this enclosing intermediate completion handler as the completion token. + // + // All arguments to our lambda after the first must be defaulted to allow the + // state machine to be started, as well as to allow the completion handler to + // match the completion signature of both the async_write and + // steady_timer::async_wait operations. + return asio::async_compose< + CompletionToken, void(std::error_code)>( + [ + // The implementation holds a reference to the socket as it is used for + // multiple async_write operations. + &socket, + + // The allocated buffer for the encoded message. The std::unique_ptr + // smart pointer is move-only, and as a consequence our lambda + // implementation is also move-only. + encoded_message = std::move(encoded_message), + + // The repeat count remaining. + repeat_count, + + // A steady timer used for introducing a delay. + delay_timer = std::move(delay_timer), + + // To manage the cycle between the multiple underlying asychronous + // operations, our implementation is a state machine. + state = starting + ] + ( + auto& self, + const std::error_code& error = {}, + std::size_t = 0 + ) mutable + { + if (!error) + { + switch (state) + { + case starting: + case writing: + if (repeat_count > 0) + { + --repeat_count; + state = waiting; + delay_timer->expires_after(std::chrono::seconds(1)); + delay_timer->async_wait(std::move(self)); + return; // Composed operation not yet complete. + } + break; // Composed operation complete, continue below. + case waiting: + state = writing; + asio::async_write(socket, + asio::buffer(*encoded_message), std::move(self)); + return; // Composed operation not yet complete. + } + } + + // This point is reached only on completion of the entire composed + // operation. + + // Deallocate the encoded message and delay timer before calling the + // user-supplied completion handler. + encoded_message.reset(); + delay_timer.reset(); + + // Call the user-supplied handler with the result of the operation. + self.complete(error); + }, + token, socket); +} + +//------------------------------------------------------------------------------ + +void test_callback() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using a lambda as a callback. + async_write_messages(socket, "Testing callback\r\n", 5, + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation with its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_messages(socket, + "Testing deferred\r\n", 5, asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<void> f = async_write_messages( + socket, "Testing future\r\n", 5, asio::use_future); + + io_context.run(); + + try + { + // Get the result of the operation. + f.get(); + std::cout << "Messages sent\n"; + } + catch (const std::exception& e) + { + std::cout << "Error: " << e.what() << "\n"; + } +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_deferred(); + test_future(); +} diff --git a/3rdparty/asio/src/examples/cpp14/operations/composed_8.cpp b/3rdparty/asio/src/examples/cpp14/operations/composed_8.cpp new file mode 100644 index 00000000000..d1f46ddce54 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/operations/composed_8.cpp @@ -0,0 +1,254 @@ +// +// composed_8.cpp +// ~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio/compose.hpp> +#include <asio/coroutine.hpp> +#include <asio/deferred.hpp> +#include <asio/io_context.hpp> +#include <asio/ip/tcp.hpp> +#include <asio/steady_timer.hpp> +#include <asio/use_future.hpp> +#include <asio/write.hpp> +#include <functional> +#include <iostream> +#include <memory> +#include <sstream> +#include <string> +#include <type_traits> +#include <utility> + +using asio::ip::tcp; + +// NOTE: This example requires the new asio::async_compose function. For +// an example that works with the Networking TS style of completion tokens, +// please see an older version of asio. + +//------------------------------------------------------------------------------ + +// This composed operation shows composition of multiple underlying operations, +// using asio's stackless coroutines support to express the flow of control. It +// automatically serialises a message, using its I/O streams insertion +// operator, before sending it N times on the socket. To do this, it must +// allocate a buffer for the encoded message and ensure this buffer's validity +// until all underlying async_write operation complete. A one second delay is +// inserted prior to each write operation, using a steady_timer. + +#include <asio/yield.hpp> + +template <typename T, typename CompletionToken> +auto async_write_messages(tcp::socket& socket, + const T& message, std::size_t repeat_count, + CompletionToken&& token) + // The return type of the initiating function is deduced from the combination + // of: + // + // - the CompletionToken type, + // - the completion handler signature, and + // - the asynchronous operation's initiation function object. + // + // When the completion token is a simple callback, the return type is always + // void. In this example, when the completion token is asio::yield_context + // (used for stackful coroutines) the return type would also be void, as + // there is no non-error argument to the completion handler. When the + // completion token is asio::use_future it would be std::future<void>. When + // the completion token is asio::deferred, the return type differs for each + // asynchronous operation. + // + // In C++14 we can omit the return type as it is automatically deduced from + // the return type of asio::async_compose. +{ + // Encode the message and copy it into an allocated buffer. The buffer will + // be maintained for the lifetime of the composed asynchronous operation. + std::ostringstream os; + os << message; + std::unique_ptr<std::string> encoded_message(new std::string(os.str())); + + // Create a steady_timer to be used for the delay between messages. + std::unique_ptr<asio::steady_timer> delay_timer( + new asio::steady_timer(socket.get_executor())); + + // The asio::async_compose function takes: + // + // - our asynchronous operation implementation, + // - the completion token, + // - the completion handler signature, and + // - any I/O objects (or executors) used by the operation + // + // It then wraps our implementation, which is implemented here as a stackless + // coroutine in a lambda, in an intermediate completion handler that meets the + // requirements of a conforming asynchronous operation. This includes + // tracking outstanding work against the I/O executors associated with the + // operation (in this example, this is the socket's executor). + // + // The first argument to our lambda is a reference to the enclosing + // intermediate completion handler. This intermediate completion handler is + // provided for us by the asio::async_compose function, and takes care + // of all the details required to implement a conforming asynchronous + // operation. When calling an underlying asynchronous operation, we pass it + // this enclosing intermediate completion handler as the completion token. + // + // All arguments to our lambda after the first must be defaulted to allow the + // state machine to be started, as well as to allow the completion handler to + // match the completion signature of both the async_write and + // steady_timer::async_wait operations. + return asio::async_compose< + CompletionToken, void(std::error_code)>( + [ + // The implementation holds a reference to the socket as it is used for + // multiple async_write operations. + &socket, + + // The allocated buffer for the encoded message. The std::unique_ptr + // smart pointer is move-only, and as a consequence our lambda + // implementation is also move-only. + encoded_message = std::move(encoded_message), + + // The repeat count remaining. + repeat_count, + + // A steady timer used for introducing a delay. + delay_timer = std::move(delay_timer), + + // The coroutine state. + coro = asio::coroutine() + ] + ( + auto& self, + const std::error_code& error = {}, + std::size_t = 0 + ) mutable + { + reenter (coro) + { + while (repeat_count > 0) + { + --repeat_count; + + delay_timer->expires_after(std::chrono::seconds(1)); + yield delay_timer->async_wait(std::move(self)); + if (error) + break; + + yield asio::async_write(socket, + asio::buffer(*encoded_message), std::move(self)); + if (error) + break; + } + + // Deallocate the encoded message and delay timer before calling the + // user-supplied completion handler. + encoded_message.reset(); + delay_timer.reset(); + + // Call the user-supplied handler with the result of the operation. + self.complete(error); + } + }, + token, socket); +} + +#include <asio/unyield.hpp> + +//------------------------------------------------------------------------------ + +void test_callback() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using a lambda as a callback. + async_write_messages(socket, "Testing callback\r\n", 5, + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_deferred() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the deferred completion token. This + // token causes the operation's initiating function to package up the + // operation with its arguments to return a function object, which may then be + // used to launch the asynchronous operation. + auto op = async_write_messages(socket, + "Testing deferred\r\n", 5, asio::deferred); + + // Launch the operation using a lambda as a callback. + std::move(op)( + [](const std::error_code& error) + { + if (!error) + { + std::cout << "Messages sent\n"; + } + else + { + std::cout << "Error: " << error.message() << "\n"; + } + }); + + io_context.run(); +} + +//------------------------------------------------------------------------------ + +void test_future() +{ + asio::io_context io_context; + + tcp::acceptor acceptor(io_context, {tcp::v4(), 55555}); + tcp::socket socket = acceptor.accept(); + + // Test our asynchronous operation using the use_future completion token. + // This token causes the operation's initiating function to return a future, + // which may be used to synchronously wait for the result of the operation. + std::future<void> f = async_write_messages( + socket, "Testing future\r\n", 5, asio::use_future); + + io_context.run(); + + try + { + // Get the result of the operation. + f.get(); + std::cout << "Messages sent\n"; + } + catch (const std::exception& e) + { + std::cout << "Error: " << e.what() << "\n"; + } +} + +//------------------------------------------------------------------------------ + +int main() +{ + test_callback(); + test_deferred(); + test_future(); +} diff --git a/3rdparty/asio/src/examples/cpp14/parallel_group/parallel_sort.cpp b/3rdparty/asio/src/examples/cpp14/parallel_group/parallel_sort.cpp new file mode 100644 index 00000000000..8bb7cdfd719 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/parallel_group/parallel_sort.cpp @@ -0,0 +1,133 @@ +// +// parallel_sort.cpp +// ~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <asio/experimental/parallel_group.hpp> +#include <algorithm> +#include <chrono> +#include <functional> +#include <iostream> +#include <random> + +template < + typename Executor, + typename RandomAccessIterator, + ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> +auto parallel_sort( + Executor executor, + RandomAccessIterator begin, + RandomAccessIterator end, + CompletionToken&& token); + +template < + typename Executor, + typename RandomAccessIterator> +void parallel_sort_impl( + Executor executor, + RandomAccessIterator begin, + RandomAccessIterator end, + std::function<void()> continuation) +{ + std::size_t n = end - begin; + if (n <= 16384) + { + asio::post(executor, + [=] + { + std::sort(begin, end); + continuation(); + } + ); + } + else + { + asio::experimental::make_parallel_group( + [=](auto token) + { + return parallel_sort(executor, begin, begin + n / 2, token); + }, + [=](auto token) + { + return parallel_sort(executor, begin + n / 2, end, token); + } + ).async_wait( + asio::experimental::wait_for_all(), + [=](std::array<std::size_t, 2>) + { + std::inplace_merge(begin, begin + n / 2, end); + continuation(); + } + ); + } +} + +template < + typename Executor, + typename RandomAccessIterator, + ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken> +auto parallel_sort( + Executor executor, + RandomAccessIterator begin, + RandomAccessIterator end, + CompletionToken&& token) +{ + return asio::async_compose<CompletionToken, void()>( + [=](auto& self, auto... args) + { + if (sizeof...(args) == 0) + { + using self_type = std::decay_t<decltype(self)>; + parallel_sort_impl(executor, begin, end, + [self = std::make_shared<self_type>(std::move(self))] + { + asio::dispatch( + asio::append( + std::move(*self), 0)); + } + ); + } + else + { + self.complete(); + } + }, + token + ); +} + +int main() +{ + asio::thread_pool pool(4); + + std::vector<int> values(100'000'000); + + std::random_device random_device; + std::mt19937 rng(random_device()); + std::uniform_int_distribution<int> dist(1, 1'000'000); + std::generate(values.begin(), values.end(), [&]{ return dist(rng); }); + + std::cout << "starting sort\n"; + + auto begin = std::chrono::high_resolution_clock::now(); + + parallel_sort( + pool.get_executor(), + values.begin(), + values.end(), + asio::use_future + ).get(); + + auto end = std::chrono::high_resolution_clock::now(); + + auto duration = end - begin; + std::cout << "sort took " + << std::chrono::duration_cast<std::chrono::microseconds>(duration).count() + << " microseconds\n"; +} diff --git a/3rdparty/asio/src/examples/cpp14/parallel_group/ranged_wait_for_all.cpp b/3rdparty/asio/src/examples/cpp14/parallel_group/ranged_wait_for_all.cpp new file mode 100644 index 00000000000..18772884072 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/parallel_group/ranged_wait_for_all.cpp @@ -0,0 +1,70 @@ +// +// ranged_wait_for_all.cpp +// ~~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <asio/experimental/parallel_group.hpp> +#include <iostream> +#include <vector> + +#ifdef ASIO_HAS_POSIX_STREAM_DESCRIPTOR + +int main() +{ + asio::io_context ctx; + + asio::posix::stream_descriptor out(ctx, ::dup(STDOUT_FILENO)); + asio::posix::stream_descriptor err(ctx, ::dup(STDERR_FILENO)); + + using op_type = decltype( + out.async_write_some( + asio::buffer("", 0), + asio::deferred + ) + ); + + std::vector<op_type> ops; + + ops.push_back( + out.async_write_some( + asio::buffer("first\r\n", 7), + asio::deferred + ) + ); + + ops.push_back( + err.async_write_some( + asio::buffer("second\r\n", 8), + 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> ec, + 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 << "operation " << idx << " finished: "; + std::cout << ec[idx] << ", " << n[idx] << "\n"; + } + } + ); + + ctx.run(); +} + +#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +int main() {} +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) diff --git a/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_all.cpp b/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_all.cpp new file mode 100644 index 00000000000..f007326326b --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_all.cpp @@ -0,0 +1,64 @@ +// +// wait_for_all.cpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <asio/experimental/parallel_group.hpp> +#include <iostream> + +#ifdef ASIO_HAS_POSIX_STREAM_DESCRIPTOR + +int main() +{ + asio::io_context ctx; + + asio::posix::stream_descriptor in(ctx, ::dup(STDIN_FILENO)); + asio::steady_timer timer(ctx, std::chrono::seconds(5)); + + char data[1024]; + + asio::experimental::make_parallel_group( + [&](auto token) + { + return in.async_read_some(asio::buffer(data), token); + }, + [&](auto token) + { + return timer.async_wait(token); + } + ).async_wait( + asio::experimental::wait_for_all(), + []( + std::array<std::size_t, 2> completion_order, + std::error_code ec1, std::size_t n1, + std::error_code ec2 + ) + { + switch (completion_order[0]) + { + case 0: + { + std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n"; + } + break; + case 1: + { + std::cout << "timer finished: " << ec2 << "\n"; + } + break; + } + } + ); + + ctx.run(); +} + +#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +int main() {} +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) diff --git a/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_one.cpp b/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_one.cpp new file mode 100644 index 00000000000..7b25e26d678 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_one.cpp @@ -0,0 +1,64 @@ +// +// wait_for_one.cpp +// ~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <asio/experimental/parallel_group.hpp> +#include <iostream> + +#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + +int main() +{ + asio::io_context ctx; + + asio::posix::stream_descriptor in(ctx, ::dup(STDIN_FILENO)); + asio::steady_timer timer(ctx, std::chrono::seconds(5)); + + char data[1024]; + + asio::experimental::make_parallel_group( + [&](auto token) + { + return in.async_read_some(asio::buffer(data), token); + }, + [&](auto token) + { + return timer.async_wait(token); + } + ).async_wait( + asio::experimental::wait_for_one(), + []( + std::array<std::size_t, 2> completion_order, + std::error_code ec1, std::size_t n1, + std::error_code ec2 + ) + { + switch (completion_order[0]) + { + case 0: + { + std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n"; + } + break; + case 1: + { + std::cout << "timer finished: " << ec2 << "\n"; + } + break; + } + } + ); + + ctx.run(); +} + +#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +int main() {} +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) diff --git a/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_one_error.cpp b/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_one_error.cpp new file mode 100644 index 00000000000..c157d0b3355 --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_one_error.cpp @@ -0,0 +1,64 @@ +// +// wait_for_one_error.cpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <asio/experimental/parallel_group.hpp> +#include <iostream> + +#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + +int main() +{ + asio::io_context ctx; + + asio::posix::stream_descriptor in(ctx, ::dup(STDIN_FILENO)); + asio::steady_timer timer(ctx, std::chrono::seconds(5)); + + char data[1024]; + + asio::experimental::make_parallel_group( + [&](auto token) + { + return in.async_read_some(asio::buffer(data), token); + }, + [&](auto token) + { + return timer.async_wait(token); + } + ).async_wait( + asio::experimental::wait_for_one_error(), + []( + std::array<std::size_t, 2> completion_order, + std::error_code ec1, std::size_t n1, + std::error_code ec2 + ) + { + switch (completion_order[0]) + { + case 0: + { + std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n"; + } + break; + case 1: + { + std::cout << "timer finished: " << ec2 << "\n"; + } + break; + } + } + ); + + ctx.run(); +} + +#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +int main() {} +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) diff --git a/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_one_success.cpp b/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_one_success.cpp new file mode 100644 index 00000000000..a328600a9fc --- /dev/null +++ b/3rdparty/asio/src/examples/cpp14/parallel_group/wait_for_one_success.cpp @@ -0,0 +1,64 @@ +// +// wait_for_one_error.cpp +// ~~~~~~~~~~~~~~~~~~~~~~ +// +// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#include <asio.hpp> +#include <asio/experimental/parallel_group.hpp> +#include <iostream> + +#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) + +int main() +{ + asio::io_context ctx; + + asio::posix::stream_descriptor in(ctx, ::dup(STDIN_FILENO)); + asio::steady_timer timer(ctx, std::chrono::seconds(5)); + + char data[1024]; + + asio::experimental::make_parallel_group( + [&](auto token) + { + return in.async_read_some(asio::buffer(data), token); + }, + [&](auto token) + { + return timer.async_wait(token); + } + ).async_wait( + asio::experimental::wait_for_one_success(), + []( + std::array<std::size_t, 2> completion_order, + std::error_code ec1, std::size_t n1, + std::error_code ec2 + ) + { + switch (completion_order[0]) + { + case 0: + { + std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n"; + } + break; + case 1: + { + std::cout << "timer finished: " << ec2 << "\n"; + } + break; + } + } + ); + + ctx.run(); +} + +#else // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) +int main() {} +#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) |